你好欢迎来到我的博客我是【菜鸟学鸿蒙】我是一名在路上的移动端开发者正从传统“小码农”转向鸿蒙原生开发的进阶之旅。为了把学习过的知识沉淀下来也为了和更多同路人互相启发我决定把探索 HarmonyOS 的过程都记录在这里。️主要方向ArkTS 语言基础、HarmonyOS 原生应用Stage 模型、UIAbility/ServiceAbility、分布式能力与软总线、元服务/卡片、应用签名与上架、性能与内存优化、项目实战以及 Android → 鸿蒙的迁移踩坑与复盘。内容节奏从基础到实战——小示例拆解框架认知、专项优化手记、实战项目拆包、面试题思考与复盘让每篇都有可落地的代码与方法论。 我相信写作是把知识内化的过程分享是让生态更繁荣的方式。如果你也想拥抱鸿蒙、热爱成长欢迎关注我一起交流进步前言做多语言适配时一个很常见的误区是中文页面已经完成只要把“确定”“取消”“立即体验”翻译成英文国际化就结束了。真正开始切换语言后问题往往才出现中文四个字能放下的按钮英文可能变成二十多个字符某些语言的文本长度进一步增加同一个数字在不同区域使用不同的小数点和分组符号日期顺序也未必都是“年-月-日”。所以多语言适配不能只解决“翻译”还要同时处理资源组织、系统匹配、回退策略、弹性布局以及区域格式化。本文以一个最小的“设置页”为例围绕 HarmonyOS 7 做一次完整拆解把页面中的中文硬编码迁移到资源文件准备中英文资源让 ArkUI 根据语言环境加载对应内容再处理英文文本变长后最容易出现的 UI 问题。按照华为当前版本资料HarmonyOS 7 对应 API 26.0.0官方也建议面向 HarmonyOS 7 升级并适配 26.0.0 开发套件。一、国际化为什么不能从“翻译字符串”开始先看一种非常普通的 ArkTS 写法EntryComponentstruct SettingsPage{build(){Column({space:16}){Text(语言与地区).fontSize(24)Text(切换语言后应用内容将自动更新)Button(立即体验)}.width(100%).padding(20)}}中文环境下这段代码没有明显问题。但一旦应用需要支持英语开发者就很容易继续写成Text(isEnglish?Language Region:语言与地区)页面少的时候似乎还能接受随着业务增长会迅速出现几个问题UI 文案和业务逻辑混在一起新增语言需要不断修改 ArkTS同一个字符串可能散落在多个页面无法充分利用系统的资源匹配机制翻译人员也很难脱离代码维护语言内容。华为官方国际化指南明确提出UI 元素中的字符串、图片等本地化内容应该与代码逻辑分离并放入应用资源中。这样新增地区版本时主要调整资源而不是重新修改业务代码。这也是本文实践的第一个原则ArkTS 负责“页面做什么”资源文件负责“页面说什么”。二、先确认 HarmonyOS 7 下我们到底要用什么本文场景只涉及本地应用资源、ArkUI 页面以及 Localization Kit 的本地化规则不需要网络、相机、定位之类的系统权限。需要关注的部分可以整理成下面这样项目本文使用情况系统背景HarmonyOS 7对应版本API 26.0.0UI 框架ArkUI开发语言ArkTS本地化能力Localization Kit / 应用资源系统字符串访问$r(app.string.xxx)资源位置src/main/resources运行时权限本场景无额外权限核心目标多语言资源匹配、默认资源回退、UI 伸缩适配HarmonyOS 当前官方文档仍将 Localization Kit 作为本地化相关能力入口包含国际化、本地化、资源管理等内容。需要特别区分一个版本问题一些较早的官方国际化示例使用ohos.intl下的NumberFormat、DateTimeFormat。HarmonyOS 后续版本的 API 变更记录已经对ohos.intl中多项接口标记了废弃版本变化因此面向 HarmonyOS 7 新工程时不应该看到旧教程就直接照搬而应该再次以 API 26 当前参考文档确认接口状态。本文的核心 Demo 因此只采用已经能够明确核实的应用资源与 ArkUI 资源引用机制日期、数字部分重点讲设计原则和 API 版本检查方法不把历史接口伪装成 HarmonyOS 7 新推荐方案。三、默认资源不是“可有可无”的兜底目录一个典型的模块资源目录可以这样组织entry └── src └── main └── resources ├── base │ └── element │ └── string.json ├── zh_CN │ └── element │ └── string.json └── en_US └── element └── string.json这里有三个层次base默认资源zh_CN简体中文、中国区域对应资源en_US英语、美国区域对应资源。华为官方“提供多语言资源”文档说明应用资源目录分为默认base目录和带限定词的目录。系统运行时会根据语言、地区等条件寻找最匹配资源如果应用偏好语言以及系统语言都没有找到合适资源最终会加载默认资源。因此默认目录必须准备完整。当前华为官方场景示例的工程结构中也仍可以看到base、en_US、zh_CN这类资源目录组织形式。这个地方比较容易理解错base不是“中文版目录”的另一个名字。它真正承担的是默认资源职责。如果项目规定默认语言是中文可以把完整中文资源放入base也可以同时维护zh_CN用于进一步区分语言/地区场景。但无论如何不建议把base做成一个只有少数几个字符串的残缺目录。四、搭一个最小的中英文资源示例这次把页面定义成一个很小的设置卡片标题一行描述一个主要操作按钮一段比较长的提示文字。这样既能验证资源匹配也容易观察英文文本长度变化。1. 默认资源resources/base/element/string.json{string:[{name:page_title,value:语言与地区},{name:page_description,value:切换语言后应用会使用对应的本地化资源},{name:primary_action,value:立即体验},{name:language_tip,value:界面设计需要同时考虑文本长度、日期、数字和单位等区域差异。}]}2. 中文资源resources/zh_CN/element/string.json{string:[{name:page_title,value:语言与地区},{name:page_description,value:切换语言后应用会使用对应的本地化资源},{name:primary_action,value:立即体验},{name:language_tip,value:界面设计需要同时考虑文本长度、日期、数字和单位等区域差异。}]}3. 英文资源resources/en_US/element/string.json{string:[{name:page_title,value:Language Region},{name:page_description,value:The app uses localized resources that match the selected language.},{name:primary_action,value:Start Exploring},{name:language_tip,value:Layout design should also account for differences in text length, dates, numbers, and measurement units.}]}这里真正需要注意的是三个目录中的资源名称保持一致变化的是资源值。ArkTS 不应该关心当前加载的是立即体验还是Start Exploring页面只需要请求primary_action。五、页面不要再写字符串用$r()引用资源页面可以改成EntryComponentstruct SettingsPage{build(){Column({space:16}){Text($r(app.string.page_title)).fontSize(24).fontWeight(FontWeight.Bold).width(100%)Text($r(app.string.page_description)).fontSize(16).width(100%)Button($r(app.string.primary_action)).width(100%).padding({left:16,right:16,top:12,bottom:12})Text($r(app.string.language_tip)).fontSize(14).width(100%)}.width(100%).padding(20)}}这段代码解决的核心问题不是“让英文显示出来”而是让页面代码与具体语言解耦。$r(app.string.xxx)用来访问应用资源。ResourceManager 官方 API 文档也明确说明可以通过类似$r(app.string.test)的资源地址访问应用资源并可通过.id获得对应资源 ID。这样再新增德语、法语时页面通常不需要出现if(languagede){...}而是继续补充新的限定词资源目录。六、系统到底怎样决定加载哪一份字符串多语言资源并不是简单做一次当前语言 en_US ?官方资源匹配机制会结合应用偏好语言列表以及应用已经提供的限定词资源进行选择。对于字符串可以把匹配过程理解成下面几步根据当前语言与应用资源限定词寻找相关目录按匹配程度对候选资源进行排序从匹配度最高的资源开始寻找目标字符串当前偏好语言没有找到时再检查偏好语言列表里的其他语言如果依然没有合适资源则使用base默认资源。因此资源目录的意义并不是让业务代码自己选语言而是业务代码只请求资源资源系统负责选择最匹配的实现。这也是为什么不建议自己维护一个巨大的switch(language){casezh:caseen:casede:casefr:}这种代码实际上是在重复实现资源系统已经提供的职责。七、找不到目标语言时为什么base很重要假设后续应用只提供base zh_CN en_US某个用户的偏好语言并没有对应的完整资源目录。此时真正保护页面不出现资源缺失问题的就是默认资源。官方明确要求默认资源目录需要完整填充否则可能造成资源加载失败甚至编译相关问题。因此整理多语言资源时可以给自己定一条很实用的规则新增一个资源 key 时先补base再补各语言目录。比如新增privacy_settings不要只在zh_CN中添加然后等翻译完成再想起base。比较稳妥的维护顺序是base ↓ zh_CN ↓ en_US ↓ 其他语言资源 key 一致性的检查也应该进入发布前的本地化回归流程。八、真正让页面“英文全乱”的经常不是资源而是布局现在再看中文版立即体验英文Start Exploring字符串明显变长。如果原来的设计是Button($r(app.string.primary_action)).width(100).height(40)那么中文显示正常并不能证明这个布局合理。问题在于我们实际上把三个条件写死了文本长度 按钮宽度 按钮高度只要语言发生变化三者之间的关系就可能被破坏。所以本文示例没有给按钮固定 100vp 宽度而是Button($r(app.string.primary_action)).width(100%).padding({left:16,right:16,top:12,bottom:12})重点不是要求所有按钮都必须占满一行而是尽量避免根据中文版文案反推组件固定尺寸。同样对于普通正文Text($r(app.string.language_tip)).width(100%)允许文本在可用宽度中自然排版通常比直接假设“这一行永远只有十几个汉字”更可靠。华为官方本地化测试内容也明确把“应用界面排版”作为本地化测试对象之一而不只是检查有没有漏翻译。九、如果换成德语比英语还长怎么办英文变长只是第一轮检查。国际化页面设计不能把“英文版能放下”当作终点因为其他语言的表达长度还可能继续增加。这时候通常有三类处理方式。1. 普通描述文本允许自然换行正文、说明、卡片描述本身就适合多行展示。不要为了保持中文页面的一行高度把所有语言都强制压在一行里。2. 操作按钮给文案留下弹性按钮设计应该考虑内容宽度 左右内边距而不是中文四个字 ≈ 80vp如果产品视觉上必须限制按钮宽度则需要在设计阶段明确超长文本策略而不是上线前看到翻译结果再临时处理。3. 截断应该是明确的产品选择ArkUI 文本组件具有超长文本与行数控制相关能力但“能显示省略号”并不代表应该默认把重要操作截断。例如Delete all downloaded offline content如果最后只剩Delete all down...虽然布局没溢出但操作含义可能已经不完整。因此多语言页面适配的目标不是“永远不换行”而是让信息在不同语言环境下仍然可理解、可操作。十、日期、数字和单位不要自己拼字符串多语言开发还有一个比文本翻译更隐蔽的问题Text(year-month-day)以及Text(price USD)再比如Text(distance km)这些写法表面上没有中文却仍然可能没有完成国际化。官方国际化说明明确提醒不能假设所有地区都使用相同的数字分组符、小数分隔符等文化习惯。华为数字与度量衡国际化指南还举了非常直接的例子同一个1000不同文化环境中的分隔符含义可能不同因此需要进行区域化格式处理而不能把固定显示形式写死。日期也是类似的。不同地区可能在以下方面存在差异年/月/日顺序 12小时制 / 24小时制 月份显示方式 星期显示方式 时区因此应该把两个概念区分开原始数据 ↓ 本地化格式化 ↓ 页面展示字符串而不是原始数据 ↓ 手动 - / km ↓ 展示HarmonyOS Localization Kit 提供日期、数字、度量衡、时区等国际化能力。这里再强调一次版本问题历史官方指南中可以看到import{intl}fromkit.LocalizationKit;letformatternewintl.NumberFormat(...);但 HarmonyOS 后续 API 变更资料已经标记了ohos.intl多项 API 的废弃版本变化。面向 HarmonyOS 7 / API 26 新项目在真正落地格式化代码前应以当前 SDK API Reference 中的状态和替代接口为准而不是直接复制旧版本示例。这种地方宁可少写一段“看起来能运行”的代码也不要把旧 API 包装成 HarmonyOS 7 推荐写法。十一、语言切换之后建议至少做一遍这样的回归多语言页面测试不能只看“有没有变成英文”。可以按下面的顺序检查。1. 先检查资源完整性重点确认base zh_CN en_US中的 key 是否一致。如果新增了primary_action却漏掉了一个目录应该优先修资源而不是在 ArkTS 中加条件分支。2. 再检查匹配与回退测试至少应该包含中文 英文 一个没有提供专用资源的语言第三种情况主要用于检查默认资源是否能够正常承担回退职责。3. 检查长文本特别关注ButtonTabs列表尾部操作对话框操作区单行标题横向 Row 中的多个文字组件。很多中文 UI 的问题并不会在中文环境暴露出来。4. 检查动态数据不要只切语言检查静态标题还要观察日期 时间 价格 百分比 文件大小 距离 温度 单位因为“字符串翻译正确”和“区域格式正确”是两个问题。5. 检查业务代码中剩余的硬编码可以重点搜索Text(Button( title:message:不能简单认为这些位置全部有问题但它们很适合作为人工检查入口。华为官方当前仍提供本地化测试、伪本地化测试以及语言测试相关指导这类测试本身就是完整本地化流程的一部分。十二、几个容易理解错的地方“有en_US就不用base了”不对。base是默认资源回退链的重要组成部分应该准备完整资源。“国际化就是所有中文翻译成英文”不够。官方国际化能力范围本身就覆盖语言、时间日期、数字、度量衡、时区等区域差异。“英文放不下就统一缩小字体”这通常只是在隐藏布局问题。更应该先检查固定宽度、固定高度、横向空间分配以及是否允许合理换行。“所有语言都用省略号就安全了”布局可能不溢出了但信息可能不完整。尤其是按钮、权限说明、支付信息等关键文本不应该把“截断成功”当作适配完成。“搜索到官方示例就可以直接复制”还差一步核对版本。HarmonyOS 7 已进入 API 26.0.0 版本体系而较早文档中的接口可能已经发生废弃或替代变化。官方升级指南也明确要求开发者评估 API 版本变化并完成适配。十三、实际项目中可以按什么顺序排查碰到“中文版正常英文版布局错乱”可以先不要急着改字体。建议按这条链路检查字符串是不是仍然硬编码 ↓ 目标语言资源目录是否存在 ↓ 资源 key 是否完整且一致 ↓ base 默认资源是否完整 ↓ $r() 引用的资源名称是否正确 ↓ 组件是否使用了针对中文设计的固定尺寸 ↓ 长文本是否允许合理换行或伸缩 ↓ 日期、数字、单位是否仍在手动拼字符串 ↓ 最后做中文 / 英文 / 回退语言回归这样排查有一个好处能够先区分到底是资源问题还是布局问题。如果$r()已经拿到了正确英文页面仍然溢出就不应该继续折腾语言匹配而应该回到 ArkUI 布局本身。反过来如果英文环境仍显示base的内容那么应优先检查限定词资源与匹配关系而不是改组件尺寸。开发经验总结这次最小实践虽然只有一个页面但多语言适配真正值得带到项目里的有五点。第一不要把可见文案直接写进 ArkTS 业务代码。页面通过$r()请求资源让不同语言资源与业务逻辑分离。第二base必须当作正式资源维护。它不是临时目录而是资源匹配最终的默认回退。第三布局不能只按照中文字符串长度设计。按钮、标题、Row 横向布局都应该给翻译后的文本留下变化空间。第四日期、数字和单位也是本地化内容。没有中文字符并不代表已经国际化。第五版本核对要放在复制代码之前。HarmonyOS 7 对应 API 26.0.0旧版本 Localization Kit 示例中的 API 状态需要重新确认尤其不能把已经进入废弃流程的历史接口直接写成新项目推荐方案。如果正在整理一个已有的 HarmonyOS 项目可以先做一个很小的动作搜索所有直接出现在 ArkTS 里的用户可见字符串再挑一个页面迁移到base zh_CN en_US资源结构。完成这一步以后很多隐藏的固定宽度、字符串拼接和格式化问题会自然暴露出来。 写在最后如果你觉得这篇文章对你有帮助或者有任何想法、建议欢迎在评论区留言交流你的每一个点赞 、收藏 ⭐、关注 ❤️都是我持续更新的最大动力我是一个在代码世界里不断摸索的小码农愿我们都能在成长的路上越走越远越学越强感谢你的阅读我们下篇文章再见✍️ 作者菜鸟不学编程 本文原创转载请注明出处。