多语言的难点不是“翻译”,而是工程化流程:词条一致、更新可追踪、避免漏翻。本文基于 flutter_localizations + intl 给出一套可复用的 i18n 工作流与代码范式。
0. 依赖与配置
dependencies:
flutter_localizations:
sdk: flutter
intl: ^0.18.1
l10n.yaml 示例:
arb-dir: lib/l10n
template-arb-file: intl_zh.arb
output-localization-file: l10n.dart
output-class: S
1. 统一词条规范(ARB)
建议使用 ARB 作为唯一词条来源:
{
"app_title": "我的应用",
"login": "登录",
"logout": "退出"
}
命名规范:
- 统一前缀(如
app_) - 使用下划线命名
- 避免同义重复
2. 统一翻译入口
// lib/generated/l10n.dart
S.of(context).login
UI 层不出现硬编码字符串。
3. 词条扫描(示例脚本思路)
核心目标:扫描代码中 t("xxx") 或 S.of(context).xxx 的使用,统一生成词条列表。
rg "S\.of\(.*\)\." lib/ -n
扫描结果写入 new_language_entries.txt,交给翻译流程处理。
4. 翻译注入
翻译完成后,把新词条注入回 ARB:
{
"app_title": "My App",
"login": "Login",
"logout": "Logout"
}
推荐让翻译团队只编辑新增部分,避免误改旧词条。
5. 自动化校验
- 未翻译检测(空值)
- 多语言键一致性
- 格式化占位符一致
示例校验逻辑:
bool validateArbKeys(Map<String, dynamic> base, Map<String, dynamic> target) {
return base.keys.toSet().difference(target.keys.toSet()).isEmpty;
}
6. 运行时切换语言
class LocaleProvider extends ChangeNotifier {
Locale _locale = const Locale('zh');
Locale get locale => _locale;
void setLocale(Locale locale) {
_locale = locale;
notifyListeners();
}
}
MaterialApp(
locale: context.watch<LocaleProvider>().locale,
supportedLocales: S.delegate.supportedLocales,
localizationsDelegates: const [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
)
7. 实践清单
- 词条统一入口(ARB)
- 词条扫描与新增收敛
- 翻译流程独立
- 自动化校验
- 运行时可切换
总结
多语言不是“翻一遍”,而是工程流程。把词条、翻译、注入、校验串成闭环,维护成本才能降下来。