Flutter多语言支持插件multiple_localization的使用

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

Flutter多语言支持插件multiple_localization的使用

multiple_localization 插件简介

multiple_localization 是一个为 intl 包提供多个 arb 和消息本地化文件支持的插件。它解决了当您想要注册多个 arb 文件,每个文件对应不同的委托时,intl 不允许多次调用 initializeMessages 的问题。只有第一次调用会被处理并使用其消息,后续的调用将被忽略。这在您想添加带有 arb 文件的国际化到单独包中并在项目中使用自己的本地化文件时是一个常见问题。

为什么需要多个 arb 文件?

通常情况下,我们不需要多个 arb 文件,只需将所有本地化字符串放在单个文件中即可。但如果您希望将 intl 国际化与 arb 文件添加到单独的包中,并在项目中使用这些包以及项目的自有本地化文件,这就成了一个问题。

MultipleLocalizations 支持使用 Localizations.override(delegates: [SomeLocalizationsDelegate(), ...]) widget。

使用方法

要使用此插件,请按照以下步骤操作:

  1. pubspec.yaml 文件中添加 multiple_localization 作为依赖项。
  2. 使用 MultipleLocalizations.load 方法代替显式调用 initializeMessages 来加载您的委托。

示例代码

主应用入口 (main.dart)

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:multiple_localization/multiple_localization.dart';
import './app/l10n/messages_all.dart'; // 应用的本地化文件
import './package/l10n/messages_all.dart' as package; // 包的本地化文件

void main() {
  runApp(
    const MaterialApp(
      supportedLocales: [Locale('en')],
      localizationsDelegates: [
        AppLocalizations.delegate, // 应用的本地化代理
        PackageLocalizations.delegate, // 包的本地化代理
        DefaultCupertinoLocalizations.delegate,
      ],
      home: HomeScreen(),
    ),
  );
}

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

  @override
  Widget build(BuildContext context) {
    final appLocalization = AppLocalizations.of(context);
    final packageLocalization = PackageLocalizations.of(context);
    return Scaffold(
      appBar: AppBar(
        title: Text(appLocalization.title),
      ),
      body: Padding(
        padding: const EdgeInsets.all(18.0),
        child: Center(
          child: Column(
            children: [
              Text(appLocalization.messageFromApp),
              Text(packageLocalization.messageFromPackage),
              Text(packageLocalization.messageFromPackageForOverride),
            ],
          ),
        ),
      ),
    );
  }
}

应用程序本地化类 (AppLocalizations)

class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
  const _AppLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) => ['en'].contains(locale.languageCode);

  @override
  Future<AppLocalizations> load(Locale locale) {
    return MultipleLocalizations.load(
        initializeMessages, locale, AppLocalizations.new,
        setDefaultLocale: true);
  }

  @override
  bool shouldReload(LocalizationsDelegate<AppLocalizations> old) => false;
}

/// 应用程序本地化
class AppLocalizations {
  /// 代理
  static const LocalizationsDelegate<AppLocalizations> delegate =
      _AppLocalizationsDelegate();

  static AppLocalizations of(BuildContext context) =>
      Localizations.of<AppLocalizations>(context, AppLocalizations)!;

  final String locale;

  AppLocalizations(this.locale);

  String get title => Intl.message('Multiple localization', name: 'title');

  String get messageFromApp =>
      Intl.message('Default Message from App', name: 'messageFromApp');

  String get messageFromPackageForOverride =>
      Intl.message('This translation override package translation',
          name: 'messageFromPackageForOverride');
}

包的本地化类 (PackageLocalizations)

class _PackageLocalizationsDelegate extends LocalizationsDelegate<PackageLocalizations> {
  const _PackageLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) => ['en'].contains(locale.languageCode);

  @override
  Future<PackageLocalizations> load(Locale locale) {
    return MultipleLocalizations.load(
        package.initializeMessages, locale, PackageLocalizations.new);
  }

  @override
  bool shouldReload(LocalizationsDelegate<PackageLocalizations> old) => false;
}

/// 包的本地化
class PackageLocalizations {
  /// 代理
  static const LocalizationsDelegate<PackageLocalizations> delegate =
      _PackageLocalizationsDelegate();

  static PackageLocalizations of(BuildContext context) =>
      Localizations.of<PackageLocalizations>(context, PackageLocalizations)!;

  final String locale;

  PackageLocalizations(this.locale);

  String get messageFromPackage =>
      Intl.message('Default Message from Package', name: 'messageFromPackage');

  String get messageFromPackageForOverride =>
      Intl.message('Default Message from Package for override',
          name: 'messageFromPackageForOverride');
}

覆盖包中的字符串

如果要覆盖包中的字符串(例如更改包小部件中的某些标签),则需要在应用程序的本地化类中定义具有所需名称的字符串。确保将应用程序的本地化代理添加到包的本地化代理之前。

// 如果包中有如下字符串:
String get messageFromPackageForOverride =>
      Intl.message('Package', name: 'messageFromPackageForOverride');

// 则在 AppLocalizations 中定义同名字符串:
String get messageFromPackageForOverride =>
      Intl.message('App', name: 'messageFromPackageForOverride');

设置回退语言

还可以在加载应用程序的本地化代理时指定回退语言。使用 fallbackLocale 参数设置在当前语言找不到某些键时使用的语言。请注意,仅第一个 load 调用会设置回退语言,因此请确保应用程序的本地化代理是代理列表中的第一个元素。

此外,注意如果提供了 fallbackLocale,那么所有消息将在应用程序启动时加载到内存中,而不仅仅是当前语言的消息。

通过以上步骤和示例代码,您可以轻松地在Flutter项目中实现多语言支持,同时能够灵活管理来自不同来源的本地化资源。


更多关于Flutter多语言支持插件multiple_localization的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter多语言支持插件multiple_localization的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用multiple_localization插件来实现多语言支持的代码示例。multiple_localization是一个流行的Flutter插件,它简化了多语言支持的实现。

1. 添加依赖

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

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

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

2. 创建语言文件

假设你有英语(en)和中文(zh)两种语言支持,你需要在项目的assets文件夹下创建相应的语言文件。例如:

  • assets/locales/en.json
  • assets/locales/zh.json

en.json内容示例:

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

zh.json内容示例:

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

3. 配置pubspec.yaml

pubspec.yaml中配置资源路径:

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

4. 设置MultipleLocalization

在你的主文件(通常是main.dart)中设置MultipleLocalization

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultipleLocalization(
      supportedLocales: [Locale('en'), Locale('zh')],
      pathToLocalizationFiles: 'assets/locales/',
      fallbackLocale: Locale('en'),
      child: MaterialApp(
        title: 'Flutter Multi-language Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: MyHomePage(),
        localizationsDelegates: [
          GlobalMaterialLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate,
          MultipleLocalizations.delegate,  // 添加此行
        ],
        supportedLocales: [Locale('en'), Locale('zh')],  // 添加此行
        locale: Locale('en'),  // 初始语言
        onGenerateRoute: (RouteSettings settings) {
          // 你可以在这里根据路由设置动态更改语言
          // 根据需要调整语言设置
          return MaterialPageRoute(builder: (context) => MyHomePage());
        },
      ),
    );
  }
}

5. 使用翻译文本

在你的页面或组件中,使用MultipleLocalizations.of(context)来获取翻译文本:

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

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    final MultipleLocalizations localizations = MultipleLocalizations.of(context);
    return Scaffold(
      appBar: AppBar(
        title: Text(localizations.translate('welcome_message')),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(localizations.translate('welcome_message')),
            ElevatedButton(
              onPressed: () {
                // 切换语言示例
                final Locale currentLocale = Localizations.localeOf(context);
                final newLocale = currentLocale.languageCode == 'en' ? Locale('zh') : Locale('en');
                MultipleLocalization.of(context).setLocale(newLocale);
              },
              child: Text(localizations.translate('change_language')),
            ),
          ],
        ),
      ),
    );
  }
}

注意:在上面的代码中,change_language键需要在你的语言文件中定义,这里假设你在en.jsonzh.json中都添加了"change_language": "Change Language"

总结

通过上述步骤,你已经成功地在Flutter项目中集成了multiple_localization插件,并实现了多语言支持。你可以根据需要扩展语言文件和翻译内容。

回到顶部