Flutter国际化插件intl_extension的使用

Flutter国际化插件intl_extension的使用

特性

  • 普通字符串(带参数和不带参数)
  • 选择字符串(带参数和不带参数)
  • 复数字符串(带参数和不带参数)

如何使用

安装

要使用 intl_extension 需要在 pubspec.yaml 文件中添加依赖项:

$ flutter pub add intl_extension
$ flutter pub add --dev intl_extension_builder

提取和生成

任何时候都可以使用以下命令来提取字符串并创建翻译文件:

$ flutter pub run intl_extension_builder:build

在安装完插件后,首先运行此命令。

初始化

在主函数中添加 WidgetsFlutterBinding.ensureInitialized();IntlLocalizations.init(IntlConfig()); 来初始化翻译服务。IntlConfig() 是由代码生成器创建的。

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  IntlLocalizations.init(IntlConfig());

  runApp(const MyApp());
}

翻译字符串

可以通过追加 intl() 方法来轻松翻译字符串:

Text('This is my address'.intl());

如果字符串包含参数,可以将它们作为 Map<String, String> 传递给 intl() 方法:

Text('My address is {address}'.intl({"address": "CWC8+R9 Mountain View, Kalifornien, USA"}));

如果字符串尚未包含在翻译文件中,则会返回或显示未翻译的字符串。

标记了新字符串用于翻译后,需要运行上述命令以提取和生成翻译文件。之后需要重启应用。否则字符串将被显示为未翻译。

翻译复数

可以通过追加 intlPlural() 方法来轻松翻译复数字符串:

Text(
    'You have pushed the button {value} times.'.intlPlural(
        value: _counter,
        zero: 'You have not pushed the button yet.',
        one: 'You pushed the button once',
    ),
),

如果复数字符串包含参数,可以将它们作为 Map<String, String> 传递给 intlPlural() 方法:

Text(
    'You have pushed the button {value} times.'.intlPlural(
        value: _counter,
        zero: 'You have not pushed the button yet.',
        one: 'You pushed the button {where} once',
        params: {"where": "in the office"}
    ),
),

如果复数字符串尚未包含在翻译文件中,则会返回或显示未翻译的字符串。

标记了新的复数字符串用于翻译后,需要运行上述命令以提取和生成翻译文件。之后需要重启应用。否则字符串将被显示为未翻译。

翻译选择

可以通过追加 intlSelect() 方法来轻松翻译选择字符串。主字符串将用作 other,如果没有任何变体匹配:

Text(
    'Someone comes'.intlSelect(value: 'female', variants: {
        "male": "A man comes",
        "female": "A woman comes"
    }),
),

如果选择字符串包含参数,可以将它们作为 Map<String, String> 传递给 intlSelect() 方法:

Text(
    'Someone comes'.intlSelect(
        value: 'male',
        variants: {
            "male": "A {age} year old man comes",
            "female": "A {age} year old woman comes"
        },
        params: {"age": "30"},
    ),
),

如果选择字符串尚未包含在翻译文件中,则会返回或显示未翻译的字符串。

标记了新的选择字符串用于翻译后,需要运行上述命令以提取和生成翻译文件。之后需要重启应用。否则字符串将被显示为未翻译。

更改语言

默认情况下,如果可能的话,将加载系统语言。如果没有可用,将显示原始语言。

可以随时使用以下命令更改语言:

IntlLocalizations.setLocale(const Locale('de'));

为了相应地更改应用的语言,需要在 MaterialApp 小部件周围添加一个 IntlChangeBuilder。当语言更改时,该构建器将再次执行:

[@override](/user/override)
Widget build(BuildContext context) {
  return IntlChangeBuilder(
    builder: (context, locale) {
      return MaterialApp(
        title: 'Intl_Extension Demo',
        localizationsDelegates: IntlLocalizations.localizationsDelegates,
        supportedLocales: IntlLocalizations.supportedLocales,
        locale: locale,
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: MyHomePage(title: 'Flutter Demo Home Page'.intl()),
      );
    },
  );
}

当前可用的区域可以直接传递到 MaterialApp

配置

对于语言配置和存储语言文件的文件夹,可以在根目录创建一个 intl.yaml 文件:

sourceLang: 'en'
targetLang:
  - 'de'

addOnlyToSource: true
outputDir: './lib/intl'

extract:
  inputDirs: 
    - './lib'
  outputDir: './intl'

示例代码

import 'package:example/intl/intl_config.dart';
import 'package:flutter/material.dart';
import 'package:intl_extension/intl_extension.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  IntlLocalizations.init(IntlConfig());

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return IntlChangeBuilder(
      builder: (context, locale) {
        return MaterialApp(
          title: 'Intl_Extension Demo',
          localizationsDelegates: IntlLocalizations.localizationsDelegates,
          supportedLocales: IntlLocalizations.supportedLocales,
          locale: locale,
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'.intl()),
        );
      },
    );
  }
}

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  Widget _localeSwitch() {
    if (IntlLocalizations.locale == const Locale('de')) {
      return ElevatedButton(
        onPressed: () => IntlLocalizations.setLocale(const Locale('en')),
        child: Text('SWITCH TO ENGLISH'.intl()),
      );
    } else {
      return ElevatedButton(
        onPressed: () => IntlLocalizations.setLocale(const Locale('de')),
        child: Text('SWITCH TO GERMAN'.intl()),
      );
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            _localeSwitch(),
            const SizedBox(height: 30),
            Text(
              'You have pushed the button {value} times.'.intlPlural(
                value: _counter,
                zero: 'You have not pushed the button yet.',
                one: 'You pushed the button one',
              ),
            ),
            Text(
              'Someone comes'.intlSelect(
                value: 'male',
                variants: {
                  "male": "A man comes",
                  "female": "A woman comes",
                },
                params: {},
              ),
            ),
            Text('Thanks man'.intl()),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

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

1 回复

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


intl_extension 是一个用于 Flutter 国际化的插件,它可以帮助你更轻松地管理和加载不同语言的翻译文件。以下是如何使用 intl_extension 的基本步骤:

1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  intl_extension: ^0.0.1  # 请检查最新版本

然后运行 flutter pub get 来获取依赖。

2. 创建翻译文件

在项目的 assets 目录下创建翻译文件。例如,你可以创建 en.jsonzh.json 分别对应英文和中文的翻译:

// en.json
{
  "hello": "Hello",
  "world": "World"
}

// zh.json
{
  "hello": "你好",
  "world": "世界"
}

3. 配置 pubspec.yaml

pubspec.yaml 中配置 assets,确保 Flutter 能够找到这些翻译文件:

flutter:
  assets:
    - assets/en.json
    - assets/zh.json

4. 初始化 intl_extension

在你的 Flutter 应用中初始化 intl_extension。通常可以在 main.dart 文件中进行初始化:

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // 初始化 intl_extension
  await IntlExtension.initialize(
    defaultLocale: 'en',
    supportedLocales: ['en', 'zh'],
    assetLoader: AssetLoader(),
  );

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Intl Extension Demo',
      home: MyHomePage(),
    );
  }
}

5. 使用翻译

在应用中使用翻译。你可以通过 IntlExtension.of(context) 来获取当前语言的翻译:

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

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(IntlExtension.of(context).translate('hello')),
      ),
      body: Center(
        child: Text(IntlExtension.of(context).translate('world')),
      ),
    );
  }
}

6. 切换语言

你可以通过 IntlExtension.setLocale 方法来动态切换语言:

IntlExtension.setLocale(context, 'zh');
回到顶部