Flutter国际化插件i18n_omatic的使用
Flutter国际化插件i18n-o-matic的使用
i18n-o-matic 是一个用于简化 Flutter 应用程序中翻译工作的 Dart 包。它能够自动搜索源代码中的可翻译字符串,并为每种语言构建翻译表。这种方法受到 Qt 框架的启发。
特点
- 无痛翻译工作流
 - 自动发现可翻译字符串
 - 人类可读的 YAML 格式翻译文件
 - 格式化字符串用于变量替换
 
如何工作
i18n-o-matic 使用源代码中标记为可翻译的原始字符串作为翻译键。I18nOMatic 类将每个可翻译字符串替换为当前语言对应的字符串。建议在应用程序中使用英语作为翻译字符串的参考语言。
1. 导入 i18n_omatic 包
首先,需要在包含可翻译字符串的每个源文件中导入 i18n_omatic 包:
import 'package:i18n_omatic/i18n_omatic.dart';
2. 标记字符串为可翻译
为了标记字符串为可翻译,需要使用 i18n_omatic 提供的 tr() 方法:
String firstString = 'My first string'.tr();
// ...
Text('Share on network'.tr());
如果可翻译字符串的一部分基于外部值(即字符串插值),可以在字符串中使用占位符,并提供相应的键值对表。这些占位符以 % 字符开头,并且必须与键名匹配:
String birthdayMsg = 'Happy birthday %name, you are %age years old'.tr({'name': 'Peter', 'age': '21'});
3. 准备翻译配置
一旦标记了需要翻译的字符串,你需要编辑 Flutter 应用程序的 pubspec.yaml 配置文件,并添加每个翻译语言的资产文件。这些文件位于 assets/i18nomatic 目录下,文件名使用“语言_国家”代码(例如法国的 fr_FR.yaml,西班牙的 es_ES.yaml 等)。
pubspec.yaml 示例:
flutter:
  assets:
    - assets/
    - assets/i18nomatic/es_ES.yaml
    - assets/i18nomatic/fr_FR.yaml
对于 iOS 平台,还需要更新 ios/Runner/info.plist 文件以注册支持的语言。需要添加或更新 <CFBundleLocalizations> 元素,包含支持的语言列表:
<key>CFBundleLocalizations</key>
<array>
    <string>es_ES</string>
    <string>fr_FR</string>
</array>
4. 自动构建翻译表
i18n_omatic 包提供了一个命令行工具,该工具会扫描应用程序的源代码并查找可翻译的字符串。然后,它会创建或更新翻译文件以包含找到的字符串。
运行以下命令行工具:
dart pub run i18n_omatic:update
默认情况下,该工具会递归地扫描 lib 目录下的 .dart 文件,并更新位于 assets/i18nomatic 目录下的翻译文件。如果在 pubspec.yaml 文件中声明的翻译文件尚不存在,它会自动创建。
你可以根据需要运行此工具来更新翻译表,包括新引入的可翻译字符串。以前已翻译的字符串将保留在翻译文件中。
5. 在应用中启用翻译
你需要启用 i18n_omatic 的本地化代理,并在应用程序定义类中添加支持的语言。
MaterialApp(
    // ...
    localizationsDelegates: [
      I18nOMatic.delegate,
      GlobalMaterialLocalizations.delegate,
      GlobalCupertinoLocalizations.delegate,
      GlobalWidgetsLocalizations.delegate,
    ],
    supportedLocales: [
      const Locale('en', 'US'),
      const Locale('fr', 'FR'),
      const Locale('es', 'ES'), 
    ],
)
完成上述步骤后,带有 .tr() 方法的每个字符串都会被翻译为目标语言中的相应字符串。
6. 编辑翻译文件
假设以下源代码片段:
String firstString = 'My first string'.tr();
// ...
Text('Share on network'.tr());
// ...
String birthdayMsg = 'Happy birthday %name, you are %age years old'.tr({'name': 'Peter', 'age': '21'});
// ...
String ignoredString = 'ignored string';
首次运行 i18n_omatic:update 命令行工具时,将会生成如下的法语文档文件 (assets/i18nomatic/fr_FR.yaml):
format_version: 1
strings:
  "My first string" : null
  "Share on network" : null
  "Happy birthday %name, you are %age years old" : null
这 3 个收集到的字符串现在可供翻译,但默认为 null。你必须编辑文件并提供正确的翻译,例如法语:
format_version: 1
strings:
  "My first string" : "Ma première chaîne de caractères"
  "Share on network" : "Partager sur le réseau"
  "Happy birthday %name, you are %age years old" : "Bon anniversaire %name, tu as %age ans"
如果你在后续开发中删除了一个或多个可翻译字符串(例如上面示例中的 firstString),并在再次运行 i18n_omatic:update 命令行工具时,这些已翻译的字符串不会丢失,而是会被放置在一个 unused_strings 分类中:
format_version: 1
strings:
  "Share on network" : "Partager sur le réseau"
  "Happy birthday %name, you are %age years old" : "Bon anniversaire %name, tu as %age ans"
unused_strings:
  "My first string" : "Ma première chaîne de caractères"
一旦确定不再使用这些字符串,可以将其从 YAML 文件中删除。建议在发布应用程序的新版本之前清理这些文件。
如何测试使用 i18n_omatic 的小部件
你可以使用 Mockito 包来模拟 tr() 函数的翻译:
import 'package:i18n_omatic/i18n_omatic.dart';
import 'package:mockito/mockito.dart';
class MockI18nOMatic extends Mock implements I18nOMatic {}
class MockSetUp {
 static void mockI18nOMatic() {
   I18nOMatic.instance = MockI18nOMatic();
   when(I18nOMatic.instance.tr(any, any)).thenAnswer((realInvocation) {
     var strTranslated = realInvocation.positionalArguments[0].toString();
     if (realInvocation.positionalArguments[1] != null) {
       realInvocation.positionalArguments[1].forEach((String key, String value) {
         value ??= '';
         strTranslated = strTranslated.replaceAll('%$key', value.toString());
       });
     }
     return strTranslated;
   });
 }
}
在 Flutter 小部件测试的开始处调用 MockSetUp.mockI18nOMatic():
void main() {
  setUp(()  {
    MockSetUp.mockI18nOMatic();
  });
  [...]
}
更多关于Flutter国际化插件i18n_omatic的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter国际化插件i18n_omatic的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中使用i18n_omatic插件进行国际化的代码示例。i18n_omatic是一个流行的Flutter插件,用于简化和加速应用的国际化过程。请注意,实际使用时,你需要确保已经将该插件添加到了你的pubspec.yaml文件中。
1. 添加依赖
首先,在你的pubspec.yaml文件中添加i18n_omatic依赖:
dependencies:
  flutter:
    sdk: flutter
  i18n_omatic: ^x.y.z  # 请替换为最新版本号
然后运行flutter pub get来安装依赖。
2. 创建翻译文件
假设你要支持英语和中文,你可以在项目的assets文件夹下创建两个JSON文件:en.json和zh.json。
en.json
{
  "greeting": "Hello",
  "farewell": "Goodbye"
}
zh.json
{
  "greeting": "你好",
  "farewell": "再见"
}
3. 配置pubspec.yaml
在pubspec.yaml中配置这些翻译文件作为资产:
flutter:
  assets:
    - assets/en.json
    - assets/zh.json
4. 初始化i18n_omatic
在你的主应用文件(通常是main.dart)中,初始化i18n_omatic并设置默认语言:
import 'package:flutter/material.dart';
import 'package:i18n_omatic/i18n_omatic.dart';
import 'dart:convert';
import 'package:flutter/services.dart' show rootBundle;
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // 加载翻译文件
  Map<String, dynamic> enTranslations = jsonDecode(await rootBundle.loadString('assets/en.json'));
  Map<String, dynamic> zhTranslations = jsonDecode(await rootBundle.loadString('assets/zh.json'));
  // 初始化i18n
  I18nOmatic.instance.loadTranslations({
    'en': enTranslations,
    'zh': zhTranslations,
  });
  // 设置默认语言
  I18nOmatic.instance.currentLocale = Locale('en');
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: I18nOmatic.instance.translate('app.title', locale: I18nOmatic.instance.currentLocale),
      home: MyHomePage(),
      localizationsDelegates: [
        // 添加i18n_omatic的本地化委托
        I18nOmatic.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: I18nOmatic.instance.supportedLocales,
      locale: I18nOmatic.instance.currentLocale,
    );
  }
}
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(I18nOmatic.instance.translate('greeting', locale: I18nOmatic.instance.currentLocale)),
      ),
      body: Center(
        child: TextButton(
          onPressed: () {
            // 切换语言示例
            I18nOmatic.instance.currentLocale = I18nOmatic.instance.currentLocale.languageCode == 'en'
                ? Locale('zh')
                : Locale('en');
            // 更新UI(在实际应用中,你可能需要通知监听器或使用Provider来更新UI)
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text(I18nOmatic.instance.translate('farewell', locale: I18nOmatic.instance.currentLocale)),
              ),
            );
          },
          child: Text(I18nOmatic.instance.translate('farewell', locale: I18nOmatic.instance.currentLocale)),
        ),
      ),
    );
  }
}
5. 使用翻译文本
在你的应用中,你可以使用I18nOmatic.instance.translate方法来获取翻译后的文本。上面的代码示例已经展示了如何在按钮和AppBar的标题中使用翻译文本。
总结
以上代码展示了如何在Flutter项目中使用i18n_omatic插件进行国际化。这包括加载翻译文件、初始化插件、设置默认语言以及在UI中使用翻译文本。注意,在实际应用中,你可能需要更复杂的逻辑来处理语言切换和用户偏好设置。
        
      
            
            
            
