Flutter国际化插件i18n的使用

发布于 1周前 作者 wuwangju 来自 Flutter

Flutter国际化插件i18n的使用

简介

i18n 是一个用于Dart和Flutter的简单国际化包。此包支持热重载,并已在最新的Flutter版本上进行了测试。你可以将消息写入YAML文件,让这个包自动生成方便使用的Dart类。

概述

YAML文件到Dart类的转换

示例:YAML文件

lib/messages.i18n.yaml

button:
  save: Save
  load: Load
users:
  welcome(String name): "Hello $name!"
  logout: Logout

生成的Dart类

class Messages {
    const Messages();
    ButtonMessages get button => ButtonExampleMessages(this);
    UsersMessages get users => UsersExampleMessages(this);
}

class ButtonMessages {
    final Messages _parent;
    const ButtonMessages(this._parent);
    String get save => "Save";
    String get load => "Load";
}

class UsersMessages {
    final Messages _parent;
    const UsersMessages(this._parent);
    String get logout => "Logout";
    String welcome(String name) => "Hello $name!";
}

使用示例

Messages m = Messages();
print(m.users.welcome('World'));
// 输出: Hello World!

动机与目标

  • 国际化应该在编译时进行检查。
  • 消息键应该是方法而不是任意字符串。
  • 支持参数化消息。
  • 消息应按主题分组。
  • 利用Dart的字符串插值功能。
  • 支持build_runner和代码生成。

解决方案

写入YAML文件

默认消息

messages.i18n.yaml (默认消息):

generic:
  ok: OK
  done: DONE
invoice:
  create: Create invoice
  delete: Delete invoice

德语翻译

messages_de.i18n.yaml (_de = German translation)

generic:
  ok: OK
  done: ERLEDIGT
invoice:
  create: Rechnung erstellen
  delete: Rechnung löschen

使用生成的类

Messages m = Messages();
print(m.generic.ok); // 输出: OK
print(m.generic.done); // 输出: DONE

m = Messages_de();
print(m.generic.ok); // 输出: OK
print(m.generic.done); // 输出: ERLEDIGT

参数和复数形式

示例:带有参数的消息

invoice:
  create: Create invoice
  delete: Delete invoice
  help: "Use this function
  to generate new invoices and stuff.
  Awesome!"
  count(int cnt): "You have created $cnt ${_plural(cnt, one:'invoice', many:'invoices')}."
apples:
  _apples(int cnt): "${_plural(cnt, one:'apple', many:'apples')}"
  count(int cnt): "You have eaten $cnt ${_apples(cnt)}."

生成的类

class Messages {
    const Messages();
    InvoiceMessages get invoice => InvoiceExampleMessages(this);        
    ApplesMessages get apples => ApplesExampleMessages(this);
}

class InvoiceMessages {
    final Messages _parent;
    const InvoiceMessages(this._parent);
    String get create => "Create invoice";
    String get help => "Use this function to generate new invoices and stuff. Awesome!";
    String get delete => "Delete invoice";
    String count(int cnt) => "You have created $cnt ${_plural(cnt, one:'invoice', many:'invoices')}.";
}

class ApplesMessages {
    final Messages _parent;
    const ApplesMessages(this._parent);
    String _apples(int cnt) => "${_plural(cnt, one:'apple', many:'apples')}";
    String count(int cnt) => "You have eaten $cnt ${_apples(cnt)}.";
}         

复数函数

String _plural(int count, {String zero, String one, String two, String few, String many, String other})

String _cardinal(int count, {String zero, String one, String two, String few, String many, String other})

String _ordinal(int count, {String zero, String one, String two, String few, String many, String other})

如何使用生成的类

选择使用哪种翻译(如 Messages_deMessages_hu)取决于你。该包仅生成消息类。

示例代码

import 'messages.i18n.dart';
import 'messages_de.i18n.dart' as de;

void main() async {
  Messages m = Messages();
  print(m.apples.count(1));
  print(m.apples.count(2));
  print(m.apples.count(5));

  m = de.Messages_de(); // ExampleMessages_de 继承自 Messages
  print(m.apples.count(1));
  print(m.apples.count(2));
  print(m.apples.count(5));    
}

如何在Flutter中使用

创建YAML文件

lib/messages/foo.i18n.yaml

修改 pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  i18n: any
  ...

dev_dependencies:
  build_runner: any
  flutter_test:
    sdk: flutter

运行生成器

flutter packages pub run build_runner watch

导入并使用生成的消息

import 'packages:my_app/messages/foo.i18n.dart'

...

Foo m = Foo();
return Text(m.bar);
...

自定义复数形式

目前,该包仅正确处理英语和捷克语的复数形式。你可以通过实现自己的语言规则来扩展支持。

示例:注册德语复数规则

i18n.registerResolver('de', (int count, i18n.QuantityType type) {
  if (type == i18n.QuantityType.cardinal && count == 1) {
    return i18n.QuantityCategory.one;
  }
  return i18n.QuantityCategory.other;
});

参考链接

希望这些信息能帮助你在Flutter项目中顺利实现国际化!如果有任何问题或需要进一步的帮助,请随时提问。


更多关于Flutter国际化插件i18n的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter国际化插件i18n的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter应用中使用flutter_i18n插件来实现国际化的代码示例。这个示例将涵盖基本的设置、资源文件创建和使用。

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加flutter_i18n的依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_i18n: ^0.19.0  # 请检查最新版本号

然后运行flutter pub get来安装依赖。

2. 配置flutter_i18n

在你的Flutter项目根目录下创建一个名为assets/i18n的文件夹,用于存放翻译文件。

3. 创建翻译文件

assets/i18n文件夹中,为每个支持的语言创建对应的JSON文件。例如:

  • en.json (英文)
  • zh.json (中文)

en.json内容示例:

{
  "welcome_message": "Welcome to our app!",
  "goodbye_message": "Goodbye!"
}

zh.json内容示例:

{
  "welcome_message": "欢迎来到我们的应用!",
  "goodbye_message": "再见!"
}

4. 初始化flutter_i18n

在你的main.dart文件中,初始化flutter_i18n

import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart';

void main() {
  // 初始化flutter_i18n
  FlutterI18nDelegate delegate = FlutterI18nDelegate(
    fallbackLocale: Locale("en", "US"), // 默认语言
    translationAssets: const ["assets/i18n"] // 翻译文件路径
  );

  runApp(
    MaterialApp(
      home: MyHomePage(),
      localizationsDelegates: [
        delegate.buildLocalizationsDelegate(),
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: delegate.supportedLocales,
      locale: delegate.currentLocale,
      localeResolutionCallback: (locale, supportedLocales) {
        // 根据用户设置或系统语言选择语言
        for (var supportedLocale in supportedLocales) {
          if (supportedLocale.languageCode == locale?.languageCode ||
              supportedLocale.countryCode == locale?.countryCode) {
            return supportedLocale;
          }
        }
        return supportedLocales.first;
      },
    ),
  );
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    FlutterI18n flutterI18n = FlutterI18n.instance;

    return Scaffold(
      appBar: AppBar(
        title: Text(flutterI18n.translate("welcome_message")),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(flutterI18n.translate("welcome_message")),
            ElevatedButton(
              onPressed: () {
                // 切换语言示例
                FlutterI18nDelegate delegate =
                    Localizations.localeOf(context).languageCode == "en"
                        ? FlutterI18nDelegate(
                            fallbackLocale: Locale("zh", "CN"),
                            translationAssets: const ["assets/i18n"])
                        : FlutterI18nDelegate(
                            fallbackLocale: Locale("en", "US"),
                            translationAssets: const ["assets/i18n"]);

                delegate.loadTranslations();
                delegate.setLocale(Localizations.localeOf(context));

                // 更新MaterialApp的locale
                MaterialApp.router(
                  routeInformationParser: Router.routeInformationParser,
                  routerDelegate: MyRouterDelegate(),
                  locale: delegate.currentLocale,
                  localizationsDelegates: [
                    delegate.buildLocalizationsDelegate(),
                    GlobalMaterialLocalizations.delegate,
                    GlobalWidgetsLocalizations.delegate,
                  ],
                  supportedLocales: delegate.supportedLocales,
                ).build(context);
              },
              child: Text(flutterI18n.translate("goodbye_message")),
            ),
          ],
        ),
      ),
    );
  }
}

注意事项

  1. 重启应用:切换语言时,由于MaterialApp需要重新构建,实际应用中可能需要使用更优雅的方法来处理语言切换,例如使用ProviderRiverpod等状态管理库。
  2. 热重载:在开发过程中,确保在更改翻译文件后执行热重载,以便看到更改的效果。

以上代码提供了一个基本的框架,展示了如何在Flutter应用中使用flutter_i18n插件来实现国际化。根据你的具体需求,你可能需要添加更多的翻译文件和逻辑来处理不同的语言设置。

回到顶部