标签 国际化 下的文章

在这里插入图片描述

摘要

随着鸿蒙应用逐步走向国际化,应用不再只面对中文和英文用户。
中东、北非 等地区,阿拉伯语、希伯来语 这类 从右到左(RTL)语言 是主流,如果应用在这些语言环境下:

  • 布局顺序是反的
  • 返回按钮方向不对
  • 文字对齐看着很别扭

那基本可以直接劝退用户。

好消息是:
鸿蒙系统对 RTL 是原生支持的,而且大部分情况下是“自动完成”的。
坏消息是:
一旦你写了不该写的代码,系统也救不了你。

这篇文章就从真实开发角度,聊清楚鸿蒙里 RTL 适配到底该怎么做、哪些地方最容易踩坑,以及在真实页面里该怎么写。

引言

在早期做 Android / Web 国际化时,RTL 基本属于“高级需求”,很多项目甚至直接忽略。
但在鸿蒙生态里,国际化是默认要考虑的事情,尤其是:

  • 智能设备出海
  • 海外 ROM
  • 多语言系统级应用

在这些场景下,RTL 不再是“锦上添花”,而是基础能力

鸿蒙的设计理念其实很明确:

系统帮你做方向适配,你只要别把方向写死。

问题就在于:
很多开发者在不知不觉中,把方向写死了。

鸿蒙对 RTL 的整体支持机制

系统层是自动感知的

当系统语言切换为 RTL 语言时,鸿蒙会自动做这些事情:

  • 整体布局方向切换为 RTL
  • 文本阅读方向切换
  • Row / Flex 子组件顺序镜像
  • 列表、导航组件交互方向变化

前提只有一个:
你的代码要写得“语义化”。

布局方向适配的核心原则

永远不要写死 left / right

这是 RTL 适配里最常见、也是最致命的问题

错误示例(真实项目里经常看到)

Text('返回')
  .margin({ left: 16 })

这段代码在中文、英文环境下完全正常,
但在 RTL 环境下:

  • 系统已经整体翻转
  • 你又强行加了 left
  • 结果就是布局看起来“很怪”

正确示例(推荐写法)

Text('返回')
  .margin({ start: 16 })

这里的 start 是一个语义方向

  • LTR 语言下等价于 left
  • RTL 语言下等价于 right

你不用管语言,系统会帮你算。

Demo:基础 RTL 自适应 Row

下面是一个可以直接运行的 Demo,你只需要切换系统语言就能看到效果。

@Entry
@Component
struct RtlBaseDemo {
  build() {
    Row() {
      Image($r('app.media.arrow'))
        .width(24)
        .height(24)

      Text('返回')
        .margin({ start: 8 })
    }
    .padding({ start: 16, end: 16 })
  }
}

这个 Demo 的特点:

  • 没有写 left / right
  • 没有强制方向
  • 图标和文字顺序会自动镜像

在阿拉伯语系统下,你会发现:

  • 箭头跑到了右侧
  • 文本在左
  • 间距依然正确

文本方向与对齐的正确方式

文本不要写 Left / Right 对齐

很多人习惯性这样写:

Text('مرحبا')
  .textAlign(TextAlign.Left)

问题是:
Left 在 RTL 里并不是“阅读起点”。

正确的写法是:

Text('مرحبا')
  .textAlign(TextAlign.Start)

系统会自动判断:

  • 英文 → 左对齐
  • 阿拉伯语 → 右对齐

Demo:多语言文本展示

@Entry
@Component
struct TextAlignDemo {
  build() {
    Column() {
      Text('Hello HarmonyOS')
        .textAlign(TextAlign.Start)
        .fontSize(18)

      Text('مرحبا هارموني')
        .textAlign(TextAlign.Start)
        .fontSize(18)
    }
    .padding(16)
  }
}

这个 Demo 非常适合用来自测
切换系统语言,你能直观看到对齐方向变化。

结合真实业务场景的 RTL 适配实践

场景一:应用顶部导航栏

这是 RTL 最容易翻车的地方。

典型需求

  • 返回按钮
  • 页面标题

正确实现方式

@Component
struct TitleBar {
  build() {
    Row() {
      Image($r('app.media.back'))
        .width(24)
        .height(24)

      Text('设置')
        .margin({ start: 12 })
        .fontSize(20)
    }
    .padding(16)
  }
}

这里的关键点:

  • 不指定 FlexDirection
  • 使用 start 间距
  • 图标自动镜像

系统语言一换,整个标题栏方向自然就对了。

场景二:设置页列表项

设置页通常是左右结构,比如:

  • 左边是标题
  • 右边是开关或箭头

推荐写法

@Component
struct SettingItem {
  build() {
    Row() {
      Text('通知')
        .layoutWeight(1)

      Image($r('app.media.arrow'))
        .width(16)
    }
    .padding({ start: 16, end: 16, top: 12, bottom: 12 })
  }
}

在 RTL 下:

  • 文本会靠右
  • 箭头会跑到左侧
  • 整体阅读顺序符合习惯

你不需要为 RTL 单独写一套 UI。

场景三:列表页面与滑动方向

鸿蒙的 List 在 RTL 下:

  • 排列顺序自动调整
  • 滑动方向符合阅读习惯

示例代码

@Entry
@Component
struct ListDemo {
  build() {
    List() {
      ForEach(['Item A', 'Item B', 'Item C'], (item: string) => {
        ListItem() {
          Text(item)
            .padding(16)
            .textAlign(TextAlign.Start)
        }
      })
    }
  }
}

只要你不去强制对齐方向,列表在 RTL 下基本是“零成本适配”。

QA:开发中常见问题

Q1:需要手动判断当前是不是 RTL 吗?

一般不需要。
90% 的页面交给系统就够了。

只有在:

  • 自定义绘制
  • 特殊动画
  • 非标准交互

这些场景下,才需要手动处理。

Q2:图片什么时候需要手动镜像?

  • 返回箭头
  • 方向性极强的图标

可以使用:

Image($r('app.media.arrow'))
  .mirror(true)

普通装饰性图片不建议镜像。

Q3:为什么我写了 start / end 还是不生效?

通常是因为:

  • 强制写了 FlexDirection.Row
  • 写死了 Alignment.Left
  • 在父容器里破坏了方向规则

RTL 出问题,优先回头检查是不是哪一层写死了方向

总结

鸿蒙里的 RTL 适配,其实不是“多写代码”,而是“少犯错误”。

一句话经验总结:

  • start / end
  • TextAlign.Start
  • 不强制方向
  • 相信系统

只要遵守这几条规则,
绝大多数 RTL 问题都会在你“什么都没做”的情况下自动解决。

在这里插入图片描述

摘要(背景与现状)

随着鸿蒙系统在手机、平板、穿戴设备以及 IoT 场景中的逐步落地,同一套应用需要面向不同国家、不同地区、不同语言和政策环境已经成为常态。
在实际项目中,我们经常会遇到这些问题:

  • 不同地区展示的文案不一样
  • 某些功能在特定地区不能上线
  • 活动内容、公告、支付方式存在地区差异

如果地区适配逻辑处理得不好,就很容易出现代码混乱、维护成本高、后期改动困难的问题。

本文结合鸿蒙系统(HarmonyOS / OpenHarmony)的实际开发方式,从系统能力、资源机制和业务逻辑三个层面,总结一套可落地、好维护的地区特定内容实现方案。

引言(发展情况与应用场景)

从早期 Android / iOS 开发经验来看,地区适配往往依赖大量 if-else 判断,代码里到处是国家缩写,后期维护非常痛苦。
鸿蒙在设计之初,就在国际化与地区适配方面做了比较完整的能力封装,比如:

  • 系统级语言和地区识别
  • 资源文件按地区自动匹配
  • ArkUI 对多语言、多地区资源的天然支持

在真实项目中,大多数地区定制需求并不复杂,核心思路其实只有一句话:

先交给系统做资源适配,实在不行再写判断逻辑。

下面我们一步一步来看具体实现方式。

鸿蒙地区特定内容的整体实现思路

在鸿蒙系统中,地区定制通常可以拆分为三个层次:

  1. 系统层:获取当前设备的语言和地区信息
  2. 资源层:根据地区自动加载不同资源
  3. 业务层:在运行时根据地区控制功能和内容

这三层并不是互斥的,而是经常组合使用。

通过系统语言和地区识别用户环境

获取系统地区信息

鸿蒙提供了 i18n 模块用于国际化相关能力,获取系统地区非常简单。

import i18n from '@ohos.i18n';

const locale: string = i18n.getSystemLocale();
console.info(`当前系统地区为: ${locale}`);

常见返回值包括:

  • zh-CN:中国大陆
  • zh-HK:香港地区
  • en-US:美国
  • ja-JP:日本

这个值通常在应用启动时获取一次即可。

基于地区进行基础内容控制

let isChinaRegion: boolean = false;

if (locale.startsWith('zh-CN')) {
  isChinaRegion = true;
}

在 ArkUI 页面中直接使用:

if (isChinaRegion) {
  Text('中国地区专属内容')
    .fontSize(16)
}

这种方式比较直观,适合少量差异控制,但不建议大量使用在文案层面。

通过资源文件实现地区内容自动适配

资源目录结构设计

这是鸿蒙中最推荐、维护成本最低的方式。

resources/
 ├─ base/
 │   └─ element/
 │       └─ string.json
 ├─ zh_CN/
 │   └─ element/
 │       └─ string.json
 ├─ en_US/
 │   └─ element/
 │       └─ string.json

不同地区资源内容示例

base 目录作为兜底资源:

{
  "welcome_text": "Welcome"
}

中国地区资源:

{
  "welcome_text": "欢迎使用(中国地区)"
}

美国地区资源:

{
  "welcome_text": "Welcome (US Version)"
}

ArkUI 中直接使用资源

Text($r('app.string.welcome_text'))
  .fontSize(18)

系统会根据当前设备地区自动匹配资源,不需要任何额外判断。

如果没有对应地区资源,就自动回退到 base。

结合运行时逻辑实现地区功能差异

在真实项目中,地区差异不仅体现在文案上,功能层面的限制更常见。

地区功能开关示例

let enablePayment: boolean = true;

if (!locale.startsWith('zh-CN')) {
  enablePayment = false;
}

ArkUI 中控制按钮展示:

if (enablePayment) {
  Button('立即支付')
    .width(200)
}

代码逻辑说明

  • 地区判断逻辑集中在一个地方
  • UI 只关心布尔状态,不直接判断地区
  • 后期调整地区规则只改一处代码

这种写法在中大型项目中特别重要。

结合实际业务场景的应用示例

场景一:地区公告与活动内容展示

不同地区活动内容变化频繁,适合服务端下发。

let requestParam = {
  locale: locale
};

服务器返回内容:

{
  "notice": "日本地区限定活动"
}

客户端展示:

Text(serverData.notice)

这种方式运营改内容不需要重新发版。

场景二:支付方式地区限制

function isPaymentSupported(locale: string): boolean {
  return locale.startsWith('zh-CN');
}
if (isPaymentSupported(locale)) {
  Button('使用本地支付')
}

清晰区分业务规则和 UI。

场景三:隐私协议与合规文案差异

通过资源文件区分不同地区隐私条款:

Text($r('app.string.privacy_policy'))

不同地区加载不同内容,避免代码层面处理复杂文本。

常见问题 QA

Q1:可以只用代码判断不做资源适配吗?

可以,但不推荐。
代码判断适合控制功能,不适合承载大量文案。

Q2:地区和语言一定是一一对应的吗?

不一定。
比如香港地区可能使用中文或英文,建议优先按语言,再结合地区判断。

Q3:地区变化时需要重启应用吗?

一般不需要,重新加载页面即可。
资源匹配通常在页面创建时生效。

总结

在鸿蒙系统中实现地区特定内容,其实并不复杂,关键在于合理分层

  • 文案和静态内容优先使用资源适配
  • 功能和业务规则使用少量逻辑判断
  • 活动和运营内容交给服务端

一句话概括就是:

资源适配解决大部分问题,代码只处理真正的差异逻辑。