资讯动态

TREK 多语言支持完全指南:20 种语言、RTL 布局与语言检测链路解析

发布时间:2026/9/15 19:55:30 来源:尧图企业网站定制
TREK 多语言支持完全指南20 种语言、RTL 布局与语言检测链路解析【免费下载链接】TREKA self-hosted travel/trip planner with real-time collaboration, interactive maps, PWA support, SSO, budgets, packing lists, and more.项目地址: https://gitcode.com/GitHub_Trending/nomad22/TREK导读TREK 是一个自托管的旅行规划器内置了覆盖 20 种语言的完整翻译体系支持从登录前到登录后的全流程语言切换。本文以 wiki/Languages.md 为骨架结合trek/shared国际化包、客户端TranslationProvider与服务器DEFAULT_LANGUAGE配置的源码实现系统讲解 TREK 支持的语言清单、阿拉伯语 RTL 布局机制、四级语言检测链路以及管理员如何通过环境变量控制未登录用户的默认语言。读完本文你将掌握 TREK 多语言体系的全貌并能独立完成用户端切换与服务器端默认语言配置。支持的语言一览TREK 开箱即用提供 20 种语言的界面翻译用户无需登出即可随时切换语言。文档表格中的语言代码与仓库源码中的权威注册表一一对应权威来源位于 shared/src/i18n/languages.ts客户端通过 client/src/i18n/supportedLanguages.ts 将其重新导出该文件注释明确指出Canonical language registry now lives in trek/shared。CodeLanguageIntl Locale源码注册值deDeutschde-DEenEnglishen-USesEspañoles-ESfrFrançaisfr-FRhuMagyarhu-HUnlNederlandsnl-NLbrPortuguês (Brasil)pt-BRcsČeskycs-CZplPolskipl-PLruРусскийru-RUzh简体中文zh-CNzh-TW繁體中文zh-TWitItalianoit-ITtrTürkçetr-TRarالعربيةar-SAidBahasa Indonesiaid-IDja日本語ja-JPko한국어ko-KRukУкраїнськаuk-UAgrΕλληνικάel-GR补充说明仓库实际状态虽然 wiki/Languages.md 表格列出 20 种语言但当前仓库的翻译目录 shared/src/i18n 中实际还包含svSvenska、viTiếng Việt、caCatalà三个目录shared/src/i18n/languages.ts 也已注册对应条目因此运行时实际可用的语言代码为 23 个。用户在语言选择器中看到的具体选项以SUPPORTED_LANGUAGES数组为准。两个值得注意的代码约定br≠ 布鲁塞尔br实际代表巴西葡萄牙语Português do Brasil其 Intl locale 映射为pt-BR。客户端在 client/src/i18n/TranslationContext.tsx 中对浏览器上报的pt-BR做了显式映射而pt-PT和裸pt则不会命中会继续沿检测链路向下匹配。gr代表希腊语代码使用gr而非 ISO 标准的el对应 locale 为el-GR。RTL 布局支持阿拉伯语专属的从右到左渲染阿拉伯语ar是 TREK 目前唯一使用从右到左RTL布局的语言其余所有语言均为从左到右LTR。这一行为由共享包中的isRtlLanguage工具函数实现RTL 语言集合定义在 shared/src/i18n/languages.ts// Languages displayed right-to-left. const RTL_LANGUAGES new Setstring([ar]); export function isRtlLanguage(language: string): boolean { return RTL_LANGUAGES.has(language); }当用户选择语言后客户端 TranslationProvider 会同步更新 HTML 文档的语言与方向属性useEffect(() { document.documentElement.lang language document.documentElement.dir isRtlLanguage(language) ? rtl : ltr }, [language])即html langar dirrtl会被自动写入 DOM配合浏览器的 RTL 排版能力如 flex/grid 方向的自动镜像即可完成整个界面的镜像布局无需为每个组件单独编写 RTL 样式。CSS 层面基于dir属性与逻辑属性logical properties即可自适应这也是所有依赖dir的现代 Web 布局的标准做法。语言检测链路四级解析顺序TREK 解析显示语言时严格按照以下优先级从高到低用户偏好——保存在账号中的语言Settings → General 中设置浏览器语言——浏览器上报的navigator.languages以及navigator.language服务器默认值——管理员设置的DEFAULT_LANGUAGE环境变量兜底——英语en第 1 级用户偏好localStorage 账号设置用户语言偏好保存在localStorage的app_language键中。见 client/src/store/settingsStore.ts// Returns true when the user has explicitly chosen a language (persisted in localStorage). export const hasStoredLanguage (): boolean typeof localStorage ! undefined !!localStorage.getItem(app_language)settingsStore的初始状态直接读取该键settingsStore.ts并提供两个写入入口setLanguage——持久化写入localStorage并更新 store对应Settings → General中的显式选择setLanguageTransient——仅对当前会话生效、不写入localStorage用于登录页的临时检测结果见 settingsStore.ts。TranslationProvider正是从useSettingsStore中读取settings.language作为当前语言TranslationContext.tsx因此用户偏好是整条链路的最高优先级。第 2 级浏览器语言检测若用户没有已保存的偏好登录页逻辑client/src/pages/login/useLogin.ts会调用detectBrowserLanguage()export function detectBrowserLanguage(): string | null { if (typeof navigator undefined) return null const browserLangs navigator.languages?.length ? navigator.languages : navigator.language ? [navigator.language] : [] const supported SUPPORTED_LANGUAGES.map(l l.value) for (const lang of browserLangs) { const exactMatch supported.find(s s.toLowerCase() lang.toLowerCase()) if (exactMatch) return exactMatch // pt-BR has no exact match (our code is br), so map it explicitly. if (lang.toLowerCase() pt-br) return br const prefix lang.split(-)[0]?.toLowerCase() const prefixMatch supported.find(s s.toLowerCase() prefix) if (prefixMatch) return prefixMatch } return null }检测逻辑TranslationContext.tsx依次尝试遍历navigator.languages数组降序偏好列表对每个语言做精确匹配如浏览器上报zh-TW直接命中特殊映射pt-BR→br对每个语言做主语言前缀匹配如浏览器上报en-US取en命中。detectBrowserLanguage是纯函数且无副作用返回null表示浏览器语言不在支持列表内此时进入第 3 级。第 3 级服务器默认值DEFAULT_LANGUAGE当浏览器语言无法匹配时登录页会向服务器请求公开配置configApi.getPublicConfig() .then(({ defaultLanguage }) { if (defaultLanguage) setLanguageTransient(defaultLanguage) }) .catch((err) console.warn(Failed to fetch default language config:, err))该公开配置由 server/src/nest/config/config.controller.ts 提供直接返回服务器端解析后的DEFAULT_LANGUAGE常量。第 4 级英语兜底settingsStore的默认值是ensettingsStore.tsTranslationProvider中也以英文包en作为同步初始值和翻译缺失时的回退源TranslationContext.tsx。整个链路保证任何环境下界面都不会出现空字符串。端到端流程小结用户已保存偏好? ──是──▶ 使用 localStorage 中的 app_language │否 ▼ detectBrowserLanguage() 命中? ──是──▶ setLanguageTransient(detected) │否 ▼ GET /api/configDEFAULT_LANGUAGE──▶ setLanguageTransient(defaultLanguage) │失败/未配置 ▼ 硬编码兜底 en语言选择器出现在哪里登录 / 注册页——登录之前即可切换语言此时语言偏好以瞬态方式生效不写入 localStorage见setLanguageTransient的注释与实现Settings → General——登录后通过账号设置持久化语言偏好相关文档见 Display-Settings公开分享页——旅行分享链接的公开视图公开旅程页——面向公众的旅程展示视图。管理员提示DEFAULT_LANGUAGE环境变量设置的是登录页及未认证用户的兜底语言。相关文档见 Environment-Variables。管理员配置DEFAULT_LANGUAGE 环境变量服务端解析逻辑服务器在启动时读取DEFAULT_LANGUAGE并做合法性校验server/src/config.ts// DEFAULT_LANGUAGE sets the language shown on the login page before the user // selects one. Only applies when the user has no saved language preference. const rawDefaultLang process.env.DEFAULT_LANGUAGE?.toLowerCase() || en; if (!SUPPORTED_LANG_CODES.includes(rawDefaultLang)) { console.warn( DEFAULT_LANGUAGE${rawDefaultLang} is not supported. Falling back to en. Supported: ${SUPPORTED_LANG_CODES.join(, )}, ); } export const DEFAULT_LANGUAGE SUPPORTED_LANG_CODES.includes(rawDefaultLang) ? rawDefaultLang : en;关键行为未设置时默认en值会先转小写再匹配ZH与zh等价非法值不会导致启动失败只会打印一条警告日志并回退到en——这保证了误配置不会让实例崩溃。各部署方式的配置位置部署方式配置位置Docker Composedocker-compose.yml 中取消注释DEFAULT_LANGUAGEenHelmcharts/trek/values.yaml 中取消注释DEFAULT_LANGUAGE: enUnraid 模板unraid-template.xml 中的DEFAULT_LANGUAGE高级变量Advanced View注释中给出了完整支持列表.env.exampleserver/.env.example同样给出了示例。需要注意的是docker-compose.yml与unraid-template.xml中的注释列出的是 20 个语言代码未含sv/vi/ca而仓库源码的SUPPORTED_LANGUAGES实际注册了 23 个DEFAULT_LANGUAGE的合法值以源码注册表为准设置为任何未注册代码都会回退到en。可用值速查DEFAULT_LANGUAGE支持的值与 共享语言注册表 一致de, en, es, fr, hu, nl, br, cs, pl, ru, zh, zh-TW, it, tr, ar, id, ja, ko, uk, gr另有源码中注册的sv, vi, ca。翻译体系如何工作按需加载与键回退深入理解 TREK 的多语言支持还需要了解其翻译文件的组织与加载方式。翻译文件的领域化组织每种语言的翻译按功能域拆分成多个文件。以英文为例shared/src/i18n/en/index.ts聚合了admin、airport、atlas、budget、collab、journey、map、planner、reservations、transport、vacay等 40 余个域模块最终合并为一个扁平键值对 locale 对象。每个语言独立的代码分包客户端为每个 locale 声明了独立的动态导入client/src/i18n/TranslationContext.tsx// One explicit dynamic import per locale — Vite code-splits a separate chunk per locale. // Only the active locale is fetched; en is always available synchronously as the fallback. const localeLoaders: RecordSupportedLanguageCode, () Promise{ default: TranslationStrings } { en: () Promise.resolve({ default: en }), de: () import(trek/shared/i18n/de), es: () import(trek/shared/i18n/es), // ... }TranslationProvider根据当前语言调用对应 loader仅在语言切换时才请求对应语言包英文包则始终同步可用TranslationContext.tsx兼顾了冷启动速度与按需加载的体积控制。三层键回退翻译查找采用当前语言键 → 英文键 → 原样返回键名的三层回退TranslationContext.tsxlet val: string (strings[key] ?? en[key] ?? key) as string这意味着某条翻译在目标语言中尚未完成时会优雅地回退到英文即使英文也缺失界面也不会崩溃而是显示键名本身便于开发排查。带参插值与 HTML 安全t()支持{placeholder}形式的参数插值基于正则替换tHtml()则是面向含标记模板的变体采用双层防御插值参数先 HTML 转义、整体字符串再经sanitizeInlineHtml白名单过滤TranslationContext.tsx确保翻译模板即使被恶意构造也无法注入脚本这对多语言环境尤为重要。翻译一致性校验仓库用测试保障翻译体系的结构健康shared/src/i18n/i18n-parity.spec.ts每个非英文语言目录必须与en/拥有完全相同的领域文件集file-level drift 视为结构性 bug 直接 fail而具体翻译键的增减key-level drift则允许渐进推进由 CLI 脚本 shared/scripts/i18n-parity.mjs 输出差异报告供译者参考。另有 i18n-placeholders.spec.ts 用于校验占位符一致性。这解释了为什么新增语言必须覆盖全部领域文件也解释了某些语言个别文案显示英文是设计内的渐进式翻译策略。常见问题与排查思路Q1为什么我的浏览器是英文登录页却显示中文检查三级链路是否曾在该浏览器上保存过app_languagelocalStorage——用户偏好优先级最高其次检查管理员设置的DEFAULT_LANGUAGE。Q2设置了不支持的DEFAULT_LANGUAGE会怎样不会启动失败。服务器会打印DEFAULT_LANGUAGExx is not supported. Falling back to en.警告并回退到enserver/src/config.ts。Q3切换语言后页面方向dir没有变化正常情况下TranslationProvider会同步写入html dirrtl| ltr。只有ar会被判定为 RTL其他语言包括希伯来语等未支持语言均按 LTR 处理languages.ts。Q4为什么某些界面文案还是英文TREK 的翻译键采用缺失即回退英文策略某个键在该语言中尚未翻译完成时属正常现象翻译进度属于渐进式推进参见 i18n-parity.spec.ts 的说明。延伸阅读Display-Settings —— 显示相关设置含语言选项的 UI 位置Environment-Variables ——DEFAULT_LANGUAGE及其余环境变量完整说明User-Settings —— 用户账号级设置语言注册表与工具函数shared/src/i18n/languages.ts客户端翻译运行时client/src/i18n/TranslationContext.tsx服务器默认语言解析server/src/config.ts【免费下载链接】TREKA self-hosted travel/trip planner with real-time collaboration, interactive maps, PWA support, SSO, budgets, packing lists, and more.项目地址: https://gitcode.com/GitHub_Trending/nomad22/TREK创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价