ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

OHIF Viewer 国际化(i18n)完全指南:语言切换、翻译管理与自定义语言包

2026/9/19 19:18:46 拓冰建站 浏览量
OHIF Viewer 国际化(i18n)完全指南:语言切换、翻译管理与自定义语言包 OHIF Viewer 国际化i18n完全指南语言切换、翻译管理与自定义语言包【免费下载链接】ViewersOHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages项目地址: https://gitcode.com/GitHub_Trending/vi/ViewersOHIF Viewer 内置了完善的国际化i18n能力用户可以在偏好设置或通过 URL 参数随时切换整个 Viewer 的显示语言。本文以官方用户指南中的 Language 文档 为主线结合ohif/i18n包源码与 Internationalization 开发文档系统讲解语言切换的两种方式、底层语言检测与持久化机制、t翻译函数的使用、命名空间Namespace体系以及如何扩展已有语言或新增一门全新语言帮助你在一小时内为 OHIF 接入或定制自己的多语言方案。概述OHIF Viewer 支持哪些语言能力OHIF Viewer 原生支持国际化internationalization并允许用户设置 Viewer 的整体显示语言。需要特别说明的是当前项目并没有为所有组件和所有语言提供完整的翻译——部分组件可能只有英文部分语言可能只覆盖了高频词条。不过OHIF 的翻译架构是开放且可扩展的你可以按照开发者指南轻松添加键值key-value翻译对逐步补全缺失的部分。从源码层面看整个国际化体系建立在i18next生态之上通过 npm 包ohif/i18n即本仓库platform/i18n目录提供统一的 i18n 实例、语言检测器和多种语言资源。该包的核心导出在 platform/i18n/src/index.js 中定义包括i18n初始化好的 i18next 实例供t()翻译函数和changeLanguage()语言切换使用initI18n()可接受自定义语言检测配置重新初始化的方法addLocales()动态注册新语言资源availableLanguages当前可用的语言列表defaultLanguage/currentLanguage默认语言与当前语言信息。运行时切换语言两种开箱即用的方式根据官方文档普通用户切换 OHIF Viewer 的语言主要有两种入口。方式一通过偏好设置弹窗点击 Viewer 顶栏的Preferences偏好设置菜单在User Preferences Modal中选择目标语言并提交即可立即生效。这一交互在 UI Service 文档 中有对应的实现证据弹窗组件收到currentLanguage、availableLanguages、defaultLanguage三个属性用于渲染语言下拉框提交时调用i18n.changeLanguage(state.language.value)完成语言切换并同步hotkeysManager处理快捷键偏好。方式二URL 查询参数lng无需任何点击直接在浏览器地址栏的 URL 中追加lng查询参数即可强制指定语言https://your-viewer.example.com/viewer/...?lnges https://your-viewer.example.com/?lngzh https://your-viewer.example.com/?lngpt-BR该参数由 i18next 的语言检测插件i18next-browser-languageDetector解析。除了es、zh、pt-BR这类已有语言代码你甚至可以直接传入test-LNG详见下文「测试语言」小节来验证翻译覆盖情况。语言检测与持久化浏览器如何记住你的选择语言并非只在打开页面那一刻被决定一次——OHIF 会在加载时按顺序探测用户语言并在切换后记住偏好。这一逻辑全部封装在 platform/i18n/src/config.js 的detectionOptions中const detectionOptions { // 检测顺序从何处探测用户语言 order: [querystring, cookie, localStorage, navigator, htmlTag, path, subdomain], // 各类来源对应的查询键 lookupQuerystring: lng, lookupCookie: i18next, lookupLocalStorage: i18nextLng, lookupFromPathIndex: 0, lookupFromSubdomainIndex: 0, // 缓存用户语言偏好到哪些位置 caches: [localStorage, cookie], excludeCacheFor: [cimode], // 不持久化的语言如开发用的 cimode // 可选带 lang 属性的 html 标签默认取 document.documentElement htmlTag: document.documentElement, };几点值得注意的细节优先级querystringURL 参数优先级最高navigator浏览器语言排第四即用户手动指定的语言始终优先于浏览器默认语言持久化切换语言后偏好会被同时写入 cookie键名i18next和localStorage键名i18nextLng下次访问自动生效可定制initI18n()接受一个新的检测配置作为参数你可以覆盖order、缓存键名等所有选项。同时请注意从config.js的实现可以看到debugMode由构建期环境变量REACT_APP_I18N_DEBUG控制NODE_ENV ! production时才可能开启。底层初始化i18n 实例是如何装配的ohif/i18n的核心初始化逻辑位于 platform/i18n/src/index.js 的initI18n()函数它根据是否启用 Locize 走两条路径但共用相同的 i18next 配置要点fallbackLng: en-US任何语言缺少某条翻译时回退到美式英语keySeparator: false禁用 i18next 默认的键分隔符避免与翻译键中的字符冲突interpolation.escapeValue: false由于 React 默认会转义输出关闭 i18next 的二次转义插件链LanguageDetector语言检测→initReactI18next接入 React。使用本地翻译文件时所有语言资源通过locales目录导入见 platform/i18n/src/locales/index.js该文件由pullTranslations.sh脚本动态生成。实例初始化完成后还会暴露几个实用 APIi18n.initializing initI18n(); i18n.initI18n initI18n; i18n.addLocales addLocales; i18n.availableLanguages getAvailableLanguagesInfo(locales); i18n.defaultLanguage { label: getLanguageLabel(en-US), value: en-US }; i18n.currentLanguage () ({ label: getLanguageLabel(i18n.language), value: i18n.language });其中语言代码与显示名称的映射表如zh: Chinese、pt-BR: Portuguese (Brazil)、en-US: English (USA)定义在 platform/i18n/src/utils.js 的languagesMap中getAvailableLanguagesInfo()会基于该表把locales目录下的每个语言文件夹转换成{ value, label }列表——这正是偏好设置弹窗中语言下拉框的数据来源。翻译工作原理认识t函数OHIF 的翻译机制极其简单页面上的每一段文字只要被包进t()函数就会自动在语言资源中查找对应的翻译。官方文档给出了一组直观的前后对比改动前divmy translated text/div改动后div{t(my translated text)}/div只要translation.json中存在与 HTML 内容匹配的键keyt()就会自动替换为对应语言的文案。在 React 组件中使用通过react-i18next提供的useTranslationHook 可以轻松拿到t函数OHIF Viewer 已在应用根部挂载了共享的I18nextProvider扩展组件无需再手动挂载import React from react; import { useTranslation } from react-i18next; function MyComponent() { const { t } useTranslation(); return p{t(my translated text)}/p; }在非 React 环境普通 JS中使用ohif/i18n也导出一个可直接调用的T函数适用于工具脚本、纯逻辑模块等场景import { T } from ohif/i18n; console.log(T(my translated text)); console.log(T($t(Common:Play) my translated text)); // 跨命名空间引用在 OHIF Viewer 之外使用如果你的 React 应用完全独立于 OHIF Viewer可以自行挂载共享的 i18n 实例import i18n from ohif/i18n; import { I18nextProvider } from react-i18next; import App from ./App; I18nextProvider i18n{i18n} App / /I18nextProvider;挂载之后ohif/i18n中的全部语言资源即可按上述方式使用。命名空间Namespace翻译文件如何组织为了避免把所有翻译堆进一个巨大文件OHIF 使用Namespace命名空间按语义和用途拆分翻译。在ohif/i18n中locales目录下每个语言文件夹里的每一个.json文件自动成为一个命名空间。以仓库中 en-US 目录 为例包含约 30 个命名空间常见的有Buttons所有按钮文字Common可复用的通用术语如t($t(common:image))CineDialogCine 播放器对话框内的提示文字HeaderOHIF 顶部导航栏相关MeasurementTable测量表组件UserPreferencesModal偏好设置弹窗Modals通用弹窗文字PatientInfo患者信息悬浮层SidePanel侧面板ToolTip工具提示StudyList/StudyBrowser工作列表与检查浏览器。跨命名空间引用i18next 支持在任意命名空间中引用其他命名空间的翻译语法为$t(Namespace:Key)$t(Common:Reset)这让你可以在Buttons中复用Common里已定义好的词条避免重复维护。扩展已有语言按国家/地区/机构定制子语言实际部署中常有这样的需求同一种语言不同国家、地区甚至不同医院的术语习惯不同例如英式英语与美式英语。此时无需整包重建语言只需在已有语言文件夹内新建一个以两个字符命名的子文件夹ohif/i18n会自动合并。src/locales/ index.js |-- en |-- Buttons.json index.js |-- UK |-- Buttons.js index.js |-- US |-- Buttons.js index.js合并规则子语言en-US、en-UK的属性会与基础语言en合并缺失的键通过 i18next 的 fallback 机制自动回退到en。你需要在index.js中按如下结构导出所有 JSON 文件{ en: { NameSpace: { keyWord1: keyWord1Translation, keyWord2: keyWord2Translation, keyWord3: keyWord3Translation, }, }, en-UK: { NameSpace: { keyWord1: keyWord1DifferentTranslation, // 仅覆盖需要差异化的键 }, }, }动态扩展语言由于ohif/i18n暴露了 i18next 实例你也可以在运行时通过addResourceBundle按需添加或修改资源适合扩展/插件在初始化时注入自己的翻译import i18n from ohif/i18n; i18n.addResourceBundle(pt-BR, Buttons, { Angle: Ângulo, });新增一门完整语言要为一个全新语言建立完整翻译官方推荐两种途径。途径一在项目中通过addLocales注入构造一个以语言代码为顶层键、命名空间为二级键、键值对为三级结构的对象下例为法语const newLanguage { fr: { Commons: { Reset: Réinitialiser, Previous: Précédent, }, Buttons: { Rectangle: Rectangle, Circle: Cercle, }, }, };然后调用addLocales注册import { addLocales } from ohif/i18n; import locales from ./locales/index.js; addLocales(locales);最省力的做法是直接复制locales目录下某个语言的.json文件及其index.js导出器保持键和命名空间不变只替换翻译值。也可以参照 platform/i18n/src/locales/zh 或 en-US 的目录结构理解每种语言文件夹内index.js与各 JSON 命名空间的装配方式。途径二贡献回社区推荐为ohif/i18n提交 Pull Request把翻译分享给整个 OHIF 社区。项目通过Locize平台进行众包翻译管理翻译项目完成后经审核合并进主项目该语言会立刻可用于所有 OHIF 项目——既支持通过 Locize CDN 加载也支持直接复制进ohif/i18n包由最终用户在自己的域名下托管。测试语言test-LNG快速验证翻译覆盖仓库的 test-LNG 目录 是一个专门的测试语言。启用它例如在 URL 中追加?lngtest-LNG后页面上的所有元素都会被追加 Test {} 前缀——例如Study list会变成Test Study list。这让你一眼就能看出哪些文案已经接入t()翻译、哪些仍是硬编码是审计翻译覆盖率最快捷的手段。调试与 Locize 云端翻译集成本地调试翻译设置环境变量REACT_APP_I18N_DEBUGtrue后启动开发服务器即可在控制台看到完整的翻译加载与匹配日志REACT_APP_I18N_DEBUGtrue yarn run dev对应地platform/i18n/src/config.js 中的debugMode会决定 i18next 的debug开关。接入 Locize 翻译管理ohif/i18n与 Locize 深度集成相关选项见 platform/i18n/src/index.js启用后i18next 会通过i18next-locize-backend从 Locize 项目加载翻译、通过locize-editor提供页面内联编辑能力在 URL 加?locizetrue唤起、通过locize-lastused记录翻译条目使用时间以便清理。三个关键环境变量如下表所示也可参考 环境变量文档环境变量说明默认值USE_LOCIZE是否启用 Locize 作为翻译后端false默认使用本地文件LOCIZE_PROJECTID用于拉取翻译的 Locize 项目 ID无LOCIZE_API_KEY启用 Locize 实时编辑翻译所需的 API Key无切勿提交到仓库注意USE_LOCIZE与LOCIZE_API_KEY均为构建期环境变量未设置或设置不完整时会自动回退到本地翻译文件模式。当 Locize 编辑器中保存了翻译时onEditorSaved回调会通过i18n.reloadResources(lng, ns)重载对应语言的命名空间并通过bindI18n: languageChanged editorSaved触发 React 重渲染。从 Locize 拉取翻译更新仓库内的 pullTranslations.sh 脚本展示了本地语言资源与 Locize 的同步流程先把test-LNG临时备份清空src/locales后调用npx locize --config-path ../../.locize download --ver latest下载最新翻译再运行node ./writeLocaleIndexFiles.js生成各语言与总入口的index.js最后还原test-LNG目录。当前仓库内置的语言与翻译现状从 platform/i18n/src/locales/index.js 可以看到本仓库ohif/i18n目前内置了以下语言命名空间文件的数量和完整度因语言而异en-US英语/美国默认与回退语言命名空间最全zh中文、ja-JP日语、ko未内置但languagesMap中已登记es西班牙语、fr法语、de德语、pt-BR葡萄牙语/巴西、it意大利语等ru俄语、ar阿拉伯语、nl荷兰语、tr-TR土耳其语、vi越南语test-LNG测试语言每种语言的文件夹内由若干命名空间 JSON 文件加一个index.js导出器组成。需要强调的是不同语言文件夹的命名空间数量并不相同例如en-US约 30 个命名空间而zh约 26 个这正是文档开头所提醒的并非所有组件、所有语言都有完整翻译的直接体现——缺口部分会通过fallbackLng回退到en-US展示。结语OHIF Viewer 的国际化方案以 i18next 为内核通过ohif/i18n包提供了从语言检测、偏好持久化、t()函数翻译到命名空间管理、Locize 众包协作的一整套能力。作为开发者你既可以通过偏好设置或lng查询参数立刻切换语言也可以借助addLocales、addResourceBundle和子语言扩展机制在几分钟内接入自己的语言包。若想进一步深入推荐继续阅读 Internationalization 开发文档 与 UI Service 文档并结合 i18n 源码 与 locales 目录 进行实践。【免费下载链接】ViewersOHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages项目地址: https://gitcode.com/GitHub_Trending/vi/Viewers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考