
Seelen UI 支持语言机制详解SUPPORTED_LANGUAGES 单一数据源、类型绑定生成与 slu 翻译工作流【免费下载链接】Seelen-UIThe Fully Customizable Desktop Environment for Windows 10/11.项目地址: https://gitcode.com/GitHub_Trending/se/Seelen-UI本文围绕 Seelen UI 仓库中documentation/supported-languages.md文档展开讲解“Seelen UI 支持哪些语言”这一问题的权威列表是如何定义、生成与消费的从 Rust 常量SUPPORTED_LANGUAGES这一唯一数据源到deno task build:rs生成前端 TypeScript 绑定再到设置界面语言选择器与slu resource translate命令如何从同一份列表派生行为。读完后你将掌握 Seelen UI 语言体系的完整架构、当前支持的 74 种语言清单、绑定再生成的完整命令以及为新语言扩展或翻译资源文本的实操流程。一、设计原则一份列表三处消费Seelen UI 在应用范围内维护一份单一权威语言列表所有需要回答“Seelen UI 支持哪些语言”的组件都从这份列表取数具体包括Settings 语言选择器用户切换界面语言的下拉框i18n/translations/下的 locale 文件应用各界面模块的翻译文件集合slu resource translateCLI 命令资源作者翻译ResourceText字段时自动补齐所有目标语言。这样做的好处在 documentation/supported-languages.md 中说得非常直接因为前端与 CLI 都从同一份 Rust 源码派生所以“UI 提供的语言”与“资源被翻译成的语言”永远不会出现漂移drift。文档因此也给出了一条维护约定——不要在文档里另存一份语言清单副本需要当前准确列表时直接查mod.rs。二、列表定义在哪里Rust 常量SUPPORTED_LANGUAGES语言列表的唯一定义位置是 Rust 侧的 libs/core/src/constants/mod.rspub const SUPPORTED_LANGUAGES: [SupportedLanguage] [ lang(Afrikaans, Afrikaans, af), lang(አማርኛ, Amharic, am), lang(العربية, Arabic, ar), // ... 共 74 条 lang(isiZulu, Zulu, zu), ];结构定义在 libs/core/src/constants/mod.rs#L76-L92pub struct SupportedLanguage { pub label: static str, // 语言的母语名称如 Deutsch、日本語 pub en_label: static str, // 语言的英文名称如 German、Japanese pub value: static str, // 语言代码如 es、pt-BR、zh-CN } const fn lang( label: static str, en_label: static str, value: static str, ) - SupportedLanguage { SupportedLanguage { label, en_label, value, } }三个字段各有用途label母语名称用于 UI 中以用户自己的语言展示语言名如德语界面里显示 “Deutsch” 而不是 “German”en_label英文名称作为排序、调试输出的稳定参照value语言代码是贯穿 locale 文件名、Settings 存储值、翻译命令目标语言的匹配键。代码格式上既有双字母代码es、de也有带区域后缀的代码pt-BR、pt-PT、zh-CN、zh-TW。列表使用const fn lang(...)构造使整个数组成为编译期常量零运行时分配。当前支持的 74 种语言以下是 libs/core/src/constants/mod.rs 中的完整列表按文件中顺序以value代码为匹配键value语言en_labelvalue语言en_labelafAfrikaanskoKoreanamAmharickuKurdisharArabiclbLuxembourgishazAzerbaijaniloLaobgBulgarianltLithuanianbnBengalilvLatvianbsBosnianmkMacedoniancaCatalanmnMongoliancsCzechmsMalaycyWelshmtMaltesedaDanishneNepalideGermannlDutchelGreeknoNorwegianenEnglishpaPunjabiesSpanishplPolishetEstonianpsPashtoeuBasquept-BRPortuguese (Brazil)faPersianpt-PTPortuguese (Portugal)fiFinnishroRomanianfrFrenchruRussianguGujaratisiSinhalaheHebrewskSlovakhiHindisoSomalihrCroatiansrSerbianhuHungariansvSwedishhyArmenianswSwahiliidIndonesiantaTamilisIcelandicteTeluguitItaliantgTajikjaJapanesethThaikaGeorgiantlFilipinokmKhmertrTurkishukUkrainianurUrduuzUzbekviVietnameseyoYorubazh-CNChinese (Simplified)zh-TWChinese (Traditional)zuZulu注意几个命名约定中文只有zh-CN/zh-TW葡萄牙语只有pt-BR/pt-PT不存在裸的zh或pt代码。documentation/resource-text.md 特别警告手动写zh:或pt:键永远不会与运行中应用的语言匹配会被静默忽略。enEnglish也在列表内它是ResourceText的强制兜底语言。三、TypeScript 绑定如何生成deno task build:rsdocumentation/supported-languages.md 强调了一条硬性规则绝不手改libs/core/src/constants/mod.ts它是生成产物。该文件由libs/core从mod.rs自动生成导出前端使用的SupportedLanguages常量见 libs/core/src/constants/mod.tsexport type SupportedLanguagesCode (typeof SupportedLanguages)[number][value]; export interface SupportedLanguage { label: string; enLabel: string; /** language code example de es zh en-US en-UK */ value: string; } export const SupportedLanguages [ { label: Afrikaans, enLabel: Afrikaans, value: af }, { label: አማርኛ, enLabel: Amharic, value: am }, // ... 与 mod.rs 逐条一一对应 { label: isiZulu, enLabel: Zulu, value: zu }, ] as const;对照两边的源码可以看到一一对应关系Rust 端的en_label字段在 TS 端按camelCase约定变为enLabelRust 的[SupportedLanguage]静态数组变为 TS 的as const只读元组SupportedLanguagesCode类型则把全部合法语言代码收敛成一个字面量联合类型供前端做穷尽性检查。要增加、删除或重命名一个受支持语言标准流程是# 1. 编辑 libs/core/src/constants/mod.rs 中的 SUPPORTED_LANGUAGES # 2. 重新生成绑定 cd libs/core deno task build:rsbuild:rs任务的定义在 libs/core/deno.json 中它执行 libs/core/scripts/rust_bindings.tstasks: { build:npm: deno run -A ./scripts/build_npm.ts, build:rs: deno run -A ./scripts/rust_bindings.ts, build: deno task build:rs deno task build:npm }从 libs/core/scripts/rust_bindings.ts 的实现看整个流水线分为五步清理旧绑定删除并重建./gen/types目录L3-L16生成 TS 绑定运行cargo test --features gen-binds——绑定生成被实现在cargo test里而非独立二进制中脚本注释原话是 cargo test generates the typescript bindings, why? ask to aleph-alpha/ts-rs xd这也解释了为什么libs/core的 Rust 结构体上普遍挂着#[cfg_attr(all(feature gen-binds, not(feature salvo)), derive(ts_rs::TS))]这类条件 derive创建入口为gen/types下的所有生成文件写mod.ts聚合导出L44-L69抽取类型文档用deno doc --json分别提取gen/types/mod.ts与src/lib.ts的 API 定义输出gen/doc-types.json与gen/doc-lib.jsonL71-L97格式化依次cargo fmt与deno fmtL99-L109。因此mod.ts中的语言数组是每次构建的确定性产物——手改它只会在下次build:rs时被动机覆盖这正是文档要求“永不手改”的原因。四、Settings 如何消费这份列表系统语言回退匹配设置结构体中的语言字段定义在 libs/core/src/state/settings/mod.rs#L478-L479/// language to use, if null the system locale is used pub language: String,而真正与SUPPORTED_LANGUAGES交互的逻辑是同文件的Settings::get_app_language()libs/core/src/state/settings/mod.rs#L558-L577pub fn get_app_language() - String { use crate::constants::SUPPORTED_LANGUAGES; let Some(sys_locale) sys_locale::get_locale() else { return en.to_string(); }; if SUPPORTED_LANGUAGES.iter().any(|l| l.value sys_locale) { return sys_locale; } let Some(base) sys_locale.split(-).next() else { return en.to_string(); }; if SUPPORTED_LANGUAGES.iter().any(|l| l.value base) { return base.to_string(); } en.to_string() }这段代码揭示了系统语言解析的两级匹配算法精确匹配系统 locale如zh-CN、pt-BR直接与列表中某个value完全相等则采用基础语言回退取 locale 按-分割后的首段如zh-HK→zh、pt→pt再匹配一次兜底都匹配不上则返回en。这里也再次印证了第二节的命名约定由于列表中只有zh-CN/zh-TW而没有裸zh一个zh-HK的系统 locale 经过两级匹配后都会落到en兜底——这解释了为什么中文用户需要zh-CN或zh-TW这类带区域代码的语言包。sanitize()libs/core/src/state/settings/mod.rs#L612-L629中还有一处兜底当持久化的language为空字符串时重新调用get_app_language()从系统 locale 推导保证语言字段永远非空。应用级的翻译文件就按这些value代码组织。以 scripts/translate/mod.ts#L64 处理的src/background/i18n目录为例其中的af.yml、am.yml、zh-CN.yml等 68 个文件与SUPPORTED_LANGUAGES中的语言代码一一对应另有en.yml作为源语言、hash.yml记录译文哈希。五、资源侧消费slu resource translate与内部翻译脚本5.1slu resource translate命令资源作者使用的翻译命令由 src/slu/resources.rs 实现。在sluCLI 的入口 src/slu/main.rs#L36-L43 中可以看到AppCommand::Resource走Direct执行模式——直接在 CLI 进程内完成不需要把命令转发给主实例async fn process_direct(cli: AppCli) - Result() { match cli.command { AppCommand::Art(cmd) art::process(cmd), AppCommand::Resource(cmd) resources::process(cmd).await?, _ return Err(Command does not support direct execution.into()), } Ok(()) }命令用法详见 documentation/resource-text.md 第 4 节slu resource translate path/to/file.yml [source_lang]path/to/file.yml——包含ResourceText值纯字符串或语言映射的 YAML 文件[source_lang]——源文本的语言代码默认en。工作流先确认文件中存在source_lang条目没有则报错然后遍历 Seelen UI 支持的每种语言已有译文的语言跳过、绝不覆盖缺失的调用 Google Translate API 补齐最后原地写回文件。示例输出slu resource translate i18n/display_name.yml[01/68] English (Afrikaans) Speel Rekenaar [02/68] Amharic ጨዋታ ኮምፒተር ... [14/68] English Skipped ...非英语源文本需显式传语言代码slu resource translate i18n/description.yml es由于“目标语言”直接来自SUPPORTED_LANGUAGES在mod.rs中新增语言后slu resource translate会自动为每个资源的每个ResourceText字段多翻译这一种语言——资源作者侧无需任何改动。这也是原文档“Why this matters for resources”一节的核心结论。5.2 内部 i18n 补齐脚本仓库自身界面文本的翻译补齐在 scripts/translate/mod.ts它展示了前端绑定SupportedLanguages的真实消费方式import { GoogleTranslator, ObjectTranslator } from seelen/translation-toolkit; import { SupportedLanguages } from seelen-ui/lib; const targetLanguages SupportedLanguages.filter((lang) lang.value ! en);脚本以en.yml为源、hash.yml中的缓存哈希表避免重复翻译遍历除en外的全部目标语言对src/ui/react/settings/i18n/translations、src/ui/svelte/weg/i18n/translations等 14 个界面模块目录以及src/background/i18nscripts/translate/mod.ts#L46-L64逐个补齐缺失译文。从源码结构看应用界面翻译与资源翻译共用同一套“哈希缓存 跳过已有译文”策略只是前者面向应用自身 locale 文件后者面向第三方资源的i18n/目录。六、实操工作流新增一种支持语言结合上述机制为 Seelen UI 新增一种语言的完整步骤是修改单一数据源在 libs/core/src/constants/mod.rs 的SUPPORTED_LANGUAGES中按字母序插入一行例如lang(Srpski, Serbian, sr), // label 用母语名称value 用标准 BCP-47 代码若该语言存在区域变体请沿用xx-REGION形式参照pt-BR、zh-CN的先例不要使用裸代码。重新生成前端绑定cd libs/core deno task build:rs确认 libs/core/src/constants/mod.ts 中出现了对应条目enLabel与 Rust 端en_label一致。补齐应用 locale 文件在相应的i18n目录如src/background/i18n/新建code.yml可运行 scripts/translate/mod.ts 从en.yml自动补齐并按惯例人工校对机器翻译。验证消费端自动生效Settings 语言选择器出现新语言前提是第 3 步的 locale 文件存在文档明确指出“once a matching locale file exists”对既有资源执行slu resource translate新语言会作为缺失项被自动翻译已有语言保持 Skipped。七、约束与注意事项综合 documentation/supported-languages.md 与源码维护语言体系时有几条硬约束mod.ts是生成文件禁止手改一切变更走mod.rsdeno task build:rs文档不复制清单任何文档需要列举语言时以 libs/core/src/constants/mod.rs 为准避免多份清单漂移en是强制键ResourceText的映射形式中en缺失会导致资源校验失败、无法发布见 documentation/resource-text.md区域代码是精确匹配系统 locale 匹配采用“精确 → 基础语言 →en兜底”的三级策略手写zh:/pt:这类列表外代码会被渲染层静默忽略机器翻译只是初稿slu resource translate基于 Google Translate对短小的 UI 标签容易产生生硬或错误译法发布前应人工复核且该命令按文件执行、不递归目录应作为打包前的一次性步骤而非例行操作。从架构上看Seelen UI 把“支持哪些语言”收敛为一个 Rust 编译期常量并通过ts-rs风格的测试期绑定生成把它无漂移地投射到前端与 CLI 两侧是一份“单一数据源 生成绑定 双端消费”的典型国际化设计样本。【免费下载链接】Seelen-UIThe Fully Customizable Desktop Environment for Windows 10/11.项目地址: https://gitcode.com/GitHub_Trending/se/Seelen-UI创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考