HarmonyOS 多语言适配实战:资源管理、文本长度与 RTL 布局检查

多语言适配不是把中文翻译成英文就结束。按钮文字变长后会挤压布局,日期和数字格式不一致会让用户误解,阿拉伯语等 RTL 场景会影响图标方向和焦点顺序。真正稳定的国际化方案,要把资源 key、占位符、文本伸缩、日期格式、RTL 和上线验收放进同一条链路。

请添加图片描述

本文围绕一个目标展开:在 HarmonyOS 应用里把多语言适配做成工程能力,而不是翻译文件回填后的页面修补。

一、先区分翻译问题和布局问题

多语言缺陷通常分两类:翻译不准确和界面承载不了翻译后的文本。后者更容易被忽略。

问题 典型表现 处理方式
key 缺失 页面显示默认中文或空文本 构建前扫描资源
占位符错误 “欢迎 undefined” 校验参数完整性
文本过长 按钮被挤压、换行遮挡 组件预留伸缩空间
格式错误 日期、价格、数量不符合地区习惯 使用区域格式化
RTL 错位 返回箭头、列表方向异常 做镜像与方向检查

请添加图片描述

二、资料与版本边界:本文写应用层国际化治理

本文示例面向 HarmonyOS NEXT / ArkTS / ArkUI 工程,重点在资源 key 管理、文本渲染模型、占位符校验、地区格式和 RTL 检查。具体资源目录、系统语言切换、组件属性和 RTL 支持能力,以当前 HarmonyOS SDK 与官方文档为准。

请添加图片描述

接入多语言前先准备资源清单

多语言项目最怕翻译到一半才发现页面里还有硬编码文案。建议先把资源来源分成三类:页面静态文案、服务端动态文案、本地拼接文案。前两类容易处理,第三类最危险,因为它经常藏在错误提示、按钮状态和空结果描述里。

资源来源 示例 推荐处理
页面静态文案 标题、按钮、Tab 名称 全部收敛为资源 key
动态参数文案 欢迎 {userName} 校验占位符和参数
服务端文案 活动标题、错误说明 后端返回语言字段或错误码
本地拼接 距离 2 km、剩余 3 次 用格式化函数处理
资产方向 返回箭头、步骤箭头 RTL 场景按语义镜像

读者在改造旧项目时,可以先从核心路径开始:登录页、首页、列表页、详情页、提交页。不要试图一天内改完整个应用,先把资源治理流程跑通。

建议目录:让翻译文件和页面解耦

资源 key 不应该跟页面代码混在一起。推荐把 key 定义、占位符规则和页面消费拆开,方便后续做脚本扫描。

export const RouteI18nKeys = {
  routeTitle: 'route.detail.title',
  routeDistance: 'route.detail.distance',
  routeDuration: 'route.detail.duration',
  routeEmpty: 'route.search.empty'
};

export interface I18nResourceItem {
  key: string;
  zhCN: string;
  enUS: string;
  arSA: string;
  placeholders: string[];
}

这段代码的边界是资源声明,不负责渲染。它的价值是让页面只引用 key,翻译同学和研发也能围绕同一份清单确认缺失项。

三、资源 key 模型:不要在页面硬编码文案

页面直接写中文,后期国际化会很难收敛。建议统一资源 key 和参数。

export interface I18nText {
  key: string;
  params: Record<string, string>;
  fallback: string;
}

export function createI18nText(key: string, fallback: string, params: Record<string, string>): I18nText {
  return { key, fallback, params };
}

export function missingI18nKey(text: I18nText, resourceMap: Record<string, string>): boolean {
  return resourceMap[text.key] === undefined;
}

这段模型的边界是描述一段可翻译文本。页面只消费 I18nText,资源层负责根据 key 和语言返回最终文本。

四、占位符校验:参数缺失比翻译错误更隐蔽

动态文案经常包含用户名、数量、城市等参数。翻译文件里有占位符,但代码没传参数,就会出现奇怪文本。

export function findPlaceholders(template: string): string[] {
  const result: string[] = [];
  const regexp = /\{([a-zA-Z0-9_]+)\}/g;
  let match = regexp.exec(template);
  while (match !== null) {
    result.push(match[1]);
    match = regexp.exec(template);
  }
  return result;
}

export function placeholderParamsValid(template: string, params: Record<string, string>): boolean {
  const placeholders = findPlaceholders(template);
  return placeholders.every(name => params[name] !== undefined);
}

这段代码用于资源检查或渲染前校验。它预防的是上线后出现 {userName} 原样展示,或者动态参数缺失。

五、文本长度策略:按钮和卡片要能伸缩

多语言文本通常比中文长。组件层需要根据位置选择截断、换行或缩小密度。

export type TextOverflowStrategy = 'singleLineEllipsis' | 'multiLine' | 'expandContainer';

export interface LocalizedTextLayout {
  maxLines: number;
  strategy: TextOverflowStrategy;
  minWidthVp: number;
}

export function resolveTextLayout(component: 'button' | 'title' | 'cardSummary'): LocalizedTextLayout {
  if (component === 'button') {
    return { maxLines: 1, strategy: 'expandContainer', minWidthVp: 96 };
  }
  if (component === 'title') {
    return { maxLines: 2, strategy: 'multiLine', minWidthVp: 0 };
  }
  return { maxLines: 2, strategy: 'singleLineEllipsis', minWidthVp: 0 };
}

按钮通常不能随便换行,标题可以两行展示,摘要可以省略。策略写清楚后,页面适配会更一致。

六、地区格式:日期、数字和复数不要手拼

不同语言环境下,日期、距离和数量的展示顺序不同。业务层应该输出语义值,展示层按 locale 格式化。

export interface LocaleFormatContext {
  locale: string;
  distanceKm: number;
  count: number;
}

export function buildDistanceText(context: LocaleFormatContext): string {
  if (context.locale === 'en-US') {
    return `${context.distanceKm.toFixed(1)} km`;
  }
  return `${context.distanceKm.toFixed(1)} 公里`;
}

export function buildCountText(context: LocaleFormatContext): string {
  if (context.locale === 'en-US') {
    return context.count === 1 ? '1 item' : `${context.count} items`;
  }
  return `${context.count}`;
}

示例里只演示思路。真实项目可以接入系统格式化能力,但不要在业务代码里散落拼接规则。

七、RTL 检查:方向不是只翻转文字

RTL 场景会影响布局方向、图标方向、手势方向和焦点顺序。不要只切语言不切方向。

export interface DirectionalAsset {
  name: string;
  mirrorInRtl: boolean;
}

export function resolveAssetForDirection(asset: DirectionalAsset, rtl: boolean): string {
  if (rtl && asset.mirrorInRtl) {
    return `${asset.name}_rtl`;
  }
  return asset.name;
}

返回箭头、进度方向、列表滑动图标通常需要镜像;品牌 logo 和地图图标通常不应该镜像。要按资产语义判断。

八、多语言问题排查表

多语言页面表现 优先怀疑的资源问题 排查方式 修复方向
页面仍显示中文 key 缺失或 fallback 被使用 扫描 missingI18nKey 补齐资源文件
文案出现 {name} 占位符参数缺失 检查 placeholderParamsValid 补传参数
英文按钮挤压 按钮宽度固定 查看 resolveTextLayout 增加最小宽度或缩短文案
数量文案别扭 复数规则手拼 检查 count 格式化 按 locale 生成
RTL 返回箭头方向错 图标未镜像 查看资产配置 给方向性图标加 rtl 资源
日期含义误解 日期格式未本地化 对比不同 locale 使用地区格式化

九、多语言上线前验收表

多语言验收点 通过结果
key 完整 目标语言没有缺失 key
参数完整 占位符都有传入参数
文本伸缩 按钮、标题、卡片不遮挡
格式适配 日期、距离、数量符合语言习惯
RTL 布局方向、图标、焦点顺序已检查
真机截图 每种目标语言至少保留关键页面截图

多语言验收不要只看首页。建议至少覆盖登录页、核心列表页、详情页、表单页和错误页,因为这些页面包含按钮、长标题、动态参数和错误提示。每种语言都保存一组截图,后续翻译更新时可以快速对比差异。

真机验收:不要只切英文

英文只能暴露文本长度问题,不能完整覆盖 RTL、复数、日期顺序和图标方向。建议至少准备三组语言:中文作为基线,英文看长文本,阿拉伯语或其他 RTL 语言看方向和焦点。

语言场景 要重点看的页面 典型风险
简体中文 全链路基线 key 是否覆盖完整
English 列表卡片、按钮、弹窗 文案变长导致遮挡
RTL 语言 返回、步骤、导航、图标 方向和焦点顺序错误
数字地区差异 价格、距离、日期 格式被手写字符串固定
伪翻译长文本 表单和空态 布局伸缩不足

可以给每个核心页面保存一张基线截图和一张目标语言截图。后续翻译更新时,先比对截图再回归功能,比人工逐字扫页面更稳定。

export interface LocalePageSnapshot {
  pageName: string;
  locale: string;
  screenshotName: string;
  checkedAt: number;
  riskNote: string;
}

export function createLocaleSnapshot(pageName: string, locale: string, riskNote: string): LocalePageSnapshot {
  return {
    pageName,
    locale,
    screenshotName: `${pageName}_${locale}_${Date.now()}.png`,
    checkedAt: Date.now(),
    riskNote
  };
}

这段快照对象用于记录验收证据。它不处理截图文件本身,而是把页面、语言和风险点关联起来,方便团队回看每次多语言改动影响了哪些页面。

旧项目改造建议:先扫硬编码,再改组件

第一步先扫页面里的中文硬编码。标题、按钮、Toast、空态、错误提示都要纳入范围,尤其是工具函数里拼出来的文案。

第二步建立资源 key 规则。key 名称最好能表达模块和用途,例如 route.search.empty,不要用 text001 这种后期无法维护的命名。

第三步改动态文案。包含用户名、距离、数量、日期的文案必须显式声明占位符,不能用字符串拼接凑出来。

第四步处理组件伸缩。按钮、标签、卡片标题要决定是截断、换行还是容器变宽。不同位置策略不同,不能全局一刀切。

第五步验收 RTL。返回箭头、流程箭头、列表排列、焦点顺序都要看。不是所有图标都应该镜像,表示真实方向的地图箭头就不能随便反转。

多语言问题出现时怎么定位

如果页面出现空文案,先看 key 是否存在,再看当前语言资源是否覆盖;如果出现 {count} 原样展示,优先看占位符参数;如果只有某一种语言布局挤压,重点看组件约束而不是翻译本身。

现象 优先查看 进一步动作
页面显示中文 目标语言资源是否缺 key 补资源或回退文案
占位符原样显示 参数名是否一致 修正 key 和代码参数
按钮文字溢出 组件宽度和换行策略 改为多行或缩短翻译
日期读不懂 是否手写日期格式 接入地区格式化
RTL 箭头错 图标语义 区分方向图标和装饰图标

十、多语言相关官方资料

  1. 华为开发者文档:资源分类与访问
    https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/resource-categories-and-access
  2. 华为开发者文档:ArkUI 布局开发
    https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-layout-development
  3. 华为开发者文档:Stage 模型应用开发
    https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/stage-model-development-overview

十一、把多语言做成可检查流程

多语言适配的关键是提前检查,而不是翻译完成后逐页修。资源 key 管理文案来源,占位符校验保证动态文本正确,文本布局策略避免遮挡,地区格式处理日期和数量,RTL 检查覆盖方向问题。

国际化落地问题 推荐工程答案
文案从哪里来 统一资源 key
参数怎么保证 占位符校验
文本变长怎么办 组件级伸缩策略
RTL 怎么处理 按资产语义镜像
上线前看什么 语言截图和资源扫描结果
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐