Day18 - Flutter - 国际化(上)

简介: Day18 - Flutter - 国际化(上)

概述


  • 国际化的认识
  • 国际化的适配
  • 国际化的工具


一、国际化的认识



开发一个App,如果我们的App需要面向不同的语种(比如中文、英文、繁体等),那么我们需要对齐进行国际化开发。

国际化的英文称呼:internationalization(简称为i18n,取前后两个字母,18表示中间省略字母的个数)

App国际化开发主要包括:文本国际化(包括文本的顺序),Widget显示的国际化:

比如我们下面开发的这个App

某些文本在英文环境下应该显示为英文;

某些Widget在中文环境下,应该显示中文(比如弹出的时间选择器);


image.png

image.png


二、国际化的适配



  • 2.1、Widget的国际化Flutter给我们提供的Widget默认情况下就是支持国际化,但是在没有进行特别的设置之前,它们无论在什么环境都是以英文的方式显示的。如果想要添加其他语言,你的应用必须指定额外的 MaterialApp 属性并且添加一个单独的 package,叫做 flutter_localizations。截至到 2020 年 2 月份,这个 package 已经支持大约 77 种语言。
  • 2.1.1、pubspec.ymal 添加依赖,想要使用 flutter_localizations 的话,我们需要在 pubspec.yaml 文件中添加它作为依赖如下,记得点击 Pub get 更新一下


image.png


dependencies:
    flutter:
       sdk: flutter
    flutter_localizations:
       sdk: flutter
  • 2.1.2. 设置 MaterialApp
  • 在localizationsDelegates中指定哪些Widget需要进行国际化
  • 用于生产本地化值集合的工厂
  • 我们这里指定了Material、Widgets、Cupertino都使用国际化
  • supportedLocales指定要支持哪些国际化:我们这里指定中文英文(也可以指定国家编码)


MaterialApp(
    localizationsDelegates: [
       // 指定本地化的字符串和一些其他的值
       GlobalMaterialLocalizations.delegate, 
       // 对应的Cupertino风格
       GlobalCupertinoLocalizations.delegate, 
       // 指定默认的文本排列方向, 由左到右或由右到左
       GlobalWidgetsLocalizations.delegate 
    ],
    supportedLocales: [
        Locale('en'),
        Locale('zh')
    ],
);


提示:如果要指定语言代码、文字代码和国家代码,可以进行如下指定方式:

// Full Chinese support for CN, TW, and HK
supportedLocales: [
   const Locale.fromSubtags(languageCode: 'zh'), // generic Chinese 'zh'
   const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans'), // generic simplified Chinese 'zh_Hans'
   const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant'), // generic traditional Chinese 'zh_Hant'
   const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN'), // 'zh_Hans_CN'
   const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'TW'), // 'zh_Hant_TW'
   const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'HK'), // 'zh_Hant_HK'
],


  • 2.1.3. 查看Widget结果设置完成后,我们在Android上将语言切换为中文,查看结果,我们可以看到英文的 时间Widget里面的文字是 中文了


image.png


  • 但是对于iOS,将语言切换为中文,依然显示是英文的Widget
  • 这是因为iOS定义了一些应用的元数据,其中包括支持的语言环境;
  • 我们必须将其对应的元数据中支持的语言添加进去;
  • 元数据的设置在iOS项目中对应的info.plist文件中;
  • 修改 iOS 的 info.plist 文件配置:


image.png

image.png

image.png

配置完成后,卸载之前的app,重新安装:我们可以看到和安卓模拟器一样的效果


image.png

image.png


2.2、其它文本国际化


App中除了有默认的Widget,我们也希望对自己的文本进行国际化

  • 2.2.1、创建本地化类,该类用于定义我们需要进行本地化的字符串等信息:
  • 1.我们需要一个构造器,并且传入一个Locale对象(后续会使用到)
  • 2.定义一个Map,其中存放我们不同语言对应的显示文本
  • 3.定义它们对应的getter方法,根据语言环境返回不同的结果


import 'package:flutter/material.dart';
class JKLocalizations {
    final Locale locale;
    JKLocalizations(this.locale);
    static JKLocalizations of(BuildContext context) {
        return Localizations.of(context, JKLocalizations);
    }
    static Map<String, Map<String, String>> _localizedValues = {
       "en": {
           "title": "home",
           "greet": "hello~",
           "picktime": "Pick a Time"
       },
       "zh": {
           "title": "首页",
           "greet": "你好~",
           "picktime": "选择一个时间"
       }
    };
    // 标题
    String get title {
        return _localizedValues[locale.languageCode]["title"];
    }
    // 问候
    String get greet {
        return _localizedValues[locale.languageCode]["greet"];
    }
    // 时间
    String get pickTime {
       return _localizedValues[locale.languageCode]["picktime"];
    }
}


  • 2.2.2、自定义Delegate
  • 上面的类定义好后,我们在什么位置或者说如何对它进行初始化呢?
  • 答案是我们可以像Flutter Widget中的国际化方式一样对它们进行初始化;
  • 也就是我们也定义一个对象的Delegate类,并且将其传入localizationsDelegates中;
  • Delegate的作用就是当Locale发生改变时,调用对应的load方法,重新加载新的Locale资源;
  • JKLocalizationsDelegate需要继承自LocalizationsDelegate,并且有三个方法必须重写:
  • isSupported:用于当前环境的Locale,是否在我们支持的语言范围
  • shouldReload:当Localizations Widget重新build时,是否调用load方法重新加载Locale资源
  • 一般情况下,Locale资源只应该在Locale切换时加载一次,不需要每次Localizations重新build时都加载一遍;
  • 所以一般情况下返回false即可;
  • load方法:当Locale发生改变时(语言环境),加载对应的HYLocalizations资源
  • 这个方法返回的是一个Future,因为有可能是异步加载的;
  • 但是我们这里是直接定义的一个Map,因此可以直接返回一个同步的Future(SynchronousFuture)


class JKLocalizationsDelegate extends LocalizationsDelegate<JKLocalizations> {
     @override
     // 支持的语言
     bool isSupported(Locale locale) {
         return ["en", "zh"].contains(locale.languageCode);
     }
     @override
     bool shouldReload(LocalizationsDelegate<JKLocalizations> old) {
        return false;
     }
     @override
     Future<JKLocalizations> load(Locale locale) {
        return SynchronousFuture(JKLocalizations(locale));
     }
     static JKLocalizationsDelegate delegate = JKLocalizationsDelegate();
}


  • 2.2.3. 使用本地化类
  • 1>、 在MaterialApplocalizationsDelegates里里添加我们的 delegeate


image.png


  • 2>、接着我们可以在代码中使用JKLocalization类。
    我们可以通JKYLocalizations.of(context)获取到JKLocalizations对象,本质上是在调用 Localizations.of(context, JKLocalizations)
Column(
     mainAxisAlignment: MainAxisAlignment.center,
     children: [
         Text(JKLocalizations.of(context).greet),
         RaisedButton(
            child: Text(JKLocalizations.of(context).pickTime, style: TextStyle(fontSize: 20, color:  Colors.orange),),
            onPressed: () {
                showDatePicker(
                   context: context,
                   initialDate: DateTime.now(),
                   firstDate: DateTime(2000),
                   lastDate: DateTime(3000)
                );
            }
         )
     ],
),
  • 2.2.4. 异步加载数据,也就是 JKLocalizations 里面的 _localizedValues 我们做一个抽取


static Map<String, Map<String, String>> _localizedValues = {};
// 获取配置的 Map
Future<bool> loadJson() async {
     // 1.加载json文件
     String jsonString = await rootBundle.loadString("assets/json/i18n.json");
     // 2.转成map类型
     final Map<String, dynamic> map = json.decode(jsonString);
     // 3.注意:这里是将Map<String, dynamic>转成Map<String, Map<String, String>>类型
     _localizedValues = map.map((key, value) {
         return MapEntry(key, value.cast<String, String>());
     });
     return true;
}

提示:这里我们也可以改为网络请求,拿到数据后一样转换类型

  • JKLocalizationsDelegate 中使用 异步 进行加载:


@override
Future<JKLocalizations> load(Locale locale) async {
   final localization = JKLocalizations(locale);
   await localization.loadJson();
   return localization;
}


提示:我们自己的配置 其它文本国际化,我们每次都要

  • 1、修改 json文件
  • 2、在 JKLocalizations 里面增加 对应的 get 方法,每次还要写 key ,很容易写错,要注意
  • 3、如果增加新的语言,我们还要 修改JKLocalizationsDelegate 增加支持的语言 和 在 iOS的 info.plist 文件里面增加新的语言类型
目录
相关文章
|
JSON Dart IDE
Flutter实现国际化
开发一个App,如果我们的App需要面向不同的语种(比如中文、英文、繁体等),那么我们需要对齐进行国际化开发
1399 0
Flutter实现国际化
|
4月前
|
JSON 自然语言处理 Android开发
Flutter本地化(国际化)之App名称
Flutter本地化(国际化)之App名称
75 1
|
5月前
|
存储 Dart 开发工具
flutter实现语言的国际化
【7月更文挑战第16天】
90 1
|
7月前
|
自然语言处理 前端开发 开发者
【Flutter前端技术开发专栏】Flutter中的国际化与本地化支持
【4月更文挑战第30天】Flutter支持国际化与本地化,借助`Intl`包和`Localizations`类,帮助开发者实现多语言应用。`Intl`提供日期、时间格式化,而`Localizations`管理不同语言环境的资源。在`pubspec.yaml`添加`intl`依赖,创建本地化资源文件并定义`LocalizationsDelegate`。通过`Localizations.of()`获取本地化资源,实现应用适应不同语言环境。
214 0
【Flutter前端技术开发专栏】Flutter中的国际化与本地化支持
|
7月前
|
存储 自然语言处理 API
Flutter应用的国际化支持:实现多语言环境的优雅策略
【4月更文挑战第26天】Flutter提供强大的国际化(i18n)和本地化(l10n)支持,使开发者能轻松实现应用多语言特性。通过定义`.arb`文件来管理字符串资源,使用`LocalizationsDelegate`加载资源,设置应用语言环境,以及在UI中使用`S.of(context).someString`访问字符串。进阶技巧包括字符串格式化、复数形式、双向文本和Unicode支持。充分测试确保所有语言正确显示。随着全球化需求增长,Flutter的国际化支持成为应用开发关键。
|
7月前
|
存储 容器
Flutter 应用服务:主题、暗黑、国际化、本地化-app_service库
Flutter 应用服务:主题、暗黑、国际化、本地化-app_service库
282 0
|
JSON Dart IDE
Day18 - Flutter - 国际化(下)
Day18 - Flutter - 国际化(下)
566 0
Day18 - Flutter - 国际化(下)
|
自然语言处理 JavaScript 前端开发
|
Dart
Flutter - International 国际化,Localization 本地化, 使用字符串Map
记录一种简单的方式实现字符串的国际化。 这里没有用到Intl包,而是将所需的字符串存放在一个map中。 步骤: MaterialApp中添加本地化代理和语言类型 创建文字资源文件 新建一个类继承LocalizationsDelegate,和文字资源文件联系起来 使用代理获取想要的文字资源 新建项目international_demo,得到一个带按钮示例工程。
3772 0
|
JSON Dart 开发工具
Flutter - International 国际化,Localization 本地化, 使用Intl
新建项目,得到一个示例工程。本例中使用intl包来管理文字资源。 项目地址: https://github.com/RustFisher/localization_demo 步骤: 添加依赖项 - intl 创建文字资源文件 生成arb文件 新增和修改arb文件 根据arb生成dart文件...
4856 0