鸿蒙 PC Markdown 编辑器 ArkUI 资源本地化:从字符串目录到 Ability 生命周期的工程方法

📅 2026/7/26 2:55:37
鸿蒙 PC Markdown 编辑器 ArkUI 资源本地化:从字符串目录到 Ability 生命周期的工程方法
鸿蒙 PC Markdown 编辑器 ArkUI 资源本地化从字符串目录到 Ability 生命周期的工程方法桌面编辑器的本地化最容易在“看起来已经翻译”时留下隐患工具栏是中文弹窗仍是英文启动时正确回到前台后失步资源键漏了一项只有某个冲突流程才暴露为了翻译错误消息又把文件服务与 UI 强耦合。鸿蒙 PC 应用需要把语言资源当作可验证的工程资产而不是在 ArkTS 中到处写条件表达式。OhMarkdown 的 ArkUI 本地化实现已进入公开仓库 https://gitcode.com/VON-/codex_md_oh核心提交为ed13ee0后续 PC 布局复核基线为0d8d38b。本文聚焦原生侧base与zh_CN资源目录、EntryAbility生命周期、AppStorage传播、动态状态的展示边界、资源一致性测试和自由窗口验证。ArkWeb 的 CodeMirror 词典与运行时重配另有独立实现但本文会说明两者怎样在边界处握手。先定义 ArkUI 本地化的责任边界ArkUI 负责活动栏、文件面板、搜索、大纲、设置、标签栏、冲突操作和状态栏。这些内容多数是稳定产品文案应该进入资源文件。文档正文、文件名、相对路径、编码名、LF/CRLF、底层系统错误和用户输入不属于翻译资源它们必须原样保留或通过结构化参数展示。这种划分避免两个极端。把所有字符串都写进资源会迫使文件服务依赖 UI 上下文也容易在格式化错误中丢失诊断细节把所有文案都写在 ArkTS 里则无法由系统根据语言自动解析资源键也无法静态比对。合理做法是让稳定交互词汇资源化让动态事实保持事实再在展示层组合。当前交付支持英文 base 与简体中文 zh_CN。base是默认资源也是未知语言和资源缺失时的回退zh_CN是已验证的中文集合。项目没有宣称繁体中文、法语等已经支持未知 Preferences 值回退跟随系统Web 词典未知标签回退英文。资源目录是平台契约英文资源位于entry/src/main/resources/base/element/string.json简体中文位于entry/src/main/resources/zh_CN/element/string.json。二者使用相同name只改变value。例如搜索能力在两套资源中保持一一对应{string:[{name:search_panel,value:Search},{name:search_current_document,value:Document},{name:search_workspace,value:Workspace},{name:quick_open,value:Quick Open},{name:match_case,value:Case},{name:match_whole_word,value:Whole},{name:use_regular_expression,value:Regex}]}对应中文不是逐字机械翻译而是符合编辑器语境的术语{string:[{name:search_panel,value:搜索},{name:search_current_document,value:当前文档},{name:search_workspace,value:工作区},{name:quick_open,value:快速打开},{name:match_case,value:区分大小写},{name:match_whole_word,value:全词匹配},{name:use_regular_expression,value:正则表达式}]}资源名采用稳定语义而非页面位置。match_case不叫search_row_first_text因为同一选项同时服务当前文档与工作区搜索open_document与open_action分开是因为一个用于完整入口一个用于紧凑工具栏。稳定命名使布局调整时不必重命名资源也让测试能按语义判断缺失项。资源覆盖必须包含低频危险流程本地化不能只覆盖首屏。OhMarkdown 把外部修改、恢复、保存中断、混合换行等低频但高风险流程也纳入资源。中文资源中真实存在external_changes_message、use_disk_version_message、interrupted_save_message、restore_backup_action和mixed_line_ending_message等键。这些流程的文案质量直接影响用户是否会丢文档。例如“使用磁盘版本”必须明确未保存本地修改会被替换“恢复上一版本”必须与“保留当前版本”区别清楚。只翻译按钮而漏掉解释文本会让中文用户在最需要判断时读到混合语言。资源键一致性检查能发现漏键却不能判断语义质量因此仍需要产品评审和设备截图。设置项也使用资源自动保存三种策略、图片资源目录、拖放复制/移动/仅引用、界面语言三种模式。资源层只描述选项不改变枚举值。内部AutoSavePolicy.AFTER_DELAY、AssetDropMode.REFERENCE和ApplicationLanguage.SYSTEM保持稳定英文标识避免翻译影响持久化兼容。组件只引用资源不复制文案ArkUI 组件通过$r(app.string...)获取 Resource并把 Resource 继续传给 Builder。按钮、文本和无障碍名称共用同一资源来源减少视觉文字与辅助功能文字不一致的概率。BuilderprivateactivityButton(icon:Resource,label:Resource,panel:string){Button(){SymbolGlyph(icon).fontSize(21).fontColor([this.activePanelpanelthis.sidebarOpen?#087A63:$r(app.color.workspace_text_secondary)])}.type(ButtonType.Normal).width(36).height(36).accessibilityText(label).onClick(()this.selectPanel(panel))}同一个label既不需要在 Builder 内判断语言也不会在按钮无文字时失去可访问名称。图标按钮的视觉表达稳定但屏幕阅读器会根据资源配置朗读“文件”“搜索”或英文对应词。若开发者在.accessibilityText里另写硬编码英文截图看不出问题辅助功能树却会立即暴露。模式按钮同样传 Resource不把“源码、分栏、预览”绑定到内部source/split/preview。内部模式字符串用于协议显示资源用于人机界面两者各自稳定。这是国际化不会污染业务状态机的关键边界。Ability 创建时建立初始语言事实应用启动时EntryAbility.onCreate从 ResourceManager 同步读取当前 locale并写入AppStorage。工作台使用StorageProp(language)订阅。这里读取的是平台已经解析后的当前语言不是 Preferences 中的用户策略。onCreate(want:Want,launchParam:AbilityConstant.LaunchParam):void{constcolorModethis.context.resourceManager.getConfigurationSync().colorMode??ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT;constlanguagethis.context.resourceManager.getConfigurationSync().locale??en-US;AppStorage.setOrCreate(colorMode,colorMode);AppStorage.setOrCreate(language,language);}平台首选语言已在上一次选择中通过i18n.System.setAppPreferredLanguage设置因此 ResourceManager 是当前资源配置的事实来源。若读取不到 locale英文 base 是明确回退而不是让空字符串向下传播。颜色和语言一并进入 AppStorage但两者的业务更新函数分开避免切换语言时意外重设主题。onWindowStageCreate只加载pages/Index不在窗口层重复应用语言。资源配置应在页面构建前可用若把语言设置放到页面首次渲染后才读取会先显示英文再闪成中文PC 大窗口尤其明显。配置更新与回到前台的双保险系统语言可能在应用运行中改变。Ability 的onConfigurationUpdate接收新配置只在newConfig.language存在时更新语言缺失字段不应把当前值覆盖为默认。应用从后台回到前台时再从 ResourceManager 读取一次弥补后台配置回调时序差异。onConfigurationUpdate(newConfig:Configuration):void{constcolorModenewConfig.colorMode??ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT;AppStorage.setOrCreate(colorMode,colorMode);if(newConfig.language){AppStorage.setOrCreate(language,newConfig.language);}}onForeground():void{constlanguagethis.context.resourceManager.getConfigurationSync().locale??en-US;AppStorage.setOrCreate(language,language);}双入口不会产生两套业务逻辑。它们只更新同一个 AppStorage 键工作台的 Watch 再同步 Web。重复写入相同值的成本很低远小于因漏通知导致 ArkUI 与 ArkWeb 分裂的风险。当前设备闭环验证的是应用内选择和强制停止重启。系统设置页面切换语言后的完整真机行为仍需要鸿蒙 PC 真机复核。实现覆盖生命周期并不等于所有设备路径已测试工程文章必须把代码能力与实测证据分开陈述。用户策略与当前资源语言必须分离工作台同时持有applicationLanguage和language。前者是SYSTEM、SIMPLIFIED_CHINESE、ENGLISH中之一用于设置按钮选中态并写入 Preferences后者是平台当前解析出的 locale用于决定状态栏显示和通知 ArkWeb。StorageProp(language)Watch(onLanguageChanged)privatelanguage:stringen-US;StateprivateapplicationLanguage:ApplicationLanguageApplicationLanguage.SYSTEM;privateonLanguageChanged():void{this.setEditorLanguage(this.language);}中文系统下选择“跟随系统”时applicationLanguage是defaultlanguage可能是zh-Hans-CN。若只保留一个字段就无法既正确高亮策略又正确加载当前资源。系统语言从中文改为英文时前者不变后者变化这是跟随系统真正应有的状态转换。初始化时 Preferences 异步恢复前者Ability 已经提供后者。读取失败只让按钮回退跟随系统不阻塞编辑器 Ready。显式选择时先更新平台资源再同步两个字段随后异步持久化策略。状态关系清晰后重启与运行时切换才不会互相覆盖。动态状态不应强行进入静态资源状态栏包含稳定状态和动态详情。Ready、Modified、Saved、Auto saved等可以在展示层映射Opened docs/plan.md:430、Save failed: ...、系统异常和文件名包含动态参数不适合简单做整句字符串匹配。privategetOperationStatusText():string{if(resolveEditorLanguage(this.language)!zh-CN){returnthis.operationStatus;}if(this.operationStatusReady)return就绪;if(this.operationStatusModified)return已修改;if(this.operationStatusOpened)return已打开;if(this.operationStatusSaved)return已保存;if(this.operationStatusAuto saved)return已自动保存;if(this.operationStatusRecovered)return已恢复;returnthis.operationStatus;}当前实现优先完成常见稳定状态其他详情原样保留。它不是终极国际化架构但比在服务层到处读取资源安全。后续更合理的方向是结构化状态例如{ code: SEARCH_RESULT_OPENED, path, line }展示层再用资源模板格式化。迁移必须逐步进行因为保存、恢复和冲突状态关系到文档安全不能为了翻译一次性重写可靠性链路。字数也属于动态展示。中文显示${wordCount} 字英文根据 1 或其他数值选择word/words。它说明不同语言不总能靠同一静态字符串拼接真正扩展到更多语言时应使用平台复数资源而不是不断增加 if 分支。资源键一致性是最低自动化门槛两个 JSON 能解析并不代表资源完整。验证脚本应提取string数组中的name比较集合差异同时检查重复键和空值。最终测试报告确认 base 与 zh_CN 键集合完全一致两个 JSON 均解析通过。资源集合测试能抓住三类常见回归开发新按钮只添加 base中文键拼写不同导致运行时回退删除组件后只清理一套资源。它不能判断“Whole”是否应翻译为“全词匹配”也不能发现中文过长造成裁切所以仍需 UI 设备测试。ArkTS 单元测试还覆盖语言解析default对应 SYSTEMzh-Hans-CN对应简体中文en-US对应英文未知fr-FR回退 SYSTEM跟随系统在中文系统中解析为中文固定英文不受系统中文影响Web 映射只输出zh-CN或en。这些纯函数测试让资源层与运行时的边界可重复验证。长文本会直接改变 PC 布局同一语义在不同语言中宽度差异很大。英文搜索选项是Case / Whole / Regex中文是“区分大小写 / 全词匹配 / 正则表达式”。侧栏可缩放到 220 vp 后三项固定单行会裁切最右文字。这个问题不是翻译错误而是国际化触发的响应式布局错误。修复提交0d8d38b使用 300 vp 稳定断点小于 300 时前两项一行正则单独一行达到 300 时恢复三项单行。每个 Text 自身maxLines(1)由容器决定换行而不是让文字在复选框旁随机折行。中文 220 vp 和 408 vp 均在模拟器辅助功能树中获得完整边界。这说明资源验收必须覆盖最短与最长文案、最窄与常用窗口、显示缩放和无障碍文本。只在英文默认宽度截图通过无法证明中文 PC 体验。资源层本身不控制布局但本地化交付必须把布局证据纳入完成定义。真实应用截图如何验证资源链路下面是 MateBook Pro 2in1 模拟器中的简体中文工作台。文件、搜索、设置、工具栏、状态栏和编辑器占位文案使用同一语言语言分段按钮显示“跟随系统 / 简体中文 / English”。图片来自应用内部不是设计稿。截图能够证明可见结果但不能单独证明策略持久化和辅助功能状态。因此设备闭环还读取辅助功能树确认“跟随系统 selectedtrue”强制停止应用再次启动后读取相同状态。英文模式也完成重启验证原生工作台与 Web 编辑器同步英文。布局测试继续覆盖默认 264 vp、最小 220 vp、拖动后 392 vp、最大 480 vp。资源文本没有造成标签栏、搜索选项或设置分段控件互相遮挡。系统原生标题栏右侧留白仍保留为窗口拖动区域它不是应用资源遗漏也不应被应用内容填满。自动化、构建与设备结果语言交付时 Playwright30/30通过覆盖 Web 运行时切换ArkTSUnitTestBuild通过覆盖语言纯函数Debug HAP 与 ohosTest HAP 构建通过MateBook Pro 2in1 模拟器 ohosTest7/7。资源键集合无差异git diff --check通过。PC 布局修复后再次执行全套验证。最终 Debug HAP 大小 1,520,352 字节SHA-256 为367ab8650479aa1fa8fe73bd1ebadd9a53f46659c850c2e388fc799d5cb88e5bohosTest HAP 大小 2,360,824 字节SHA-256 为b7230037b51044fe16168d2c835fb891e1c70f675941a1046165bc895217592c。哈希用于定位本次测试产物两份均为未签名包不能替代发布签名与商店验收。测试分层各自回答不同问题JSON 集合检查资源完整单元测试证明映射规则Playwright 证明 Web 状态不丢HAP 构建证明 ArkTS 和资源可打包ohosTest 证明设备服务路径模拟器截图与辅助功能树证明真实 PC 界面。把它们合并成一个“测试通过”会掩盖证据边界。性能、安全与离线属性静态资源由 HAP 打包不访问远程翻译服务。切换语言不会上传文档、文件名或使用行为也没有新增网络权限。资源文件只包含产品文案不包含用户数据。未知语言回退 base避免动态下载失败造成空界面。运行时切换主要是平台资源重配和固定数量组件更新复杂度与界面组件数相关与 Markdown 文档长度无关。ArkUI 不复制文档缓冲区Ability 只传播短语言标签。资源体积的增量很小当前无需引入按需下载更多语言到来时再根据 HAP 体积测量决定。资源值不能进入文件路径、命令 ID 或 Preferences 键。翻译人员改变“快速打开”文本不应改变SearchPanelMode.QUICK_OPEN改变“仅引用”文本不应改变AssetDropMode.REFERENCE。这一隔离是安全性和升级兼容性的共同基础。失败路径与降级策略资源不存在时平台回退 base至少保留可操作英文。Preferences 损坏或读取失败时回退 SYSTEM不把未知值交给平台。HostContext 不可用时不尝试切换。平台更新失败时维持旧界面并显示失败状态。设置已应用但 flush 失败时保留当前会话语言同时告诉用户无法跨重启保存。Ability 配置更新没有 language 字段时保持旧值前台再同步 ResourceManager。Web 尚未 Ready 时工作台在onEditorReady再发一次当前语言。所有失败路径都不能阻止文件打开、编辑、保存和恢复语言表现层优先降级文档事实层继续运行。对资源 JSON 的错误应尽量在构建前发现。解析失败、重复键、集合差异都应该成为质量门禁而不是靠运行时某个低频弹窗触发。中文文本过长则通过 220 vp 侧栏、窄窗口和辅助功能边界测试发现。术语治理与后续维护本地化规模变大后术语一致性比新增翻译速度更重要。工作区、快速打开、源码、分栏、预览、全词匹配、外部修改、磁盘版本等词应保持稳定。资源名作为技术词典索引值作为产品术语两者都需要代码审查。新增功能的完成清单应包含base 和 zh_CN 同时新增按钮与 accessibilityText 引用资源最窄侧栏和窗口检查动态参数不硬拼Web 命令如有对应文本同步词典资源集合测试通过至少一条真实设备路径。这样国际化不会成为开发结束后的补丁。未来增加繁体中文或日文时应创建独立资源目录、术语表、文本长度测试和设备验证而不是把简体中文当作所有中文地区的默认正确答案。系统default策略仍应原样保存让每台鸿蒙 PC 按自己的语言解析。结论OhMarkdown 的 ArkUI 本地化把资源目录、领域枚举、Ability 生命周期、AppStorage、组件引用、动态状态边界和测试证据连成一条可维护路径。ed13ee0完成中英文基础能力0d8d38b进一步解决中文长标签在最窄侧栏中的裁切。最终自动化30/30、ohosTest7/7、资源集合一致和模拟器重启证据共同说明它不是只在截图里成立的翻译。对鸿蒙 PC Markdown 编辑器而言好的本地化不会侵入文件协议也不会重建编辑器或依赖网络它让稳定文案由平台资源管理让动态事实保持真实并在自由窗口、键鼠和辅助功能环境中都能完整表达。这才是后续扩大语言数量时可以继续演进的原生基础。