Flutter国际化插件i18next_class_generator的使用

Flutter国际化插件i18next_class_generator的使用

对于Flutter的i18next包(https://pub.dev/packages/i18next)用于国际化。由于它不会生成引用文件,所以我们不得不在Dart文件中使用魔法字符串。为了解决这个问题,我们构建了这个包来为我们生成引用文件。

特性

这个包用于从JSON生成本地化引用文件。

使用方法

我们使用build_runner来生成引用代码。只需在示例目录中运行以下命令即可从JSON生成本地化Dart文件:

flutter pub run build_runner build

完整示例

示例代码:example/lib/main.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:i18next/i18next.dart';
import 'package:intl/intl.dart';

import 'i18n/localizations.i18next.dart';

void main() => runApp(const MyApp());

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);
  
  // 支持的本地化列表
  final List<Locale> locales = const [
    Locale('en', 'US'),  // 英语
    Locale('pt', 'BR'),  // 葡萄牙语
  ];

  [@override](/user/override)
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late Locale locale;

  [@override](/user/override)
  void initState() {
    super.initState();

    // 初始化时选择第一个本地化
    locale = widget.locales.first;
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'I18nu Demo',
      theme: ThemeData(
        dividerTheme: const DividerThemeData(
          color: Colors.black45,
          space: 32.0,
        ),
      ),
      // 添加本地化代理
      localizationsDelegates: [
        ...GlobalMaterialLocalizations.delegates,
        I18NextLocalizationDelegate(
          locales: widget.locales,
          dataSource: AssetBundleLocalizationDataSource(
            bundlePath: 'i18next',
          ),
          options: const I18NextOptions(formatter: formatter),
        ),
      ],
      home: MyHomePage(
        supportedLocales: widget.locales,
        onUpdateLocale: updateLocale,
      ),
      locale: locale,
      supportedLocales: widget.locales,
    );
  }

  // 更新本地化的回调函数
  void updateLocale(Locale newLocale) {
    setState(() {
      locale = newLocale;
    });
  }

  // 自定义格式化函数
  static String formatter(Object value, String? format, Locale? locale) {
    switch (format) {
      case 'test_formatter':
        return value.toString().toUpperCase();
      case 'uppercase':
        return value.toString().toUpperCase();
      case 'lowercase':
        return value.toString().toLowerCase();
      default:
        if (value is DateTime) {
          return DateFormat(format, locale?.toString()).format(value);
        }
    }
    return value.toString();
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({
    Key? key,
    required this.supportedLocales,
    required this.onUpdateLocale,
  }) : super(key: key);

  final List<Locale> supportedLocales;
  final ValueChanged<Locale> onUpdateLocale;

  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String _gender = '';

  [@override](/user/override)
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final i18n = I18n.of(context);

    return Scaffold(
      appBar: AppBar(
          title: Text(i18n.example.interpolationNested(
              {"key1": 'chiki chiki', "key2": "boom boom"}))),
      body: SingleChildScrollView(
        padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            CupertinoSegmentedControl<Locale>(
              children: {
                for (var e in widget.supportedLocales) e: Text(e.toString())
              },
              groupValue: Localizations.localeOf(context),
              onValueChanged: widget.onUpdateLocale,
            ),
            const Divider(),
            Text(
              i18n.example.base,
              style: theme.textTheme.headline6,
            ),
            Text(
              i18n.example.interpolation("weirdddd"),
              style: theme.textTheme.subtitle2,
            ),
            CupertinoSegmentedControl<String>(
              padding: const EdgeInsets.symmetric(vertical: 8),
              children: const {
                'male': Text('MALE'),
                'female': Text('FEMALE'),
                '': Text('OTHER'),
              },
              groupValue: _gender,
              onValueChanged: updateGender,
            ),
            Text(i18n.example
                .interpolationNested({"key1": "doge", "key2": "doge2"})),
            const Divider(),
            Text(
              i18n.example.nesting,
              style: theme.textTheme.headline4,
            ),
            Text(i18n.example.base),
            Text(i18n.example.interpolation("test 1")),
            Text(i18n.example.interpolationNested({
              "key1": "should uppercase",
              "key2": "object key 2",
            })),
            Text(i18n.example.nesting),
            Text(i18n.example.item(0)),
            Text(i18n.example.item(1)),
            Text(i18n.example.item(2)),
            Text(i18n.example.plural(0, "plural")),
            Text(i18n.example.plural(1, "plural")),
            Text(i18n.example.plural(2, "plural")),
            Text(i18n.example.nestingNested("surprise_object")),
          ],
        ),
      ),
    );
  }

  // 更新性别状态
  void updateGender(String gender) => setState(() => _gender = gender);
}

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

1 回复

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


i18next_class_generator 是一个用于 Flutter 的国际化插件,它可以帮助你自动生成 Dart 类来处理应用的国际化支持。这个插件基于 i18next 库,支持 JSON 文件作为翻译资源,并自动生成对应的 Dart 类来访问这些翻译。

1. 安装依赖

首先,你需要在 pubspec.yaml 中添加 i18next_class_generator 作为开发依赖:

dev_dependencies:
  flutter_test:
    sdk: flutter
  i18next_class_generator: ^1.0.0

2. 创建翻译文件

在项目中创建一个 i18n 文件夹(或其他你喜欢的名称),并在其中添加 JSON 文件来存储不同语言的翻译。例如:

lib/
  i18n/
    en.json
    fr.json
    zh.json

每个 JSON 文件的内容应该是键值对的形式:

en.json:

{
  "hello": "Hello",
  "welcome": "Welcome, {{name}}!"
}

fr.json:

{
  "hello": "Bonjour",
  "welcome": "Bienvenue, {{name}}!"
}

zh.json:

{
  "hello": "你好",
  "welcome": "欢迎, {{name}}!"
}

3. 配置 build.yaml

在项目的根目录下创建一个 build.yaml 文件,并配置 i18next_class_generator 的生成规则:

targets:
  $default:
    builders:
      i18next_class_generator|i18next_class_generator:
        enabled: true
        options:
          input_dir: "lib/i18n"
          output_dir: "lib/generated/i18n"
          class_name: "I18n"

4. 运行代码生成器

在终端中运行以下命令来生成 Dart 类:

flutter pub run build_runner build

这将会在 lib/generated/i18n 目录下生成一个 i18n.dart 文件,其中包含一个 I18n 类,用于访问你的翻译。

5. 使用生成的类

在 Flutter 应用中使用生成的 I18n 类来获取翻译:

import 'package:flutter/material.dart';
import 'generated/i18n/i18n.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text(I18n.of(context).hello),
        ),
        body: Center(
          child: Text(I18n.of(context).welcome(name: "Flutter Developer")),
        ),
      ),
    );
  }
}

6. 切换语言

你可以通过更改 Localizations.localeOf(context) 来切换语言。例如:

I18n.load(Locale('fr')); // 切换到法语

7. 自动监听翻译文件变化

如果你希望在开发过程中自动重新生成翻译类,可以使用 watch 命令:

flutter pub run build_runner watch
回到顶部