ToolJet 前端本地化(L10n)贡献指南:从零为产品新增一套界面语言翻译
发布时间:2026/9/9 13:02:10来源:尧图网络
ToolJet 前端本地化L10n贡献指南从零为产品新增一套界面语言翻译【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet本文对应官方贡献指南 docs/docs/contributing-guide/l10n.md带你完整走一遍 ToolJet 的本地化流程。作为面向全球用户的开源低代码平台ToolJet 的前端界面文本全部由 JSON 翻译文件驱动社区贡献者只需要“建文件、复制模板、逐条翻译、注册语言”四步就能让整个产品界面呈现一门新语言。读完本文你将掌握翻译文件的目录结构与 JSON 命名空间约定、languages.json 注册机制、i18next 的加载与回退原理以及如何通过环境变量把某门语言设为实例默认语言。ToolJet 的本地化机制概览ToolJet 前端的国际化i18n并不是一个黑盒而是基于成熟的i18next react-i18next i18next-http-backend组合实现的按需加载方案。三条核心链路在源码中可以逐一验证翻译资源所有语言文案存放在 frontend/assets/translations 目录下每门语言一个语言码.json文件另有一个languages.json维护“支持语言清单”。运行时加载前端启动入口 frontend/src/index.jsx 中完成i18n初始化通过loadPath拼接assets/translations/{{lng}}.json让 i18next 在运行期按需 HTTP 拉取对应语言的 JSON。界面切换语言选择组件 frontend/src/_components/LanguageSelection.jsx 从languages.json读取清单、渲染语言弹窗并在用户选中后调用i18n.changeLanguage(lang.code)实现全局即时切换。对贡献者来说你不需要改动任何 React 组件或构建逻辑——本地化的全部工作都集中在 JSON 资源文件上。这也是官方将其定位为“最容易上手的贡献方式”的原因。frontend |-- assets | |-- translations | | |-- languages.json # 语言注册清单 | | |-- en.json # 英文模板基准 | | |-- fr.json # 法语 | | |-- ...docs/static/img/l10n/files.png直观展示了该目录的真实组织形态翻译文件命名与目录约定本地化工作的第一步是“按规范命名新语言文件”文件位置与命名规则如下目录frontend/assets/translations仓库根目录下frontend包内的静态资源目录文件名必须是语言代码.json语言代码遵循ISO 639-1标准两位小写字母清单同时维护languages.json只有登记在清单中的语言才会出现在产品界面的语言选择器里。当前仓库中已内置了 9 门语言的翻译文件可实际查看 frontend/assets/translations语言文件语言文件英语en.json乌克兰语uk.json法语fr.json俄语ru.json西班牙语es.json德语de.json意大利语it.json中文zh.json印度尼西亚语id.json提示官方文档示例以法语frISO 639-1 中 French 的代码展开本文后续步骤保持一致。新增一门语言的四个步骤第 1 步创建languagecode.json翻译文件进入frontend/assets/translations目录新建一个以目标语言代码命名的 JSON 文件。以法语为例创建fr.jsonfr即法语的语言代码frontend/assets/translations/fr.json # 新建第 2 步复制en.json作为翻译模板打开现有的en.json将全部内容原样复制到新文件中。en.json是 ToolJet 的“母本”语言文件其中包含了全部界面文案的键key键层级多、条目多当前仓库中该文件约 1000 行因此永远不要把英文翻译文件当成可丢弃的临时文件——它是新增语言唯一的键来源。官方文档同样强调新语言文件必须以en.json为起点逐条翻译避免漏键。docs/static/img/l10n/en.png展示了en.json的真实内容形态顶部是globals命名空间中的通用按钮文案第 3 步逐条翻译键值复制完成后在fr.json中把每个 key 右侧的英文值替换为对应的法语文本。文件采用嵌套命名空间结构组织例如抽取自仓库真实en.json的开头部分{ globals: { readDocumentation: Read documentation, cancel: Cancel, save: Save, savechanges: Save changes, execute: Execute, edit: Edit, search: Search, add: Add, delete: Delete }, errorBoundary: Something went wrong., viewer: Sorry!. This app is under maintenance, app: { updateAvailable: Update available, newVersionReleased: A new version of ToolJet has been released., readReleaseNotes: Read release notes update, skipVersion: Skip this version } }真实文件共有 25 个顶级命名空间覆盖全局按钮、错误页、登录注册、编辑器、头部导航、首页、工作流仪表盘、组件管理、日期选择器等全部界面区域globals · errorBoundary · viewer · app · stripe · openApi · slack · googleSheets zendesk · profile · verificationSuccessPage · loginSignupPage · editor · header homePage · workflowsDashboard · confirmationPage · onBoarding · redirectSso · oAuth2 widgetManager · widget · leftSidebar · datepicker · notifications翻译时的三条纪律只改值、不动键key 是前端代码里t(...)查表的“身份证”改名会导致文案丢失并回退到英文保留插值占位符部分值包含{{xxx}}模板变量例如 Slack 授权文案中的{{whiteLabelText}}见 en.json 的slack命名空间翻译时必须原样保留否则运行期无法注入动态内容尽量同步最新键仓库里en.json是键最全的母本25 个顶级命名空间而部分旧语言文件缺少后来新增的命名空间如法语/德语文件目前为 21 个。得益于 i18next 的fallbackLng: en配置见 frontend/src/index.jsx缺失的键会自动显示英文而非空白——但若要保证完整体验翻译时应以最新en.json为基准补齐。第 4 步在languages.json中注册语言翻译完成后还需要把语言登记到 frontend/assets/translations/languages.json。官方要求为每种语言添加一个包含三个键值对的对象字段含义示例法语lang语言名称英文表述用于与语言列表展示Frenchcode语言代码须与 JSON 文件名一致frnativeLang该语言的母语名称用于语言选择器中以母语展示Françaislanguages.json整体结构是一个languageList数组。以“英语 法语”为例{ languageList: [ { lang: English, code: en, nativeLang: English }, { lang: French, code: fr, nativeLang: Français } ] }仓库当前真实的注册清单即为该结构的完整范例读者可打开 languages.json 对照{ languageList: [ { lang: English, code: en, nativeLang: English }, { lang: French, code: fr, nativeLang: Français }, { lang: Spanish, code: es, nativeLang: Español }, { lang: Italian, code: it, nativeLang: Italiano }, { lang: Indonesian, code: id, nativeLang: Bahasa Indonesia }, { lang: Ukrainian, code: uk, nativeLang: Українська }, { lang: Russian, code: ru, nativeLang: Русский }, { lang: German, code: de, nativeLang: Deutsch }, { lang: Chinese, code: zh, nativeLang: Chinese } ] }完成以上四步后新语言即已可被 ToolJet 前端识别与加载。docs/static/img/l10n/list.png展示了语言选择器的实际交互形态——注意每条语言同时展示了lang英文名与nativeLang母语名两行文本这与 LanguageSelection.jsx 的渲染逻辑一一对应源码视角新语言如何被前端“看见”为了让新加的翻译真正生效需要理解前端三条调用链。以下均可直接在仓库中查阅源码验证。① i18next 的初始化与加载路径在 frontend/src/index.jsx 中应用从服务端拉取的public_config读取LANGUAGE配置作为初始语言缺省en然后初始化 i18nextconst language config.LANGUAGE || en; const path config?.SUB_PATH || /; i18n .use(Backend) .use(initReactI18next) .init({ load: languageOnly, fallbackLng: en, lng: language, backend: { loadPath: ${path}assets/translations/{{lng}}.json, }, });几个关键配置项的含义load: languageOnly只按两位语言代码匹配例如浏览器上报en-US也只会去加载en.json不会尝试加载en-US.jsonfallbackLng: en当前语言缺失某条文案时自动回退英文这正是“漏键不报错、只显示英文”的兜底机制loadPath基于 HTTP 的后端按需加载模板{{lng}}在运行期替换为语言代码如fr因此只要 JSON 文件放在该目录、命名正确前端无需重新注册资源映射pathSUB_PATH当 ToolJet 部署在子路径sub-path下时翻译文件同样走子路径前缀保证静态资源可访问。② 语言选择器的清单读取与切换frontend/src/_components/LanguageSelection.jsx 是整个本地化 UI 的核心实现包含三段逻辑拉取清单组件挂载时fetch(/assets/translations/languages.json)将languageList存入引用当前语言回显以i18n.language缺省en在清单中查找当前语言找不到则回退到英文条目实时切换onLanguageSelection中调用i18n.changeLanguage(lang.code)完成全局语言切换界面上所有经useTranslation()与t(...)取值的文案会立即重渲染。组件还提供了语言搜索能力用户可按lang、nativeLang或code的前缀过滤语言列表LanguageSelection.jsx例如输入fr即可快速定位法语。③ 页面中“取文案”的方式业务组件通过react-i18next的useTranslation()获取t函数来读取翻译并支持“命名空间 key 英文兜底默认值”的写法。例如语言选择器自身的标题const { t } useTranslation(); // 读取 header.languageSelection.changeLanguage缺省英文 Change language t(header.languageSelection.changeLanguage, Change language);对应的 key 定义位于en.json的header.languageSelection命名空间header: { languageSelection: { changeLanguage: Change language, searchLanguage: Search language } }这解释了为什么新增语言的 JSON 文件必须保留与en.json完全一致的键结构——t()的路径就是 JSON 里的嵌套路径任何一个层级写错都会导致取不到值而回退英文。设置部署实例的默认语言LANGUAGE 环境变量除了用户在界面手动切换外ToolJet 还允许自托管实例的管理员通过环境变量设定全站默认语言。在官方部署环境变量文档 docs/docs/setup/env-vars.md 中给出了如下说明变量说明LANGUAGE期望的默认语言代码LANGUAGE_CODE例如将实例默认界面语言设为法语设置LANGUAGEfr即可运行时前端启动逻辑会读取该值作为i18n.init的lng对应 frontend/src/index.jsx 的config.LANGUAGE。该变量与languages.json中的code必须一一对应未登记的语言代码不会命中任何翻译文件。注意官方文档注明云版本cloud上不开放自定义默认语言的选项此项仅适用于可自行控制环境变量的自托管部署。贡献前自检清单与常见陷阱向官方仓库提交本地化改动前建议逐项核对文件名是否使用 ISO 639-1 两位语言代码如fr.json、zh.json键完整性新文件是否以当前最新en.json为基准整体复制再逐条翻译JSON 合法性翻译文本中的引号、换行需要正确转义文件必须是合法 JSON可先用JSON.parse校验避免拖拽符号破坏结构键未被改写t(header.languageSelection.changeLanguage, ...)这类调用路径对应的嵌套结构未被改动插值占位符保留{{whiteLabelText}}一类模板变量保持原样注册清单languages.json的languageList中已添加含lang/code/nativeLang的对象且code与文件名严格一致本地验证本地启动frontend后打开语言选择器确认新语言出现在列表中、切换后无大面积英文回退个别回退属于“键未翻译”应在语言文件中补齐。关于“浏览器语言自动检测”的现状说明官方文档正文中有一段被注释掉HTML 注释区块内的描述ToolJet 会自动检测浏览器默认语言并切换若浏览器语言不可用则回退英文。在本文所依据的仓库版本中该行为尚未作为正式文档承诺对外发布相关章节仍处于注释状态且前端初始语言实际由服务端下发的LANGUAGE配置决定。因此社区贡献者在本地开发时可先通过语言选择器手动切换验证不必依赖浏览器自动检测。小结ToolJet 的本地化贡献流程可以被精确概括为一条命令链级别的操作闭环在 frontend/assets/translations 创建语言代码.json复制 en.json 全部内容作为翻译母本按“只改值、不动键、保留插值占位符”的原则逐条翻译在 languages.json 中追加{ lang, code, nativeLang }注册项。后端兜底由 frontend/src/index.jsx 的 i18next 初始化负责缺省英文、HTTP 按需加载界面展示由 LanguageSelection.jsx 负责清单拉取、搜索、changeLanguage即时切换。整个过程中无需触碰任何组件源码风险低、易评审是进入 ToolJet 社区贡献的最佳切入点之一。【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网