Flutter出海系列——更优雅的多语言

498 阅读5分钟

引言

使用Flutter时,如需要开发Google Play市场的安卓应用时,国际化是一个很常见的需求。笔者最近开发的一款应用同样有这个需求。

参考官方文档基本也跑通了单文件的多语言实现。只是官方文档提供的文档目前仅支持单文件的多语言需求,如果需要拆分多个文件,如用户相关的多语言拆分到user_zh.arb中,公共文本放在common_zh.arb中,就显得捉襟见肘了。

基于以上需求,通过互联网检索,发现没有特别好的方案,因此就诞生了这篇文章。

基本实现

官方文档已经描述的比较详细了,以下就不赘述,仅提供一些关键内容,及我自己使用的配置参数。

依赖

在flutter主目录的pubspec.yaml文件中添加如下配置

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: any
  
#...省略一些其他配置信息
flutter:
  generate: true # Add this line

l10n.yaml 配置

将l10n.yaml添加到项目根目录下。

以下为笔者使用的配置,带详细注释

arb-dir: lib/l10n #arb检索路径
template-arb-file: app_zh.arb 
output-dir: lib/l10n/generated #指定生成多语言文件目录
output-localization-file: app_localizations.dart #指定生成多语言文件名
prefer-matched-file: true # 优先匹配区域设置
prevent-collisions: true # 开启键名冲突检查
synthetic-package: false   # 禁用自动合成(如果需要指定output-dir,这个参数必须为false)
nullable-getter: false    #false即代表AppLocalizations.of(context)获取的对象不为空

多语言文件

在./lib/l10n下新增app_zh.arb和app_en.arb文件,配置文件以json的形式呈现

{
  "helloWorld": "你好 世界!"
}
{
  "helloWorld": "Hello World!"
}

生成多语言localization文件

  1. 最简单的方式是直接run应用,生成的文件在上述配置的目录/lib/l10n/generated目录下
  2. 其次可以使用flutter gen-l10n手动生成

在应用中使用

// 导入(tasks是我应用的,你可以根据自己应用修改)
import 'package:tasks/l10n/generated/app_localizations.dart';

// ...忽略部分代码

AppLocalizations get l10n => AppLocalizations.of(context);

// ...忽略部分代码

// 在组件具体调用
// 前置配置请参考官方文档
Text(l10n.helloWorld);

进阶使用

在小型项目中,所有多语言配置可以全部放在同一个文件中完全没问题,但是如果是中大型项目,多人开发下,如果所有配置放在同一个文件,单文件冲突合并就显得有点不优雅了。

一般来说,项目会按照业务拆分出不同的模块,那么我们也可以参考这点,优化一下,实现形如

lib/
  l10n/
    common_en.arb      # 公共词汇
    common_zh.arb
    home/              # 首页模块
      home_en.arb
      home_zh.arb

的目录结构。

以下提供两多方式供你挑选

使用命令生成不同的多语言文件

具体细节参考 这里

省流版看以下命令

flutter gen-l10n --arb-dir ./lib/l10n/home --template-arb-file home_en.arb --output-localization-file home_localizations.dart --output-class HomeLocalizations &&

flutter gen-l10n --arb-dir ./lib/l10n/settings --template-arb-file settings_en.arb --output-localization-file settings_localizations.dart --output-class SettingsLocalizations

以上实现可以解决无法生成多arb文件的问题,但是又引入新的问题,如:1、使用命令行直接生成,需要删除项目的中l10n.yaml文件,无法使用配置文件控制多语言文件

2、通过命令生成的会生成多个文件(这个不一定是缺点,看自己需求)

基于以上问题,提供以下新思路:

能不能在不修改官方实现的基础上,同时实现多模块arb?

答案是可以的!

命令行合并json文件

既然官方不支持多arb文件,那么我们直接通过命令行手动合并所有模块下的 arb 到主arb下不就行了么?

这样既可以使用官方的原配置,同时也可以支持多文件,一举两得!

下面直接放出sh代码

#!/bin/bash

# 配置参数
BASE_DIR="lib/l10n"
MODULES=("common" "home" "setting")  # 需要合并的模块目录
LANGUAGES=("en" "zh")       # 支持的语言

# 清理旧文件
rm -f $BASE_DIR/app_*.arb

# 按语言合并
for lang in "${LANGUAGES[@]}"; do
  OUTPUT_FILE="$BASE_DIR/app_${lang}.arb"
  TEMP_FILE="${OUTPUT_FILE}.tmp"

  # 初始化合并文件
  echo "{}" > $TEMP_FILE

  # 合并模块文件
  for module in "${MODULES[@]}"; do
    MODULE_FILE="$BASE_DIR/$module/${module}_${lang}.arb"
    if [ -f "$MODULE_FILE" ]; then
      jq -s '.[0] * .[1]' $TEMP_FILE $MODULE_FILE > $TEMP_FILE.tmp
      mv $TEMP_FILE.tmp $TEMP_FILE
    fi
  done

  # 格式化输出
  jq --sort-keys . $TEMP_FILE > $OUTPUT_FILE
  rm $TEMP_FILE
done

echo "ARB files merged successfully!"

使用

./merge_arb.sh && flutter gen-l10n
扩展

以上虽然实现了合并json文件,并生成dart类,但是每次使用还是得执行命令,比较繁琐。

基于以上,我们可以考虑

1、基于git hook

在项目根目录下的.git/hooks目录下新增pre-commit文件,然后在文件中添加内容:

./merge_arb.sh && flutter gen-l10n

2、基于flutter的编译(这个可以自己调研下)

扩展2

多文件下可能存在多个相同的字段名,可以考虑在copy对应目录下的json内容时,对应添加上文件名的前缀,如helloWorld在home.arb文件下复制到app.arb文件中时,对应key修改为home_helloWorld。


以上为本文的全部内容,关注我了解更多关于flutter的相关内容。

作者:独立开发者‘一一’,应用出海实践者,专注独立应用开发,目前开发了一款资产管理应用“归物(ReCollect)”,正在Google Play封测中,今年独立应用完成1/3。

联系我

邮箱:looptry@163.com