一、引言:为什么国际化不是“加个翻译”那么简单?

当你的 App 用户遍布全球,语言只是本地化的冰山一角。真正的国际化(i18n)需考虑:

  • 文本方向(LTR/RTL)
  • 日期/数字/货币格式
  • 文化敏感内容(颜色、图标、图片)
  • App Store / Google Play 审核合规
  • 动态语言切换(无需重启)

本文将带你构建一套企业级 Flutter 国际化方案,覆盖从开发到上架全流程。


二、Flutter 国际化核心机制

2.1 官方方案:flutter_localizations

Flutter 提供 flutter_localizations 包,支持 78+ 种语言。

启用步骤:
  1. 添加依赖:
dependencies:
  flutter_localizations:
    sdk: flutter
  1. 在 MaterialApp 中配置:
MaterialApp(
  localizationsDelegates: [
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
  supportedLocales: [
    Locale('en', ''), // English
    Locale('zh', ''), // Chinese
    Locale('ar', ''), // Arabic (RTL)
  ],
)

✅ 效果:系统按钮(如 DatePicker)自动本地化。

2.2 自定义文本:使用 ARB 文件

ARB(Android Resource Bundle)是 Google 推荐的多语言格式。

目录结构:编辑
lib/
└── l10n/
    ├── app_en.arb
    ├── app_zh.arb
    └── app_ar.arb
示例:app_en.arb
{
  "helloWorld": "Hello World!",
  "welcomeMessage": "Welcome, {name}!",
  "@welcomeMessage": {
    "description": "Welcome message with placeholder",
    "placeholders": {
      "name": {
        "type": "String",
        "example": "John"
      }
    }
  }
}
生成代码:

运行 flutter gen-l10n,自动生成:

  • l10n.dart:包含 AppLocalizations.of(context).helloWorld

🔑 优势:类型安全、支持占位符、IDE 自动补全。


三、动态语言切换(无需重启 App)

官方方案不支持运行时切换语言,需自研。

3.1 核心思路

  • 使用 InheritedWidget 或 Provider 管理当前语言
  • 手动重建 MaterialApp
  • 重写 LocaleResolutionCallback

3.2 实现方案(基于 Riverpod)

Step 1:定义语言状态
@riverpod
class AppLocale extends _$AppLocale {
  @override
  Locale build() => const Locale('en');

  void change(Locale locale) {
    state = locale;
  }
}
Step 2:封装 MaterialApp
class LocalizedApp extends ConsumerWidget {
  final Widget child;

  const LocalizedApp({required this.child});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final locale = ref.watch(appLocaleProvider);

    return MaterialApp(
      locale: locale,
      localeResolutionCallback: (deviceLocale, supportedLocales) {
        // 优先使用用户选择的语言
        return locale;
      },
      supportedLocales: AppLocalizations.supportedLocales,
      localizationsDelegates: AppLocalizations.localizationsDelegates,
      home: child,
    );
  }
}
Step 3:切换语言
ElevatedButton(
  onPressed: () {
    ref.read(appLocaleProvider.notifier).change(const Locale('zh'));
  },
  child: Text('切换为中文'),
)

✅ 效果:点击按钮,全站语言实时切换,无需重启。


四、RTL(从右到左)布局支持

阿拉伯语、希伯来语等语言需镜像 UI。

4.1 自动 RTL 支持

Flutter 的 Directionality widget 可自动处理:

Directionality(
  textDirection: TextDirection.rtl,
  child: Scaffold(...),
)

但更推荐全局设置


MaterialApp(
  locale: const Locale('ar'), // 阿拉伯语
  // Flutter 自动设置 Directionality 为 rtl
)

4.2 手动适配复杂布局

某些自定义组件需显式处理:

✅ 替换规则:

  • left → start
  • right → end
  • TextAlign.left → TextAlign.start

4.3 图标镜像

部分图标在 RTL 下需翻转

Transform(
  transform: Matrix4.identity()..scale(textDirection == TextDirection.rtl ? -1 : 1, 1),
  child: Icon(Icons.arrow_forward),
)

或使用 IconTheme

IconTheme(
  data: IconThemeData(
    matchTextDirection: true, // 自动镜像
  ),
  child: Icon(Icons.arrow_forward),
)

五、文化敏感内容处理

5.1 日期/数字/货币格式化

使用 intl 包:

dependencies:
  intl: ^0.19.0

// 日期
DateFormat.yMMMMd('zh').format(DateTime.now()); // 2025年12月19日

// 货币
NumberFormat.simpleCurrency(locale: 'ar_EG').format(1234.5); // ج.م.‏ 1,234.50

⚠️ 注意:ar_EG(埃及阿拉伯语)与 ar_SA(沙特)货币不同。

5.2 图片与颜色本地化

  • 图片:不同文化对图像理解不同(如手势、动物)
  • 颜色:白色在西方=纯洁,在东方=丧葬
解决方案:

按语言加载资源:

Image.asset('assets/images/welcome_${locale.languageCode}.png')

或使用 L10n 扩展:

// app_ar.arb
{
  "welcomeImage": "assets/images/welcome_ar.png"
}

六、App Store 与 Google Play 合规指南

6.1 Apple 审核要求

  • 若支持阿拉伯语,必须完整适配 RTL
  • 元数据(标题、描述)需提供对应语言版本
  • 截图需包含主要语言界面

❌ 常见拒审原因:
“App supports Arabic but UI is not mirrored.”

6.2 Google Play 要求

  • 至少提供应用描述的本地化
  • 鼓励提供多语言截图

6.3 合规检查清单

项目 是否完成
✅ 所有支持语言均有完整翻译
✅ RTL 语言 UI 完全镜像
✅ 日期/数字/货币格式本地化
✅ App Store 描述提供对应语言
✅ 截图包含主要语言界面

七、国际化工作流:团队协作最佳实践

7.1 开发流程

7.2 工具链推荐

工具 用途
Lokalise / Crowdin 在线翻译管理
arb-validator 检查 ARB 格式
flutter_l10n_gen 自动生成缺失 key

7.3 自动化脚本示例

# 提取未翻译 key
flutter pub run intl_translation:extract_to_arb --output-dir=l10n lib/main.dart

# 生成代码
flutter gen-l10n

八、性能与包体积优化

8.1 按需加载语言包

默认所有 ARB 文件打包进 App,可优化:

  • Web:按路由懒加载语言
  • 移动端:仅打包用户设备语言(需后端配合)

8.2 移除未用语言

pubspec.yaml 中指定:

flutter:
  generate: true
  arb-dir: lib/l10n
  template-arb-file: app_en.arb
  output-localization-file: app_localizations.dart
  # 仅包含这些语言
  supported-locales:
    - en
    - zh
    - ar

✅ 减少包体积 10%~30%。


九、实战:构建一个多语言电商 App

需求:

  • 支持中/英/阿三语
  • 阿拉伯语 RTL + 货币显示
  • 用户可随时切换语言
  • 商品描述按语言存储

核心实现:

  1. 商品模型
class Product {
  final Map<String, String> name; // {'en': 'Phone', 'zh': '手机', 'ar': 'هاتف'}
  final double price;
}
  1. 价格显示
Text(
  NumberFormat.simpleCurrency(locale: locale.toLanguageTag()).format(product.price),
)
  1. 语言切换弹窗
showDialog(
  context: context,
  builder: (_) => LanguageSelector(),
);

🌍 上线后覆盖 3 亿潜在用户。


十、总结:国际化 Checklist

阶段 关键动作
设计 使用 start/end 而非 left/right
开发 所有文本走 ARB,禁用硬编码
测试 RTL 设备实测,伪本地化测试
发布 提供多语言元数据与截图
运维 监控翻译缺失率

完整模板 GitHub:github.com/yourname/flutter-i18n-template

国际化不是功能,而是对用户的尊重。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐