多语言开发:Locale 语言代码规范与完整列表(Java / C++ / C# / JavaScript)

语言选择列表看似简单,实际很容易在多个技术栈之间出现分叉:同一种语言用了不同代码、语言名大小写不一致,或者把标准库生成的名称直接当成产品文案。

本文给出一套可落地的跨语言约定,并整理了一份包含 79 项的参考目录。它适用于 Java、C++、C#、JavaScript/TypeScript 等客户端、服务端和工具程序。核心目标是:内部代码稳定、对外接口符合标准、UI 显示一致。

1. 如何理解语言代码

本文示例中的内部语言代码采用:

language_REGION

例如:

  • en_US:英语 + 美国
  • pt_BR:葡萄牙语 + 巴西
  • zh_HK:中文 + 香港

约定如下:

  • language 使用小写语言子标签,主要依据 IANA Language Subtag Registry。
  • REGION 使用大写地区子标签,通常对应 ISO 3166-1 两位地区代码,并在 IANA 注册表中登记。
  • 下划线 _ 可以作为应用内部的稳定格式;严格的 BCP 47 写法使用连字符,例如 fil-PH。内部存储与外部接口应明确分层,不要在同一数据域中混用两种格式。
  • 语言代码用于程序识别,显示名称用于 UI 展示,两者必须分别按各自规则维护。

2. 四个容易混淆的代码

原代码 建议写法 调整依据
iw_IL he_IL iw 是希伯来语的旧代码,IANA 的首选值是 he。
in_ID id_ID in 是印度尼西亚语的旧代码,IANA 的首选值是 id。
tl_PH fil_PH tl 是仍然有效的 Tagalog 代码,并非废弃代码;当名称和产品语义是 Filipino 时才应使用 fil。
my_ZG my_MM 如果原意是“缅甸语 + 缅甸地区”,应使用已注册地区代码 MM;ZG 不是地区子标签。若 ZG 原本指 Zawgyi 编码,则应把编码方式建模为独立字段,不能用地区位代替。

如果现有数据没有兼容负担,建议直接使用建议写法,不再保留旧代码别名。如果已经存在历史配置、数据库记录或外部调用方,则应先完成数据迁移,并在明确的过渡期内提供兼容映射。

需要注意,第三方翻译 API 可能仍要求 tl 等自定义参数。这类值属于供应商接口映射,不应反向替代应用内部使用的 fil_PH。

3. 显示名称规则

每项语言包含两个显示名称:

  1. 中文名称:供中文界面或管理场景使用。
  2. 本地名称:使用该语言自身的文字和常见自称形式。

统一规则:

  • 以 Unicode CLDR 的现代语言名称和地区名称为主要参考。
  • 同一语言存在多个地区版本时,在名称中明确地区,例如 English (United States)、Français (Canada)。
  • 独立出现在语言选择列表中的名称,统一采用适合 UI 标签的首字母形式,例如 Magyar、Italiano (Italia)。
  • 语言学上,匈牙利语 magyar、意大利语 lingua italiana 在普通句子中使用小写可以成立;但产品语言列表需要一致、明确且便于区分地区版本,因此本文采用规范表中的 UI 写法。
  • 不把英文翻译冒充本地名称,也不混用语言名、国名和形容词。
  • 乌兹别克语在本文参考目录中使用西里尔字母名称 Ўзбекча;如果产品采用拉丁字母版本,应在自己的语言资源策略中明确选择,避免两种写法随机出现。

4. 参考语言目录

代码 中文名称 本地名称
zh_CN 简体中文 简体中文
zh_TW 繁体中文(台湾) 繁體中文(台灣)
zh_HK 繁体中文(香港) 繁體中文(香港)
nl_NL 荷兰语 Nederlands (Nederland)
nl_BE 荷兰语(比利时) Nederlands (België)
en_US 英语(美国) English (United States)
en_AU 英语(澳大利亚) English (Australia)
en_CA 英语(加拿大) English (Canada)
en_IN 英语(印度) English (India)
en_IE 英语(爱尔兰) English (Ireland)
en_NZ 英语(新西兰) English (New Zealand)
en_SG 英语(新加坡) English (Singapore)
en_ZA 英语(南非) English (South Africa)
en_GB 英语(英国) English (United Kingdom)
fr_FR 法语 Français (France)
fr_BE 法语(比利时) Français (Belgique)
fr_CA 法语(加拿大) Français (Canada)
fr_CH 法语(瑞士) Français (Suisse)
de_DE 德语 Deutsch (Deutschland)
de_LI 德语(列支敦斯登) Deutsch (Liechtenstein)
de_AT 德语(奥地利) Deutsch (Österreich)
de_CH 德语(瑞士) Deutsch (Schweiz)
it_IT 意大利语 Italiano (Italia)
it_CH 意大利语(瑞士) Italiano (Svizzera)
pt_BR 葡萄牙语(巴西) Português (Brasil)
pt_PT 葡萄牙语 Português (Portugal)
es_ES 西班牙语 Español (España)
es_US 西班牙语(美国) Español (Estados Unidos)
bn_BD 孟加拉语 বাংলা (বাংলাদেশ)
bn_IN 孟加拉语(印度) বাংলা (ভারত)
hr_HR 克罗地亚语 Hrvatski
cs_CZ 捷克语 Čeština
da_DK 丹麦语 Dansk
el_GR 希腊语 Ελληνικά
he_IL 希伯来语(以色列) עברית
hi_IN 印地语 हिन्दी
hu_HU 匈牙利语 Magyar
id_ID 印度尼西亚语 Bahasa Indonesia
ja_JP 日语 日本語
ko_KR 韩语 한국어
ms_MY 马来语 Melayu
fa_IR 波斯语 فارسی
pl_PL 波兰语 Polski
ro_RO 罗马尼亚语 Română
ru_RU 俄语 Русский
sr_RS 塞尔维亚语 Српски
sv_SE 瑞典语 Svenska
th_TH 泰语 ไทย
tr_TR 土耳其语 Türkçe
ur_PK 乌尔都语 اردو
vi_VN 越南语 Tiếng Việt
ca_ES 加泰罗尼亚语(西班牙) Català
lv_LV 拉脱维亚语 Latviešu
lt_LT 立陶宛语 Lietuvių
nb_NO 书面挪威语 Norsk bokmål
sk_SK 斯洛伐克语 Slovenčina
sl_SI 斯洛文尼亚语 Slovenščina
bg_BG 保加利亚语 Български
uk_UA 乌克兰语 Українська
fil_PH 菲律宾语 Filipino
fi_FI 芬兰语 Suomi
af_ZA 南非荷兰语 Afrikaans
rm_CH 罗曼什语(瑞士) Rumantsch
km_KH 高棉语 ខ្មែរ
my_MM 缅甸语 မြန်မာ
am_ET 阿姆哈拉语(埃塞俄比亚) አማርኛ
be_BY 白俄罗斯语 Беларуская
et_EE 爱沙尼亚语 Eesti
sw_TZ 斯瓦希里语(坦桑尼亚) Kiswahili
zu_ZA 祖鲁语(南非) IsiZulu
az_AZ 阿塞拜疆语 Azərbaycan
hy_AM 亚美尼亚语(亚美尼亚) Հայերեն
ka_GE 格鲁吉亚语(格鲁吉亚) ქართული
lo_LA 老挝语(老挝) ລາວ
mn_MN 蒙古语 Монгол
ne_NP 尼泊尔语 नेपाली
kk_KZ 哈萨克语 Қазақ тілі
si_LK 僧伽罗语(斯里兰卡) සිංහල
uz_UZ 乌兹别克语 Ўзбекча

5. 可直接复制的完整代码

下面的 JSON、Java、C++、C# 和 JavaScript/TypeScript 示例都包含第 4 节的完整 79 项,字段、内容和顺序保持一致。读者只需选择自己的技术栈并整段复制,不需要再从 Markdown 表格逐条转换。

所有实现都遵守同一数据契约:

字段 含义 示例
code 应用内部稳定代码 fil_PH
zhName 中文显示名称 菲律宾语
nativeName 本地语言显示名称 Filipino

共同边界规则:

  • 配置文件、数据库、文件名和系统间通信保存 language_REGION,例如 fil_PH。
  • 调用要求 BCP 47 的标准库或 Web API 时,在调用边界将 _ 转为 -,例如 fil_PH → fil-PH。
  • 不要把整个代码统一转为大写或小写;语言部分小写,地区部分大写。
  • UI 直接使用目录中的 zhName 或 nativeName,不要依赖不同版本的操作系统、JDK、浏览器或 .NET 动态生成产品名称。
  • 第三方翻译 API 的语言参数维护独立映射,不要反向污染应用内部代码。
  • 源码、JSON、数据库和网络传输统一使用 Unicode;新数据文件优先使用 UTF-8。

5.1 JSON

可将下面的内容直接保存为 language-catalog.json,作为不同技术栈共享的真值源:

[
  { "code": "zh_CN", "zhName": "简体中文", "nativeName": "简体中文" },
  { "code": "zh_TW", "zhName": "繁体中文(台湾)", "nativeName": "繁體中文(台灣)" },
  { "code": "zh_HK", "zhName": "繁体中文(香港)", "nativeName": "繁體中文(香港)" },
  { "code": "nl_NL", "zhName": "荷兰语", "nativeName": "Nederlands (Nederland)" },
  { "code": "nl_BE", "zhName": "荷兰语(比利时)", "nativeName": "Nederlands (België)" },
  { "code": "en_US", "zhName": "英语(美国)", "nativeName": "English (United States)" },
  { "code": "en_AU", "zhName": "英语(澳大利亚)", "nativeName": "English (Australia)" },
  { "code": "en_CA", "zhName": "英语(加拿大)", "nativeName": "English (Canada)" },
  { "code": "en_IN", "zhName": "英语(印度)", "nativeName": "English (India)" },
  { "code": "en_IE", "zhName": "英语(爱尔兰)", "nativeName": "English (Ireland)" },
  { "code": "en_NZ", "zhName": "英语(新西兰)", "nativeName": "English (New Zealand)" },
  { "code": "en_SG", "zhName": "英语(新加坡)", "nativeName": "English (Singapore)" },
  { "code": "en_ZA", "zhName": "英语(南非)", "nativeName": "English (South Africa)" },
  { "code": "en_GB", "zhName": "英语(英国)", "nativeName": "English (United Kingdom)" },
  { "code": "fr_FR", "zhName": "法语", "nativeName": "Français (France)" },
  { "code": "fr_BE", "zhName": "法语(比利时)", "nativeName": "Français (Belgique)" },
  { "code": "fr_CA", "zhName": "法语(加拿大)", "nativeName": "Français (Canada)" },
  { "code": "fr_CH", "zhName": "法语(瑞士)", "nativeName": "Français (Suisse)" },
  { "code": "de_DE", "zhName": "德语", "nativeName": "Deutsch (Deutschland)" },
  { "code": "de_LI", "zhName": "德语(列支敦斯登)", "nativeName": "Deutsch (Liechtenstein)" },
  { "code": "de_AT", "zhName": "德语(奥地利)", "nativeName": "Deutsch (Österreich)" },
  { "code": "de_CH", "zhName": "德语(瑞士)", "nativeName": "Deutsch (Schweiz)" },
  { "code": "it_IT", "zhName": "意大利语", "nativeName": "Italiano (Italia)" },
  { "code": "it_CH", "zhName": "意大利语(瑞士)", "nativeName": "Italiano (Svizzera)" },
  { "code": "pt_BR", "zhName": "葡萄牙语(巴西)", "nativeName": "Português (Brasil)" },
  { "code": "pt_PT", "zhName": "葡萄牙语", "nativeName": "Português (Portugal)" },
  { "code": "es_ES", "zhName": "西班牙语", "nativeName": "Español (España)" },
  { "code": "es_US", "zhName": "西班牙语(美国)", "nativeName": "Español (Estados Unidos)" },
  { "code": "bn_BD", "zhName": "孟加拉语", "nativeName": "বাংলা (বাংলাদেশ)" },
  { "code": "bn_IN", "zhName": "孟加拉语(印度)", "nativeName": "বাংলা (ভারত)" },
  { "code": "hr_HR", "zhName": "克罗地亚语", "nativeName": "Hrvatski" },
  { "code": "cs_CZ", "zhName": "捷克语", "nativeName": "Čeština" },
  { "code": "da_DK", "zhName": "丹麦语", "nativeName": "Dansk" },
  { "code": "el_GR", "zhName": "希腊语", "nativeName": "Ελληνικά" },
  { "code": "he_IL", "zhName": "希伯来语(以色列)", "nativeName": "עברית" },
  { "code": "hi_IN", "zhName": "印地语", "nativeName": "हिन्दी" },
  { "code": "hu_HU", "zhName": "匈牙利语", "nativeName": "Magyar" },
  { "code": "id_ID", "zhName": "印度尼西亚语", "nativeName": "Bahasa Indonesia" },
  { "code": "ja_JP", "zhName": "日语", "nativeName": "日本語" },
  { "code": "ko_KR", "zhName": "韩语", "nativeName": "한국어" },
  { "code": "ms_MY", "zhName": "马来语", "nativeName": "Melayu" },
  { "code": "fa_IR", "zhName": "波斯语", "nativeName": "فارسی" },
  { "code": "pl_PL", "zhName": "波兰语", "nativeName": "Polski" },
  { "code": "ro_RO", "zhName": "罗马尼亚语", "nativeName": "Română" },
  { "code": "ru_RU", "zhName": "俄语", "nativeName": "Русский" },
  { "code": "sr_RS", "zhName": "塞尔维亚语", "nativeName": "Српски" },
  { "code": "sv_SE", "zhName": "瑞典语", "nativeName": "Svenska" },
  { "code": "th_TH", "zhName": "泰语", "nativeName": "ไทย" },
  { "code": "tr_TR", "zhName": "土耳其语", "nativeName": "Türkçe" },
  { "code": "ur_PK", "zhName": "乌尔都语", "nativeName": "اردو" },
  { "code": "vi_VN", "zhName": "越南语", "nativeName": "Tiếng Việt" },
  { "code": "ca_ES", "zhName": "加泰罗尼亚语(西班牙)", "nativeName": "Català" },
  { "code": "lv_LV", "zhName": "拉脱维亚语", "nativeName": "Latviešu" },
  { "code": "lt_LT", "zhName": "立陶宛语", "nativeName": "Lietuvių" },
  { "code": "nb_NO", "zhName": "书面挪威语", "nativeName": "Norsk bokmål" },
  { "code": "sk_SK", "zhName": "斯洛伐克语", "nativeName": "Slovenčina" },
  { "code": "sl_SI", "zhName": "斯洛文尼亚语", "nativeName": "Slovenščina" },
  { "code": "bg_BG", "zhName": "保加利亚语", "nativeName": "Български" },
  { "code": "uk_UA", "zhName": "乌克兰语", "nativeName": "Українська" },
  { "code": "fil_PH", "zhName": "菲律宾语", "nativeName": "Filipino" },
  { "code": "fi_FI", "zhName": "芬兰语", "nativeName": "Suomi" },
  { "code": "af_ZA", "zhName": "南非荷兰语", "nativeName": "Afrikaans" },
  { "code": "rm_CH", "zhName": "罗曼什语(瑞士)", "nativeName": "Rumantsch" },
  { "code": "km_KH", "zhName": "高棉语", "nativeName": "ខ្មែរ" },
  { "code": "my_MM", "zhName": "缅甸语", "nativeName": "မြန်မာ" },
  { "code": "am_ET", "zhName": "阿姆哈拉语(埃塞俄比亚)", "nativeName": "አማርኛ" },
  { "code": "be_BY", "zhName": "白俄罗斯语", "nativeName": "Беларуская" },
  { "code": "et_EE", "zhName": "爱沙尼亚语", "nativeName": "Eesti" },
  { "code": "sw_TZ", "zhName": "斯瓦希里语(坦桑尼亚)", "nativeName": "Kiswahili" },
  { "code": "zu_ZA", "zhName": "祖鲁语(南非)", "nativeName": "IsiZulu" },
  { "code": "az_AZ", "zhName": "阿塞拜疆语", "nativeName": "Azərbaycan" },
  { "code": "hy_AM", "zhName": "亚美尼亚语(亚美尼亚)", "nativeName": "Հայերեն" },
  { "code": "ka_GE", "zhName": "格鲁吉亚语(格鲁吉亚)", "nativeName": "ქართული" },
  { "code": "lo_LA", "zhName": "老挝语(老挝)", "nativeName": "ລາວ" },
  { "code": "mn_MN", "zhName": "蒙古语", "nativeName": "Монгол" },
  { "code": "ne_NP", "zhName": "尼泊尔语", "nativeName": "नेपाली" },
  { "code": "kk_KZ", "zhName": "哈萨克语", "nativeName": "Қазақ тілі" },
  { "code": "si_LK", "zhName": "僧伽罗语(斯里兰卡)", "nativeName": "සිංහල" },
  { "code": "uz_UZ", "zhName": "乌兹别克语", "nativeName": "Ўзбекча" }
]

5.2 Java(Java 8+)

下面是一个完整、可独立保存的 Java 类,包含不可变语言列表、代码查找和 BCP 47 转换:

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;

public final class LanguageCatalog {
    public static final class LanguageOption {
        public final String code;
        public final String zhName;
        public final String nativeName;

        public LanguageOption(String code, String zhName, String nativeName) {
            this.code = code;
            this.zhName = zhName;
            this.nativeName = nativeName;
        }

        public String toLanguageTag() {
            return code.replace('_', '-');
        }

        public Locale toLocale() {
            return Locale.forLanguageTag(toLanguageTag());
        }

        public String displayName(boolean chineseUi) {
            return chineseUi ? zhName : nativeName;
        }
    }

    public static final List<LanguageOption> ALL =
        Collections.unmodifiableList(Arrays.asList(
            new LanguageOption("zh_CN", "简体中文", "简体中文"),
            new LanguageOption("zh_TW", "繁体中文(台湾)", "繁體中文(台灣)"),
            new LanguageOption("zh_HK", "繁体中文(香港)", "繁體中文(香港)"),
            new LanguageOption("nl_NL", "荷兰语", "Nederlands (Nederland)"),
            new LanguageOption("nl_BE", "荷兰语(比利时)", "Nederlands (België)"),
            new LanguageOption("en_US", "英语(美国)", "English (United States)"),
            new LanguageOption("en_AU", "英语(澳大利亚)", "English (Australia)"),
            new LanguageOption("en_CA", "英语(加拿大)", "English (Canada)"),
            new LanguageOption("en_IN", "英语(印度)", "English (India)"),
            new LanguageOption("en_IE", "英语(爱尔兰)", "English (Ireland)"),
            new LanguageOption("en_NZ", "英语(新西兰)", "English (New Zealand)"),
            new LanguageOption("en_SG", "英语(新加坡)", "English (Singapore)"),
            new LanguageOption("en_ZA", "英语(南非)", "English (South Africa)"),
            new LanguageOption("en_GB", "英语(英国)", "English (United Kingdom)"),
            new LanguageOption("fr_FR", "法语", "Français (France)"),
            new LanguageOption("fr_BE", "法语(比利时)", "Français (Belgique)"),
            new LanguageOption("fr_CA", "法语(加拿大)", "Français (Canada)"),
            new LanguageOption("fr_CH", "法语(瑞士)", "Français (Suisse)"),
            new LanguageOption("de_DE", "德语", "Deutsch (Deutschland)"),
            new LanguageOption("de_LI", "德语(列支敦斯登)", "Deutsch (Liechtenstein)"),
            new LanguageOption("de_AT", "德语(奥地利)", "Deutsch (Österreich)"),
            new LanguageOption("de_CH", "德语(瑞士)", "Deutsch (Schweiz)"),
            new LanguageOption("it_IT", "意大利语", "Italiano (Italia)"),
            new LanguageOption("it_CH", "意大利语(瑞士)", "Italiano (Svizzera)"),
            new LanguageOption("pt_BR", "葡萄牙语(巴西)", "Português (Brasil)"),
            new LanguageOption("pt_PT", "葡萄牙语", "Português (Portugal)"),
            new LanguageOption("es_ES", "西班牙语", "Español (España)"),
            new LanguageOption("es_US", "西班牙语(美国)", "Español (Estados Unidos)"),
            new LanguageOption("bn_BD", "孟加拉语", "বাংলা (বাংলাদেশ)"),
            new LanguageOption("bn_IN", "孟加拉语(印度)", "বাংলা (ভারত)"),
            new LanguageOption("hr_HR", "克罗地亚语", "Hrvatski"),
            new LanguageOption("cs_CZ", "捷克语", "Čeština"),
            new LanguageOption("da_DK", "丹麦语", "Dansk"),
            new LanguageOption("el_GR", "希腊语", "Ελληνικά"),
            new LanguageOption("he_IL", "希伯来语(以色列)", "עברית"),
            new LanguageOption("hi_IN", "印地语", "हिन्दी"),
            new LanguageOption("hu_HU", "匈牙利语", "Magyar"),
            new LanguageOption("id_ID", "印度尼西亚语", "Bahasa Indonesia"),
            new LanguageOption("ja_JP", "日语", "日本語"),
            new LanguageOption("ko_KR", "韩语", "한국어"),
            new LanguageOption("ms_MY", "马来语", "Melayu"),
            new LanguageOption("fa_IR", "波斯语", "فارسی"),
            new LanguageOption("pl_PL", "波兰语", "Polski"),
            new LanguageOption("ro_RO", "罗马尼亚语", "Română"),
            new LanguageOption("ru_RU", "俄语", "Русский"),
            new LanguageOption("sr_RS", "塞尔维亚语", "Српски"),
            new LanguageOption("sv_SE", "瑞典语", "Svenska"),
            new LanguageOption("th_TH", "泰语", "ไทย"),
            new LanguageOption("tr_TR", "土耳其语", "Türkçe"),
            new LanguageOption("ur_PK", "乌尔都语", "اردو"),
            new LanguageOption("vi_VN", "越南语", "Tiếng Việt"),
            new LanguageOption("ca_ES", "加泰罗尼亚语(西班牙)", "Català"),
            new LanguageOption("lv_LV", "拉脱维亚语", "Latviešu"),
            new LanguageOption("lt_LT", "立陶宛语", "Lietuvių"),
            new LanguageOption("nb_NO", "书面挪威语", "Norsk bokmål"),
            new LanguageOption("sk_SK", "斯洛伐克语", "Slovenčina"),
            new LanguageOption("sl_SI", "斯洛文尼亚语", "Slovenščina"),
            new LanguageOption("bg_BG", "保加利亚语", "Български"),
            new LanguageOption("uk_UA", "乌克兰语", "Українська"),
            new LanguageOption("fil_PH", "菲律宾语", "Filipino"),
            new LanguageOption("fi_FI", "芬兰语", "Suomi"),
            new LanguageOption("af_ZA", "南非荷兰语", "Afrikaans"),
            new LanguageOption("rm_CH", "罗曼什语(瑞士)", "Rumantsch"),
            new LanguageOption("km_KH", "高棉语", "ខ្មែរ"),
            new LanguageOption("my_MM", "缅甸语", "မြန်မာ"),
            new LanguageOption("am_ET", "阿姆哈拉语(埃塞俄比亚)", "አማርኛ"),
            new LanguageOption("be_BY", "白俄罗斯语", "Беларуская"),
            new LanguageOption("et_EE", "爱沙尼亚语", "Eesti"),
            new LanguageOption("sw_TZ", "斯瓦希里语(坦桑尼亚)", "Kiswahili"),
            new LanguageOption("zu_ZA", "祖鲁语(南非)", "IsiZulu"),
            new LanguageOption("az_AZ", "阿塞拜疆语", "Azərbaycan"),
            new LanguageOption("hy_AM", "亚美尼亚语(亚美尼亚)", "Հայերեն"),
            new LanguageOption("ka_GE", "格鲁吉亚语(格鲁吉亚)", "ქართული"),
            new LanguageOption("lo_LA", "老挝语(老挝)", "ລາວ"),
            new LanguageOption("mn_MN", "蒙古语", "Монгол"),
            new LanguageOption("ne_NP", "尼泊尔语", "नेपाली"),
            new LanguageOption("kk_KZ", "哈萨克语", "Қазақ тілі"),
            new LanguageOption("si_LK", "僧伽罗语(斯里兰卡)", "සිංහල"),
            new LanguageOption("uz_UZ", "乌兹别克语", "Ўзбекча")
        ));

    public static LanguageOption findByCode(String code) {
        for (LanguageOption option : ALL) {
            if (option.code.equals(code)) {
                return option;
            }
        }
        return null;
    }

    private LanguageCatalog() {
    }
}

调用示例:

LanguageCatalog.LanguageOption option =
    LanguageCatalog.findByCode("fil_PH");

if (option != null) {
    Locale locale = option.toLocale();          // fil-PH
    String uiText = option.displayName(false);  // Filipino
}

5.3 C++(C++11+)

下面的版本使用宽字符串保存显示名称,适合 Windows/MSVC,也避开了 C++20 中 u8"..." 变为 char8_t 后不能直接赋给 std::string 的差异:

#include <algorithm>
#include <cstddef>
#include <string>

struct LanguageOption {
    const char* code;
    const wchar_t* zhName;
    const wchar_t* nativeName;
};

static const LanguageOption kLanguages[] = {
    { "zh_CN", L"简体中文", L"简体中文" },
    { "zh_TW", L"繁体中文(台湾)", L"繁體中文(台灣)" },
    { "zh_HK", L"繁体中文(香港)", L"繁體中文(香港)" },
    { "nl_NL", L"荷兰语", L"Nederlands (Nederland)" },
    { "nl_BE", L"荷兰语(比利时)", L"Nederlands (België)" },
    { "en_US", L"英语(美国)", L"English (United States)" },
    { "en_AU", L"英语(澳大利亚)", L"English (Australia)" },
    { "en_CA", L"英语(加拿大)", L"English (Canada)" },
    { "en_IN", L"英语(印度)", L"English (India)" },
    { "en_IE", L"英语(爱尔兰)", L"English (Ireland)" },
    { "en_NZ", L"英语(新西兰)", L"English (New Zealand)" },
    { "en_SG", L"英语(新加坡)", L"English (Singapore)" },
    { "en_ZA", L"英语(南非)", L"English (South Africa)" },
    { "en_GB", L"英语(英国)", L"English (United Kingdom)" },
    { "fr_FR", L"法语", L"Français (France)" },
    { "fr_BE", L"法语(比利时)", L"Français (Belgique)" },
    { "fr_CA", L"法语(加拿大)", L"Français (Canada)" },
    { "fr_CH", L"法语(瑞士)", L"Français (Suisse)" },
    { "de_DE", L"德语", L"Deutsch (Deutschland)" },
    { "de_LI", L"德语(列支敦斯登)", L"Deutsch (Liechtenstein)" },
    { "de_AT", L"德语(奥地利)", L"Deutsch (Österreich)" },
    { "de_CH", L"德语(瑞士)", L"Deutsch (Schweiz)" },
    { "it_IT", L"意大利语", L"Italiano (Italia)" },
    { "it_CH", L"意大利语(瑞士)", L"Italiano (Svizzera)" },
    { "pt_BR", L"葡萄牙语(巴西)", L"Português (Brasil)" },
    { "pt_PT", L"葡萄牙语", L"Português (Portugal)" },
    { "es_ES", L"西班牙语", L"Español (España)" },
    { "es_US", L"西班牙语(美国)", L"Español (Estados Unidos)" },
    { "bn_BD", L"孟加拉语", L"বাংলা (বাংলাদেশ)" },
    { "bn_IN", L"孟加拉语(印度)", L"বাংলা (ভারত)" },
    { "hr_HR", L"克罗地亚语", L"Hrvatski" },
    { "cs_CZ", L"捷克语", L"Čeština" },
    { "da_DK", L"丹麦语", L"Dansk" },
    { "el_GR", L"希腊语", L"Ελληνικά" },
    { "he_IL", L"希伯来语(以色列)", L"עברית" },
    { "hi_IN", L"印地语", L"हिन्दी" },
    { "hu_HU", L"匈牙利语", L"Magyar" },
    { "id_ID", L"印度尼西亚语", L"Bahasa Indonesia" },
    { "ja_JP", L"日语", L"日本語" },
    { "ko_KR", L"韩语", L"한국어" },
    { "ms_MY", L"马来语", L"Melayu" },
    { "fa_IR", L"波斯语", L"فارسی" },
    { "pl_PL", L"波兰语", L"Polski" },
    { "ro_RO", L"罗马尼亚语", L"Română" },
    { "ru_RU", L"俄语", L"Русский" },
    { "sr_RS", L"塞尔维亚语", L"Српски" },
    { "sv_SE", L"瑞典语", L"Svenska" },
    { "th_TH", L"泰语", L"ไทย" },
    { "tr_TR", L"土耳其语", L"Türkçe" },
    { "ur_PK", L"乌尔都语", L"اردو" },
    { "vi_VN", L"越南语", L"Tiếng Việt" },
    { "ca_ES", L"加泰罗尼亚语(西班牙)", L"Català" },
    { "lv_LV", L"拉脱维亚语", L"Latviešu" },
    { "lt_LT", L"立陶宛语", L"Lietuvių" },
    { "nb_NO", L"书面挪威语", L"Norsk bokmål" },
    { "sk_SK", L"斯洛伐克语", L"Slovenčina" },
    { "sl_SI", L"斯洛文尼亚语", L"Slovenščina" },
    { "bg_BG", L"保加利亚语", L"Български" },
    { "uk_UA", L"乌克兰语", L"Українська" },
    { "fil_PH", L"菲律宾语", L"Filipino" },
    { "fi_FI", L"芬兰语", L"Suomi" },
    { "af_ZA", L"南非荷兰语", L"Afrikaans" },
    { "rm_CH", L"罗曼什语(瑞士)", L"Rumantsch" },
    { "km_KH", L"高棉语", L"ខ្មែរ" },
    { "my_MM", L"缅甸语", L"မြန်မာ" },
    { "am_ET", L"阿姆哈拉语(埃塞俄比亚)", L"አማርኛ" },
    { "be_BY", L"白俄罗斯语", L"Беларуская" },
    { "et_EE", L"爱沙尼亚语", L"Eesti" },
    { "sw_TZ", L"斯瓦希里语(坦桑尼亚)", L"Kiswahili" },
    { "zu_ZA", L"祖鲁语(南非)", L"IsiZulu" },
    { "az_AZ", L"阿塞拜疆语", L"Azərbaycan" },
    { "hy_AM", L"亚美尼亚语(亚美尼亚)", L"Հայերեն" },
    { "ka_GE", L"格鲁吉亚语(格鲁吉亚)", L"ქართული" },
    { "lo_LA", L"老挝语(老挝)", L"ລາວ" },
    { "mn_MN", L"蒙古语", L"Монгол" },
    { "ne_NP", L"尼泊尔语", L"नेपाली" },
    { "kk_KZ", L"哈萨克语", L"Қазақ тілі" },
    { "si_LK", L"僧伽罗语(斯里兰卡)", L"සිංහල" },
    { "uz_UZ", L"乌兹别克语", L"Ўзбекча" },
};

static const std::size_t kLanguageCount =
    sizeof(kLanguages) / sizeof(kLanguages[0]);

inline std::string ToLanguageTag(const char* code) {
    std::string tag(code);
    std::replace(tag.begin(), tag.end(), '_', '-');
    return tag;
}

inline const wchar_t* DisplayName(
    const LanguageOption& option,
    bool chineseUi) {
    return chineseUi ? option.zhName : option.nativeName;
}

inline const LanguageOption* FindLanguage(const std::string& code) {
    for (std::size_t i = 0; i < kLanguageCount; ++i) {
        if (code == kLanguages[i].code) {
            return &kLanguages[i];
        }
    }
    return 0;
}

调用示例:

const LanguageOption* option = FindLanguage("fil_PH");
if (option != 0) {
    const std::string languageTag = ToLanguageTag(option->code); // fil-PH
    const wchar_t* uiText = DisplayName(*option, false);         // Filipino
}

源码应保存为 UTF-8 BOM,或在 MSVC 中启用 /utf-8。跨平台 C++ 项目也可以将显示名称改成 UTF-8 std::string。C++ 标准库没有统一接收 BCP 47 的 locale 构造接口,转换后的标签通常传给 Qt、ICU 或 Web API。

5.4 C# / .NET

下面的写法不依赖 record,可以覆盖更多旧版 C# 项目:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;

public sealed class LanguageOption
{
    public string Code { get; private set; }
    public string ZhName { get; private set; }
    public string NativeName { get; private set; }

    public LanguageOption(string code, string zhName, string nativeName)
    {
        Code = code;
        ZhName = zhName;
        NativeName = nativeName;
    }

    public string ToLanguageTag()
    {
        return Code.Replace('_', '-');
    }

    public CultureInfo ToCultureInfo()
    {
        return CultureInfo.GetCultureInfo(ToLanguageTag());
    }

    public string DisplayName(bool chineseUi)
    {
        return chineseUi ? ZhName : NativeName;
    }
}

public static class LanguageCatalog
{
    public static readonly ReadOnlyCollection<LanguageOption> All =
        new List<LanguageOption>
        {
            new LanguageOption("zh_CN", "简体中文", "简体中文"),
            new LanguageOption("zh_TW", "繁体中文(台湾)", "繁體中文(台灣)"),
            new LanguageOption("zh_HK", "繁体中文(香港)", "繁體中文(香港)"),
            new LanguageOption("nl_NL", "荷兰语", "Nederlands (Nederland)"),
            new LanguageOption("nl_BE", "荷兰语(比利时)", "Nederlands (België)"),
            new LanguageOption("en_US", "英语(美国)", "English (United States)"),
            new LanguageOption("en_AU", "英语(澳大利亚)", "English (Australia)"),
            new LanguageOption("en_CA", "英语(加拿大)", "English (Canada)"),
            new LanguageOption("en_IN", "英语(印度)", "English (India)"),
            new LanguageOption("en_IE", "英语(爱尔兰)", "English (Ireland)"),
            new LanguageOption("en_NZ", "英语(新西兰)", "English (New Zealand)"),
            new LanguageOption("en_SG", "英语(新加坡)", "English (Singapore)"),
            new LanguageOption("en_ZA", "英语(南非)", "English (South Africa)"),
            new LanguageOption("en_GB", "英语(英国)", "English (United Kingdom)"),
            new LanguageOption("fr_FR", "法语", "Français (France)"),
            new LanguageOption("fr_BE", "法语(比利时)", "Français (Belgique)"),
            new LanguageOption("fr_CA", "法语(加拿大)", "Français (Canada)"),
            new LanguageOption("fr_CH", "法语(瑞士)", "Français (Suisse)"),
            new LanguageOption("de_DE", "德语", "Deutsch (Deutschland)"),
            new LanguageOption("de_LI", "德语(列支敦斯登)", "Deutsch (Liechtenstein)"),
            new LanguageOption("de_AT", "德语(奥地利)", "Deutsch (Österreich)"),
            new LanguageOption("de_CH", "德语(瑞士)", "Deutsch (Schweiz)"),
            new LanguageOption("it_IT", "意大利语", "Italiano (Italia)"),
            new LanguageOption("it_CH", "意大利语(瑞士)", "Italiano (Svizzera)"),
            new LanguageOption("pt_BR", "葡萄牙语(巴西)", "Português (Brasil)"),
            new LanguageOption("pt_PT", "葡萄牙语", "Português (Portugal)"),
            new LanguageOption("es_ES", "西班牙语", "Español (España)"),
            new LanguageOption("es_US", "西班牙语(美国)", "Español (Estados Unidos)"),
            new LanguageOption("bn_BD", "孟加拉语", "বাংলা (বাংলাদেশ)"),
            new LanguageOption("bn_IN", "孟加拉语(印度)", "বাংলা (ভারত)"),
            new LanguageOption("hr_HR", "克罗地亚语", "Hrvatski"),
            new LanguageOption("cs_CZ", "捷克语", "Čeština"),
            new LanguageOption("da_DK", "丹麦语", "Dansk"),
            new LanguageOption("el_GR", "希腊语", "Ελληνικά"),
            new LanguageOption("he_IL", "希伯来语(以色列)", "עברית"),
            new LanguageOption("hi_IN", "印地语", "हिन्दी"),
            new LanguageOption("hu_HU", "匈牙利语", "Magyar"),
            new LanguageOption("id_ID", "印度尼西亚语", "Bahasa Indonesia"),
            new LanguageOption("ja_JP", "日语", "日本語"),
            new LanguageOption("ko_KR", "韩语", "한국어"),
            new LanguageOption("ms_MY", "马来语", "Melayu"),
            new LanguageOption("fa_IR", "波斯语", "فارسی"),
            new LanguageOption("pl_PL", "波兰语", "Polski"),
            new LanguageOption("ro_RO", "罗马尼亚语", "Română"),
            new LanguageOption("ru_RU", "俄语", "Русский"),
            new LanguageOption("sr_RS", "塞尔维亚语", "Српски"),
            new LanguageOption("sv_SE", "瑞典语", "Svenska"),
            new LanguageOption("th_TH", "泰语", "ไทย"),
            new LanguageOption("tr_TR", "土耳其语", "Türkçe"),
            new LanguageOption("ur_PK", "乌尔都语", "اردو"),
            new LanguageOption("vi_VN", "越南语", "Tiếng Việt"),
            new LanguageOption("ca_ES", "加泰罗尼亚语(西班牙)", "Català"),
            new LanguageOption("lv_LV", "拉脱维亚语", "Latviešu"),
            new LanguageOption("lt_LT", "立陶宛语", "Lietuvių"),
            new LanguageOption("nb_NO", "书面挪威语", "Norsk bokmål"),
            new LanguageOption("sk_SK", "斯洛伐克语", "Slovenčina"),
            new LanguageOption("sl_SI", "斯洛文尼亚语", "Slovenščina"),
            new LanguageOption("bg_BG", "保加利亚语", "Български"),
            new LanguageOption("uk_UA", "乌克兰语", "Українська"),
            new LanguageOption("fil_PH", "菲律宾语", "Filipino"),
            new LanguageOption("fi_FI", "芬兰语", "Suomi"),
            new LanguageOption("af_ZA", "南非荷兰语", "Afrikaans"),
            new LanguageOption("rm_CH", "罗曼什语(瑞士)", "Rumantsch"),
            new LanguageOption("km_KH", "高棉语", "ខ្មែរ"),
            new LanguageOption("my_MM", "缅甸语", "မြန်မာ"),
            new LanguageOption("am_ET", "阿姆哈拉语(埃塞俄比亚)", "አማርኛ"),
            new LanguageOption("be_BY", "白俄罗斯语", "Беларуская"),
            new LanguageOption("et_EE", "爱沙尼亚语", "Eesti"),
            new LanguageOption("sw_TZ", "斯瓦希里语(坦桑尼亚)", "Kiswahili"),
            new LanguageOption("zu_ZA", "祖鲁语(南非)", "IsiZulu"),
            new LanguageOption("az_AZ", "阿塞拜疆语", "Azərbaycan"),
            new LanguageOption("hy_AM", "亚美尼亚语(亚美尼亚)", "Հայերեն"),
            new LanguageOption("ka_GE", "格鲁吉亚语(格鲁吉亚)", "ქართული"),
            new LanguageOption("lo_LA", "老挝语(老挝)", "ລາວ"),
            new LanguageOption("mn_MN", "蒙古语", "Монгол"),
            new LanguageOption("ne_NP", "尼泊尔语", "नेपाली"),
            new LanguageOption("kk_KZ", "哈萨克语", "Қазақ тілі"),
            new LanguageOption("si_LK", "僧伽罗语(斯里兰卡)", "සිංහල"),
            new LanguageOption("uz_UZ", "乌兹别克语", "Ўзбекча"),
        }.AsReadOnly();

    public static LanguageOption FindByCode(string code)
    {
        foreach (LanguageOption option in All)
        {
            if (string.Equals(option.Code, code, StringComparison.Ordinal))
            {
                return option;
            }
        }
        return null;
    }
}

调用示例:

var option = LanguageCatalog.FindByCode("fil_PH");
if (option != null)
{
    var culture = option.ToCultureInfo();              // fil-PH
    var uiText = option.DisplayName(chineseUi: false); // Filipino
}

5.5 JavaScript / TypeScript

下面的代码本身是有效 JavaScript,同时通过 JSDoc 为 TypeScript 和编辑器提供类型信息:

/**
 * @typedef {Readonly<{
 *   code: string,
 *   zhName: string,
 *   nativeName: string
 * }>} LanguageOption
 */

/** @type {ReadonlyArray<LanguageOption>} */
const LANGUAGE_OPTIONS = Object.freeze([
  { code: "zh_CN", zhName: "简体中文", nativeName: "简体中文" },
  { code: "zh_TW", zhName: "繁体中文(台湾)", nativeName: "繁體中文(台灣)" },
  { code: "zh_HK", zhName: "繁体中文(香港)", nativeName: "繁體中文(香港)" },
  { code: "nl_NL", zhName: "荷兰语", nativeName: "Nederlands (Nederland)" },
  { code: "nl_BE", zhName: "荷兰语(比利时)", nativeName: "Nederlands (België)" },
  { code: "en_US", zhName: "英语(美国)", nativeName: "English (United States)" },
  { code: "en_AU", zhName: "英语(澳大利亚)", nativeName: "English (Australia)" },
  { code: "en_CA", zhName: "英语(加拿大)", nativeName: "English (Canada)" },
  { code: "en_IN", zhName: "英语(印度)", nativeName: "English (India)" },
  { code: "en_IE", zhName: "英语(爱尔兰)", nativeName: "English (Ireland)" },
  { code: "en_NZ", zhName: "英语(新西兰)", nativeName: "English (New Zealand)" },
  { code: "en_SG", zhName: "英语(新加坡)", nativeName: "English (Singapore)" },
  { code: "en_ZA", zhName: "英语(南非)", nativeName: "English (South Africa)" },
  { code: "en_GB", zhName: "英语(英国)", nativeName: "English (United Kingdom)" },
  { code: "fr_FR", zhName: "法语", nativeName: "Français (France)" },
  { code: "fr_BE", zhName: "法语(比利时)", nativeName: "Français (Belgique)" },
  { code: "fr_CA", zhName: "法语(加拿大)", nativeName: "Français (Canada)" },
  { code: "fr_CH", zhName: "法语(瑞士)", nativeName: "Français (Suisse)" },
  { code: "de_DE", zhName: "德语", nativeName: "Deutsch (Deutschland)" },
  { code: "de_LI", zhName: "德语(列支敦斯登)", nativeName: "Deutsch (Liechtenstein)" },
  { code: "de_AT", zhName: "德语(奥地利)", nativeName: "Deutsch (Österreich)" },
  { code: "de_CH", zhName: "德语(瑞士)", nativeName: "Deutsch (Schweiz)" },
  { code: "it_IT", zhName: "意大利语", nativeName: "Italiano (Italia)" },
  { code: "it_CH", zhName: "意大利语(瑞士)", nativeName: "Italiano (Svizzera)" },
  { code: "pt_BR", zhName: "葡萄牙语(巴西)", nativeName: "Português (Brasil)" },
  { code: "pt_PT", zhName: "葡萄牙语", nativeName: "Português (Portugal)" },
  { code: "es_ES", zhName: "西班牙语", nativeName: "Español (España)" },
  { code: "es_US", zhName: "西班牙语(美国)", nativeName: "Español (Estados Unidos)" },
  { code: "bn_BD", zhName: "孟加拉语", nativeName: "বাংলা (বাংলাদেশ)" },
  { code: "bn_IN", zhName: "孟加拉语(印度)", nativeName: "বাংলা (ভারত)" },
  { code: "hr_HR", zhName: "克罗地亚语", nativeName: "Hrvatski" },
  { code: "cs_CZ", zhName: "捷克语", nativeName: "Čeština" },
  { code: "da_DK", zhName: "丹麦语", nativeName: "Dansk" },
  { code: "el_GR", zhName: "希腊语", nativeName: "Ελληνικά" },
  { code: "he_IL", zhName: "希伯来语(以色列)", nativeName: "עברית" },
  { code: "hi_IN", zhName: "印地语", nativeName: "हिन्दी" },
  { code: "hu_HU", zhName: "匈牙利语", nativeName: "Magyar" },
  { code: "id_ID", zhName: "印度尼西亚语", nativeName: "Bahasa Indonesia" },
  { code: "ja_JP", zhName: "日语", nativeName: "日本語" },
  { code: "ko_KR", zhName: "韩语", nativeName: "한국어" },
  { code: "ms_MY", zhName: "马来语", nativeName: "Melayu" },
  { code: "fa_IR", zhName: "波斯语", nativeName: "فارسی" },
  { code: "pl_PL", zhName: "波兰语", nativeName: "Polski" },
  { code: "ro_RO", zhName: "罗马尼亚语", nativeName: "Română" },
  { code: "ru_RU", zhName: "俄语", nativeName: "Русский" },
  { code: "sr_RS", zhName: "塞尔维亚语", nativeName: "Српски" },
  { code: "sv_SE", zhName: "瑞典语", nativeName: "Svenska" },
  { code: "th_TH", zhName: "泰语", nativeName: "ไทย" },
  { code: "tr_TR", zhName: "土耳其语", nativeName: "Türkçe" },
  { code: "ur_PK", zhName: "乌尔都语", nativeName: "اردو" },
  { code: "vi_VN", zhName: "越南语", nativeName: "Tiếng Việt" },
  { code: "ca_ES", zhName: "加泰罗尼亚语(西班牙)", nativeName: "Català" },
  { code: "lv_LV", zhName: "拉脱维亚语", nativeName: "Latviešu" },
  { code: "lt_LT", zhName: "立陶宛语", nativeName: "Lietuvių" },
  { code: "nb_NO", zhName: "书面挪威语", nativeName: "Norsk bokmål" },
  { code: "sk_SK", zhName: "斯洛伐克语", nativeName: "Slovenčina" },
  { code: "sl_SI", zhName: "斯洛文尼亚语", nativeName: "Slovenščina" },
  { code: "bg_BG", zhName: "保加利亚语", nativeName: "Български" },
  { code: "uk_UA", zhName: "乌克兰语", nativeName: "Українська" },
  { code: "fil_PH", zhName: "菲律宾语", nativeName: "Filipino" },
  { code: "fi_FI", zhName: "芬兰语", nativeName: "Suomi" },
  { code: "af_ZA", zhName: "南非荷兰语", nativeName: "Afrikaans" },
  { code: "rm_CH", zhName: "罗曼什语(瑞士)", nativeName: "Rumantsch" },
  { code: "km_KH", zhName: "高棉语", nativeName: "ខ្មែរ" },
  { code: "my_MM", zhName: "缅甸语", nativeName: "မြန်မာ" },
  { code: "am_ET", zhName: "阿姆哈拉语(埃塞俄比亚)", nativeName: "አማርኛ" },
  { code: "be_BY", zhName: "白俄罗斯语", nativeName: "Беларуская" },
  { code: "et_EE", zhName: "爱沙尼亚语", nativeName: "Eesti" },
  { code: "sw_TZ", zhName: "斯瓦希里语(坦桑尼亚)", nativeName: "Kiswahili" },
  { code: "zu_ZA", zhName: "祖鲁语(南非)", nativeName: "IsiZulu" },
  { code: "az_AZ", zhName: "阿塞拜疆语", nativeName: "Azərbaycan" },
  { code: "hy_AM", zhName: "亚美尼亚语(亚美尼亚)", nativeName: "Հայերեն" },
  { code: "ka_GE", zhName: "格鲁吉亚语(格鲁吉亚)", nativeName: "ქართული" },
  { code: "lo_LA", zhName: "老挝语(老挝)", nativeName: "ລາວ" },
  { code: "mn_MN", zhName: "蒙古语", nativeName: "Монгол" },
  { code: "ne_NP", zhName: "尼泊尔语", nativeName: "नेपाली" },
  { code: "kk_KZ", zhName: "哈萨克语", nativeName: "Қазақ тілі" },
  { code: "si_LK", zhName: "僧伽罗语(斯里兰卡)", nativeName: "සිංහල" },
  { code: "uz_UZ", zhName: "乌兹别克语", nativeName: "Ўзбекча" }
].map((item) => Object.freeze(item)));

const findLanguage = (code) =>
  LANGUAGE_OPTIONS.find((item) => item.code === code);

const toLanguageTag = ({ code }) => code.replace("_", "-");

const displayName = (option, chineseUi) =>
  chineseUi ? option.zhName : option.nativeName;

调用示例:

const option = findLanguage("fil_PH");
if (option) {
  const languageTag = toLanguageTag(option);              // fil-PH
  const uiText = displayName(option, false);               // Filipino
  const formatter = new Intl.DateTimeFormat(languageTag); // 标准 API 使用 fil-PH
}

Web 页面还可以将转换后的标签写入 <html lang="fil-PH">。产品语言列表仍显示固定的 zhName 或 nativeName,不要用 Intl.DisplayNames 动态替换。

5.6 其他编程语言

Go、Python、Rust 等语言可以直接读取 5.1 节的完整 JSON。接入时只需保持相同边界:

  1. 记录固定包含 code、zhName、nativeName。
  2. 应用内持久化和系统间通信使用原始 code,例如 fil_PH。
  3. 调用只接受 BCP 47 的标准库或外部接口前,将 _ 转为 -,得到 fil-PH。
  4. UI 显示直接选择 zhName 或 nativeName,不要让运行时重新生成产品名称。

6. 多技术栈如何避免再次分叉

不要分别手工维护 Java、C++、C# 和前端语言表。更稳妥的做法是建立一份 UTF-8 JSON 真值文件,再通过生成脚本输出各语言所需的常量或资源文件:

language-catalog.json
    ├─ 生成 Java LanguageOptions
    ├─ 生成 C++ LanguageOptions
    ├─ 生成 C# LanguageOptions
    └─ 生成 JavaScript/TypeScript LanguageOptions

真值文件由人工审查,生成物禁止手工修改。持续集成可以重新生成一次并检查工作区是否出现差异,以便及时发现漏同步。

7. 同步检查清单

修改或新增语言后,至少确认:

8. 标准参考

外部标准负责提供代码和语言数据依据;应用自身仍需明确最终采用的内部格式、显示文字和兼容策略。


本文源地址:https://www.cnblogs.com/BensonLaur/p/23050063

posted @ 2026-09-20 16:34  BensonLaur  阅读(9)  评论(0)    收藏  举报