【问题标题】:Different methods of internationalizing/localizing Flutter apps国际化/本地化 Flutter 应用程序的不同方法
【发布时间】:2021-04-21 01:16:12
【问题描述】:

根据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: ... ,
        );
      }
    }
    

方法二:为应用的本地化资源定义一个类

  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 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 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_&lt;locale&gt;.arb 文件和intl_messages_all.dart 生成intl_messages_&lt;locale&gt;.dart,这会导入所有消息文件。

  6. 将所需的类导入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,因为涉及的步骤更多吗?

【问题讨论】:

  • 查看此博客roszkowski.dev/2021/i18n-in-flutter。现在更容易了,因为包处理所有创建/构建/设置文件
  • @Reign 这是否意味着方法 2 在引入方法 1 之前只是一种较旧的方法?
  • 最简单的解决方案是使用get
  • @Ranjit 我想使用本机解决方案,而不是依赖另一个包。另外,我询问的是决定背后的基本原理,而不是如何 使应用程序国际化。你没有回答我的问题。

标签: flutter dart localization internationalization


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    intl 包的缺点是需要在上下文中调用类。 举个例子

    S.of(context).nameOfLocalizedText
    

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

    【讨论】:

    • 我认为这不是一个好主意。见this
    • 好吧,Rémi Rousselet 这么说。但很少有人不同意,那是另一种情况。他的意思是使用 intl 并在没有上下文的情况下调用它。但是他并没有说我们可以按照自定义方式进行操作,对吗?国际本地化当您更改语言时它不是实时的,您必须导航到根路径,同时,我们需要使用 materialapp / cuppertino 应用程序的提供程序来监听当前的本地化是什么以实时更改它。
    • 但它又回来了,也许 intl & intl_translation 包是“安全方式”的最佳建议。我认为值得一试,因为 Flutter 没有像 android native 那样的字符串系统,而不是使用 .arb 文件和 S.of(context)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 2013-11-28
    • 2012-08-31
    • 2011-12-08
    • 1970-01-01
    相关资源
    最近更新 更多