Flutter国际化插件fluent_i18n的使用

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

Flutter国际化插件fluent_i18n的使用

为什么选择fluent_i18n?

有时你希望在没有上下文的情况下访问本地化文本,例如在模型类中。这个包使用单例模式加载Fluent Translation List (FTL)文件。你可以无需上下文即可访问本地化字符串(当然,也可以通过上下文访问),它还提供了更方便的方法,减少代码量并使应用程序的所有部分都能本地化。

开始使用

安装

pubspec.yaml中添加依赖:

dependencies:
  fluent_i18n: <最新版本>

创建文件夹并添加翻译文件,结构如下:

assets
└── i18n
    ├── {languageCode}.ftl                  //仅语言代码
    └── {languageCode}_countryCode}.ftl     //或完整区域代码

例如:

assets
└── i18n
    ├── en.ftl
    └── en_US.ftl

pubspec.yaml中声明你的资源本地化目录:

flutter:
  assets:
    - assets/i18n/
iOS注意事项

为了使翻译在iOS上生效,你需要在ios/Runner/Info.plist中添加支持的区域设置:

<key>CFBundleLocalizations</key>
<array>
	<string>en</string>
	<string>ja</string>
</array>
配置应用

在应用中添加EasyLocalization小部件,示例如下:

import 'package:fluent_i18n/fluent_i18n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

const List<Locale> SUPPORTED_LOCALES = [
  const Locale('ja'),
  const Locale('en'),  
];

Locale locale = SUPPORTED_LOCALES.first;

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
      locale: locale,
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        FluentLocalizationsDelegate(SUPPORTED_LOCALES),
      ],
      supportedLocales: SUPPORTED_LOCALES,
    );
  }
}

使用

更改区域设置 setLocale()

你可以通过调用以下方法更改区域设置:

await FluentLocalizations.setLocale(locale);

这将更改当前区域设置并加载相应的FTL文件。

或者,你可以调用(这是setLocale()所做的):

await FluentLocalizations.ofLocale(locale).load();
翻译 getMessage()

主要的翻译函数是getMessage(),示例如下:

final i18n = FluentLocalizations.current();
Text(i18n.getMessage('home-title')) 

如果你自己维护区域设置,可以使用:

final i18n = FluentLocalizations.ofLocale(currentLocale);
...
// 某处加载
await i18n.load();
...
Text(i18n.getMessage('home-title')) 

提示:不会破坏现有代码,你可以继续使用旧的静态方法FluentLocalizations.of(context)

完整示例Demo

以下是一个完整的示例,展示了如何使用fluent_i18n进行国际化:

import 'package:fluent_i18n/fluent_i18n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

import 'strings.dart';  // 假设这是你的字符串文件

const List<Locale> SUPPORTED_LOCALES = [
  const Locale('ja'),
  const Locale('en'),
];

Locale locale = SUPPORTED_LOCALES.first;

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      onGenerateTitle: (context) => Strings.appTitle,  // 从strings.dart中获取应用标题
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
      locale: locale,
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        FluentLocalizationsDelegate(SUPPORTED_LOCALES),
      ],
      supportedLocales: SUPPORTED_LOCALES,
    );
  }
}

class MyHomePage extends StatefulWidget {
  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

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

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(Strings.homeTitle),  // 从strings.dart中获取首页标题
      ),
      body: Container(
        padding: const EdgeInsets.all(10.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Text(
              Strings.pushedButtonThisManyTimes(_counter),  // 从strings.dart中获取按钮点击次数的文本
              style: Theme.of(context).textTheme.titleLarge,
            ),
            SizedBox(
              height: 20.0,
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text("Language: "),
                DropdownButton<Locale>(
                    value: locale,
                    items: SUPPORTED_LOCALES.map((language) {
                      return DropdownMenuItem(
                        child: Text(language.toString()),
                        value: language,
                      );
                    }).toList(),
                    onChanged: (value) async {
                      if (value != null) {
                        await Strings.applyLocale(value);  // 应用新的区域设置
                        setState(() {
                          locale = value;
                        });
                      }
                    }),
              ],
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: Strings.increment,  // 从strings.dart中获取增量提示
        child: Icon(Icons.add),
      ), // 这个尾随逗号使自动格式化更美观
    );
  }
}

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

1 回复

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


当然,下面是一个关于如何在Flutter项目中使用fluent_i18n插件进行国际化的代码示例。fluent_i18n是一个强大的国际化插件,它允许你使用Fluent语法来定义本地化资源。

步骤 1: 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  fluent_i18n: ^x.y.z  # 请替换为最新版本号

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

步骤 2: 创建Fluent资源文件

在你的Flutter项目根目录下创建一个locales文件夹,并在其中创建你的Fluent资源文件。例如,你可以创建en-US.ftlzh-CN.ftl文件。

en-US.ftl

greeting = Hello, { $name }!
farewell = Goodbye, { $name }!

zh-CN.ftl

greeting = 你好, { $name }!
farewell = 再见, { $name }!

步骤 3: 配置Flutter应用

在你的lib目录下创建一个l10n文件夹,并在其中创建一个fluent_localizations.dart文件来配置Fluent本地化。

fluent_localizations.dart

import 'package:fluent_i18n/fluent_i18n.dart';
import 'package:flutter/material.dart';
import 'dart:io';

class FluentLocalizations {
  static Future<FluentBundle> load(Locale locale) async {
    var file = File('locales/${locale.languageCode}-${locale.countryCode}.ftl');
    var content = await file.readAsString();
    return FluentBundle.fromString(locale.toString(), content);
  }

  static LocalizationsDelegate<FluentBundle> delegate(Locale locale) {
    return _FluentLocalizationsDelegate(locale);
  }
}

class _FluentLocalizationsDelegate
    extends LocalizationsDelegate<FluentBundle> {
  final Locale locale;

  _FluentLocalizationsDelegate(this.locale);

  @override
  bool isSupported(Locale locale) => true; // 或者添加你的支持逻辑

  @override
  Future<FluentBundle> load(Locale locale) => FluentLocalizations.load(locale);

  @override
  bool shouldReload(covariant LocalizationsDelegate<FluentBundle> oldDelegate) =>
      false;
}

步骤 4: 使用FluentBundle进行本地化

在你的MaterialApp中配置localizationsDelegatessupportedLocales,并使用FluentBundle进行本地化。

main.dart

import 'package:flutter/material.dart';
import 'l10n/fluent_localizations.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      localizationsDelegates: [
        FluentLocalizations.delegate(Locale('en', 'US')), // 默认语言
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: [
        Locale('en', 'US'),
        Locale('zh', 'CN'),
      ],
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Locale _locale;

  @override
  Widget build(BuildContext context) {
    final FluentBundle bundle = Localizations.of<FluentBundle>(context, FluentBundle)!;

    return Scaffold(
      appBar: AppBar(
        title: Text('Fluent I18n Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(bundle.getMessage('greeting', args: {'name': 'Alice'})),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  _locale = _locale == Locale('en', 'US')
                      ? Locale('zh', 'CN')
                      : Locale('en', 'US');
                  Localizations.override(
                    context,
                    FluentLocalizations.delegate(_locale),
                  );
                });
              },
              child: Text('Change Language'),
            ),
            Text(bundle.getMessage('farewell', args: {'name': 'Alice'})),
          ],
        ),
      ),
    );
  }
}

在这个示例中,我们通过点击按钮来改变应用的语言。注意,由于Localizations.override的使用可能会引发一些警告,它通常用于演示目的,在生产环境中你可能需要更复杂的逻辑来管理语言切换(例如,使用Provider或Riverpod等状态管理库)。

这个代码示例展示了如何在Flutter项目中使用fluent_i18n插件进行国际化。你可以根据需要进一步扩展和修改它。

回到顶部