| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- namespace LocalizationTool.Services
- {
- /// <summary>语言条目:系统代码 / 显示名 / 中文名 / 百度翻译代码 的映射。</summary>
- public class LanguageEntry
- {
- /// <summary>系统语言代码(= .dat 文件名 / 语言包 LanguageCode)。主流语言为 BCP 47(如 ja-JP),小众语言直接使用百度代码。</summary>
- public string Code { get; set; }
- /// <summary>显示名(主流语言为本地名,小众语言为中文名)。</summary>
- public string Name { get; set; }
- /// <summary>中文名,如 "日语"。</summary>
- public string ChineseName { get; set; }
- /// <summary>百度翻译 API 的语言代码,如 "jp"。</summary>
- public string BaiduCode { get; set; }
- /// <summary>百度是否支持该语言的自动语种检测。</summary>
- public bool SupportsDetect { get; set; }
- /// <summary>下拉框显示文本(显示名与中文名相同时不重复)。</summary>
- public string Display =>
- string.Equals(Name, ChineseName, StringComparison.Ordinal)
- ? $"{Name} ({Code})"
- : $"{Name} ({Code}) —— {ChineseName}";
- }
- /// <summary>
- /// 语言映射目录:系统语言代码 ↔ 百度翻译代码 的全量对照表。
- /// 数据来源:百度翻译开放平台官方语言列表(https://fanyi-api.baidu.com/doc/21 附录)。
- /// 添加语言时从这里展开选择;翻译时由 GetBaiduCode 自动映射为百度的字段。
- /// </summary>
- public static class LanguageCatalog
- {
- /// <summary>
- /// 百度全量语言原始数据:百度码 | 中文名 | 支持语种检测。
- /// ("auto 自动检测"不属于可新增的翻译目标语言,未列入。)
- /// </summary>
- private static readonly string[] BaiduRaw = new[]
- {
- // A
- "ara|阿拉伯语|是", "gle|爱尔兰语|是", "oci|奥克语|是",
- "alb|阿尔巴尼亚语|是","arq|阿尔及利亚阿拉伯语|否","aka|阿肯语|否",
- "arg|阿拉贡语|否", "amh|阿姆哈拉语|是", "asm|阿萨姆语|是",
- "aym|艾马拉语|否", "aze|阿塞拜疆语|是", "ast|阿斯图里亚斯语|是",
- "oss|奥塞梯语|否", "est|爱沙尼亚语|是", "oji|奥杰布瓦语|否",
- "ori|奥里亚语|是", "orm|奥罗莫语|否",
- // B
- "pl|波兰语|是", "per|波斯语|是", "bre|布列塔尼语|是",
- "bak|巴什基尔语|否", "baq|巴斯克语|是", "pot|巴西葡萄牙语|否",
- "bel|白俄罗斯语|是", "ber|柏柏尔语|是", "pam|邦板牙语|否",
- "bul|保加利亚语|是", "sme|北方萨米语|否", "ped|北索托语|否",
- "bem|本巴语|否", "bli|比林语|否", "bis|比斯拉马语|否",
- "bal|俾路支语|否", "ice|冰岛语|是", "bos|波斯尼亚语|是",
- "bho|博杰普尔语|否",
- // C
- "chv|楚瓦什语|否", "tso|聪加语|否",
- // D
- "dan|丹麦语|是", "de|德语|是", "tat|鞑靼语|是",
- "sha|掸语|否", "tet|德顿语|否", "div|迪维希语|否",
- "log|低地德语|是",
- // E
- "ru|俄语|是",
- // F
- "fra|法语|是", "fil|菲律宾语|是", "fin|芬兰语|是",
- "san|梵语|否", "fri|弗留利语|否", "ful|富拉尼语|否",
- "fao|法罗语|否",
- // G
- "gla|盖尔语|否", "kon|刚果语|否", "ups|高地索布语|否",
- "hkm|高棉语|是", "kal|格陵兰语|否", "geo|格鲁吉亚语|是",
- "guj|古吉拉特语|是", "gra|古希腊语|否", "eno|古英语|否",
- "grn|瓜拉尼语|否",
- // H
- "kor|韩语|是", "nl|荷兰语|是", "hup|胡帕语|否",
- "hak|哈卡钦语|否", "ht|海地语|否", "mot|黑山语|否",
- "hau|豪萨语|否",
- // J
- "kir|吉尔吉斯语|否", "glg|加利西亚语|是", "frn|加拿大法语|否",
- "cat|加泰罗尼亚语|是","cs|捷克语|是",
- // K
- "kab|卡拜尔语|是", "kan|卡纳达语|是", "kau|卡努里语|否",
- "kah|卡舒比语|否", "cor|康瓦尔语|否", "xho|科萨语|是",
- "cos|科西嘉语|否", "cre|克里克语|否", "cri|克里米亚鞑靼语|否",
- "kli|克林贡语|否", "hrv|克罗地亚语|是", "que|克丘亚语|否",
- "kas|克什米尔语|否", "kok|孔卡尼语|否", "kur|库尔德语|是",
- // L
- "lat|拉丁语|是", "lao|老挝语|否", "rom|罗马尼亚语|是",
- "lag|拉特加莱语|否", "lav|拉脱维亚语|是", "lim|林堡语|否",
- "lin|林加拉语|否", "lug|卢干达语|否", "ltz|卢森堡语|否",
- "ruy|卢森尼亚语|否", "kin|卢旺达语|是", "lit|立陶宛语|是",
- "roh|罗曼什语|否", "ro|罗姆语|否", "loj|逻辑语|否",
- // M
- "may|马来语|是", "bur|缅甸语|是", "mar|马拉地语|否",
- "mg|马拉加斯语|是", "mal|马拉雅拉姆语|是", "mac|马其顿语|是",
- "mah|马绍尔语|否", "mai|迈蒂利语|是", "glv|曼克斯语|否",
- "mau|毛里求斯克里奥尔语|否","mao|毛利语|否", "ben|孟加拉语|是",
- "mlt|马耳他语|是", "hmn|苗语|否",
- // N
- "nor|挪威语|是", "nea|那不勒斯语|否", "nbl|南恩德贝莱语|否",
- "afr|南非荷兰语|是", "sot|南索托语|否", "nep|尼泊尔语|是",
- // P
- "pt|葡萄牙语|是", "pan|旁遮普语|是", "pap|帕皮阿门托语|否",
- "pus|普什图语|否",
- // Q
- "nya|齐切瓦语|否", "twi|契维语|否", "chr|切罗基语|否",
- // R
- "jp|日语|是", "swe|瑞典语|是",
- // S
- "srd|萨丁尼亚语|否", "sm|萨摩亚语|否", "sec|塞尔维亚-克罗地亚语|否",
- "srp|塞尔维亚语|是", "sol|桑海语|否", "sin|僧伽罗语|是",
- "epo|世界语|是", "nob|书面挪威语|是", "sk|斯洛伐克语|是",
- "slo|斯洛文尼亚语|是","swa|斯瓦希里语|是", "src|塞尔维亚语(西里尔)|否",
- "som|索马里语|是", "sco|苏格兰语|否",
- // T
- "th|泰语|是", "tr|土耳其语|是", "tgk|塔吉克语|是",
- "tam|泰米尔语|是", "tgl|他加禄语|是", "tir|提格利尼亚语|否",
- "tel|泰卢固语|是", "tua|突尼斯阿拉伯语|否","tuk|土库曼语|否",
- // W
- "ukr|乌克兰语|是", "wln|瓦隆语|是", "wel|威尔士语|是",
- "ven|文达语|否", "wol|沃洛夫语|否", "urd|乌尔都语|是",
- // X
- "spa|西班牙语|是", "heb|希伯来语|是", "el|希腊语|是",
- "hu|匈牙利语|是", "fry|西弗里斯语|是", "sil|西里西亚语|否",
- "hil|希利盖农语|否", "los|下索布语|否", "haw|夏威夷语|否",
- "nno|新挪威语|是", "nqo|西非书面语|否", "snd|信德语|否",
- "sna|修纳语|否", "ceb|宿务语|否", "syr|叙利亚语|否",
- "sun|巽他语|否",
- // Y
- "en|英语|是", "hi|印地语|是", "id|印尼语|是",
- "it|意大利语|是", "vie|越南语|是", "yid|意第绪语|否",
- "ina|因特语|否", "ach|亚齐语|否", "ing|印古什语|否",
- "ibo|伊博语|否", "ido|伊多语|否", "yor|约鲁巴语|否",
- "arm|亚美尼亚语|是", "iku|伊努克提图特语|否",
- // Z
- "zh|中文(简体)|是", "cht|中文(繁体)|是", "wyw|中文(文言文)|是",
- "yue|中文(粤语)|是", "zaz|扎扎其语|否", "frm|中古法语|否",
- "zul|祖鲁语|否", "jav|爪哇语|否",
- };
- /// <summary>
- /// 主流语言的系统代码与本地显示名(百度码 → 系统码 + 本地名)。
- /// 未在此表中的语言:系统码直接用百度码,显示名用中文名。
- /// </summary>
- private static readonly Dictionary<string, (string Code, string Name)> Preferred =
- new Dictionary<string, (string, string)>(StringComparer.OrdinalIgnoreCase)
- {
- ["zh"] = ("zh-CN", "简体中文"),
- ["cht"] = ("zh-TW", "繁體中文"),
- ["yue"] = ("yue", "粵語"),
- ["en"] = ("en-US", "English"),
- ["jp"] = ("ja-JP", "日本語"),
- ["kor"] = ("ko-KR", "한국어"),
- ["fra"] = ("fr-FR", "Français"),
- ["spa"] = ("es-ES", "Español"),
- ["de"] = ("de-DE", "Deutsch"),
- ["it"] = ("it-IT", "Italiano"),
- ["pt"] = ("pt-BR", "Português"),
- ["ru"] = ("ru-RU", "Русский"),
- ["ara"] = ("ar-SA", "العربية"),
- ["th"] = ("th-TH", "ไทย"),
- ["nl"] = ("nl-NL", "Nederlands"),
- ["el"] = ("el-GR", "Ελληνικά"),
- ["pl"] = ("pl-PL", "Polski"),
- ["bul"] = ("bg-BG", "Български"),
- ["est"] = ("et-EE", "Eesti"),
- ["dan"] = ("da-DK", "Dansk"),
- ["fin"] = ("fi-FI", "Suomi"),
- ["cs"] = ("cs-CZ", "Čeština"),
- ["rom"] = ("ro-RO", "Română"),
- ["slo"] = ("sl-SI", "Slovenščina"),
- ["swe"] = ("sv-SE", "Svenska"),
- ["hu"] = ("hu-HU", "Magyar"),
- ["vie"] = ("vi-VN", "Tiếng Việt"),
- ["tr"] = ("tr-TR", "Türkçe"),
- ["id"] = ("id-ID", "Bahasa Indonesia"),
- ["may"] = ("ms-MY", "Bahasa Melayu"),
- ["ukr"] = ("uk-UA", "Українська"),
- ["heb"] = ("he-IL", "עברית"),
- ["ice"] = ("is-IS", "Íslenska"),
- ["lav"] = ("lv-LV", "Latviešu"),
- ["lit"] = ("lt-LT", "Lietuvių"),
- ["hrv"] = ("hr-HR", "Hrvatski"),
- ["srp"] = ("sr-RS", "Srpski"),
- ["sk"] = ("sk-SK", "Slovenčina"),
- ["alb"] = ("sq-AL", "Shqip"),
- ["aze"] = ("az-AZ", "Azərbaycanca"),
- ["geo"] = ("ka-GE", "ქართული"),
- ["cat"] = ("ca-ES", "Català"),
- ["glg"] = ("gl-ES", "Galego"),
- ["baq"] = ("eu-ES", "Euskara"),
- ["mlt"] = ("mt-MT", "Malti"),
- ["afr"] = ("af-ZA", "Afrikaans"),
- ["epo"] = ("eo", "Esperanto"),
- ["wel"] = ("cy-GB", "Cymraeg"),
- ["fil"] = ("fil-PH","Filipino"),
- ["ben"] = ("bn-IN", "বাংলা"),
- ["tam"] = ("ta-IN", "தமிழ்"),
- ["tel"] = ("te-IN", "తెలుగు"),
- ["pan"] = ("pa-IN", "ਪੰਜਾਬੀ"),
- ["mar"] = ("mr-IN", "मराठी"),
- ["mal"] = ("ml-IN", "മലയാളം"),
- ["kan"] = ("kn-IN", "ಕನ್ನಡ"),
- ["guj"] = ("gu-IN", "ગુજરાતી"),
- ["hi"] = ("hi-IN", "हिन्दी"),
- ["urd"] = ("ur-PK", "اردو"),
- ["per"] = ("fa-IR", "فارسی"),
- ["bur"] = ("my-MM", "မြန်မာ"),
- ["nep"] = ("ne-NP", "नेपाली"),
- ["sin"] = ("si-LK", "සිංහල"),
- ["swa"] = ("sw-KE", "Kiswahili"),
- ["amh"] = ("am-ET", "አማርኛ"),
- ["kur"] = ("ku", "Kurdî"),
- ["lat"] = ("la", "Latine"),
- ["san"] = ("sa", "संस्कृतम्"),
- };
- /// <summary>全量语言目录(已按系统码排序,主流语言在前风格由排序自然决定)。</summary>
- public static readonly List<LanguageEntry> All = Build();
- private static List<LanguageEntry> Build()
- {
- var list = new List<LanguageEntry>();
- var seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
- foreach (var line in BaiduRaw)
- {
- var parts = line.Split('|');
- if (parts.Length < 3) continue;
- var baidu = parts[0].Trim();
- var cn = parts[1].Trim();
- var detect = string.Equals(parts[2].Trim(), "是", StringComparison.Ordinal);
- // 去重(官方表偶有重复行,如斯洛文尼亚语出现两次)
- if (!seen.Add(baidu)) continue;
- var hasPreferred = Preferred.TryGetValue(baidu, out var pref);
- var code = hasPreferred ? pref.Code : baidu;
- var name = hasPreferred ? pref.Name : cn;
- list.Add(new LanguageEntry
- {
- Code = code,
- Name = name,
- ChineseName = cn,
- BaiduCode = baidu,
- SupportsDetect = detect,
- });
- }
- // 主流语言排前面(系统码精确排序:zh 系 → 常见 → 其余按码)
- list.Sort((a, b) =>
- {
- int Rank(LanguageEntry e)
- {
- switch (e.BaiduCode)
- {
- case "zh": return 0;
- case "cht": return 1;
- case "en": return 2;
- case "jp": return 3;
- case "kor": return 4;
- default: return 10;
- }
- }
- var r = Rank(a).CompareTo(Rank(b));
- return r != 0 ? r : string.CompareOrdinal(a.Code, b.Code);
- });
- return list;
- }
- /// <summary>
- /// 系统语言代码 → 百度翻译代码。
- /// 优先精确匹配 Code;其次匹配主代码(如 "ja-XX" → ja-JP → jp);都没有则返回主代码本身兜底。
- /// </summary>
- public static string GetBaiduCode(string langCode)
- {
- if (string.IsNullOrWhiteSpace(langCode))
- return "zh";
- var code = langCode.Trim();
- // 1) 精确匹配
- var exact = All.FirstOrDefault(e => string.Equals(e.Code, code, StringComparison.OrdinalIgnoreCase));
- if (exact != null) return exact.BaiduCode;
- // 2) 主代码匹配("ja-XX" 之类非标准区域码也能命中)
- var main = code.Split('-')[0].ToLowerInvariant();
- var byMain = All.FirstOrDefault(e =>
- string.Equals(e.Code.Split('-')[0], main, StringComparison.OrdinalIgnoreCase));
- if (byMain != null) return byMain.BaiduCode;
- // 3) 兜底:直接给主代码(也许百度认识)
- return main;
- }
- /// <summary>按系统代码查找条目。</summary>
- public static LanguageEntry Find(string langCode) =>
- All.FirstOrDefault(e => string.Equals(e.Code, langCode, StringComparison.OrdinalIgnoreCase));
- }
- }
|