internationalizing/localizing Flutter 应用的不同方法

Different methods of internationalizing/localizing Flutter apps

根据Flutter docs,我们可以通过2种方法添加本地化消息:

方法一

  1. 将以下内容添加到 pubspec.yaml 文件中。

    dependencies:
      flutter:
        sdk: flutter
      flutter_localizations:
        sdk: flutter
      intl: ^0.17.0
    flutter:
     generate: true
    
  2. 创建一个 <project-root>/l10n.yaml 文件包含:

    arb-dir: lib/l10n
    template-arb-file: app_en.arb
    output-localization-file: demo_localizations.dart
    
  3. <project-root/l10n.yaml> 中,为您的翻译文件创建 app_locale.arb。例如:

    • app_en.arb
    {
      "@@locale": "en",
      "helloWorld": "Hello World!"
    }
    
    • app_es.arb
    {
      "@@locale": "es",
      "helloWorld": "Hola Mundo!"
    }
    
  4. demo_localizations.dart 将生成并可以像这样导入到 main.dart

    import 'package:flutter/material.dart';
    import 'package:flutter_gen/gen_l10n/demo_localizations.dart';
    
    class MyApp extends StatelessWidget {
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          localizationsDelegates: DemoLocalizations.localizationsDelegates,
          supportedLocales: DemoLocalizations.supportedLocales,
          title: 'My app',
          home: ... ,
        );
      }
    }
    

方法 2:为应用的本地化资源定义 class

  1. 将以下内容添加到 pubspec.yaml 文件中。

    dependencies:
      flutter:
        sdk: flutter
      flutter_localizations:
        sdk: flutter
      intl: ^0.17.0
      intl_translation:
    flutter:
     generate: true
    
  2. 创建一个使用 initializeMessages()Intl.message().

    DemoLocalizations class
    class DemoLocalizations {
      DemoLocalizations(this.localeName);
    
      static Future<DemoLocalizations> load(Locale locale) {
        final String name = locale.countryCode == null || locale.countryCode!.isEmpty
            ? locale.languageCode
            : locale.toString();
        final String localeName = Intl.canonicalizedLocale(name);
    
        return initializeMessages(localeName).then((_) {
          return DemoLocalizations(localeName);
        });
      }
    
      static DemoLocalizations of(BuildContext context) {
        return Localizations.of<DemoLocalizations>(context, DemoLocalizations)!;
      }
    
      final String localeName;
    
      String get title {
        return Intl.message(
          'Hello World',
          name: 'title',
          desc: 'Title for the Demo application',
          locale: localeName,
        );
      }
    }
    
  3. 创建 DemoLocalizationsDelegate class.

    class DemoLocalizationsDelegate extends LocalizationsDelegate<DemoLocalizations> {
      const DemoLocalizationsDelegate();
    
      @override
      bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);
    
      @override
      Future<DemoLocalizations> load(Locale locale) => DemoLocalizations.load(locale);
    
      @override
      bool shouldReload(DemoLocalizationsDelegate old) => false;
    }
    
  4. 运行

    flutter pub run intl_translation:extract_to_arb --output-dir=lib/l10n lib/demo_localizations.dart
    

    生成intl_messages.arb文件。添加 intl_en.arbintl_es.arb 作为您的翻译文件。

  5. 以应用根目录为当前目录,运行

    flutter pub run intl_translation:generate_from_arb --output-dir=lib/l10n --no-use-deferred-loading lib/demo_localizations.dart lib/l10n/intl_*.arb
    

    为每个 intl_<locale>.arb 文件和 intl_messages_all.dart 生成 intl_messages_<locale>.dart,这会导入所有消息文件。

  6. 将所需的 class 导入 main.dart

    import 'package:flutter/material.dart';
    import 'demo_localizations.dart';
    import 'package:intl/intl.dart';
    import 'l10n/messages_all.dart';
    
    class MyApp extends StatelessWidget {
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          localizationsDelegates: DemoLocalizations.localizationsDelegates,
          supportedLocales: DemoLocalizations.supportedLocales,
          title: 'My app',
          home: ... ,
        );
      }
    }
    

这两种方法有区别吗?我可以知道为什么我们使用方法 2 因为涉及更多的步骤吗?

intl 包的缺点,它需要在上下文中调用 class。 例如

S.of(context).nameOfLocalizedText

我认为值得尝试一种不同的方法来创建 class 静态字符串和本地化切换器指的是当前语言环境。并且只在没有上下文的情况下调用 class 。不幸的是,我没有示例,但您可以尝试为语言切换器创建一个 class,一个用于将 JSON 映射到 class 的 class 映射器,以及包含语言字典的 map。希望对您有所帮助。

简单的答案是,您描述为“方法 #1”的是最新版本的如何在 Flutter 中执行此操作而无需外部手段。现在比以往任何时候都更简单,无需外部包。

其他方法来自“以前”,您必须做更多的工作才能启动它 运行,这就是为什么有这么多替代软件包,其中一些现在似乎已过时, Flutter 系统本身发生了变化,变得更简单、更有用。