52Flutter 国际化

Flutter 国际化

1.介绍

App内可能会使用不同的语言,进行国际化是有必要的, 而且是开发时就应该首先准备的,等到后期维护阶段在进行国际化,会非常麻烦,建议在开发时就准备国际化,方便后期维护

2.使用

依赖:

  flutter_localizations:
    sdk: flutter
  flutter_cupertino_localizations: ^1.0.1 //适配IOS
1.自定义LocalizationsDelegate
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_first/day56Language/day3/MyLocations.dart';


class MyLocationDelegate extends LocalizationsDelegate<MyLocations> {

  // 1.
  static MyLocationDelegate delegate = MyLocationDelegate();

  // 2.
  @override
  bool isSupported(Locale locale) {
    return ["en", "zh"].contains(locale.languageCode);
  }

  // 3
  @override
  Future<MyLocations> load(Locale locale) async {
    return SynchronousFuture(MyLocations(locale));
  }

  // 4
  @override
  bool shouldReload(MyLocationDelegate old) {
    return false;
  }
}

  • isSupported:用于当前环境的Locale,是否在我们支持的语言范围
  • shouldReload:当Localizations Widget重新build时,是否调用load方法重新加载Locale资源
    • 一般情况下,Locale资源只应该在Locale切换时加载一次,不需要每次Localizations重新build时都加载一遍;
    • 所以一般情况下返回false即可;
  • load方法:当Locale发生改变时(语言环境),加载对应的HYLocalizations资源
    • 这个方法返回的是一个Future,因为有可能是异步加载的;
    • 但是我们这里是直接定义的一个Map,因此可以直接返回一个同步的
2.定义资源
import 'package:flutter/material.dart';

class MyLocations {
  final Locale locale;

  MyLocations(this.locale);

  static Map<String, Map<String, String>> _localizedValues = {
    "en": {
      "title": "home",
      "greet": "hello~",
    },
    "zh": {
      "title": "首页",
      "greet": "你好~",
    }
  };

  String get title {
    return _localizedValues[locale.languageCode]["title"];
  }

  String get greet {
    return _localizedValues[locale.languageCode]["greet"];
  }
}
3.设置MaterialApp
1.localizationsDelegates

指定哪些Widget需要进行国际化

  • 用于生产本地化值集合的工厂
  • 我们这里指定了Material、Widgets、Cupertino都使用国际化
localizationsDelegates: [
    GlobalMaterialLocalizations.delegate, // 指定本地化的字符串和一些其他的值
    GlobalCupertinoLocalizations.delegate, // 对应的Cupertino风格
    GlobalWidgetsLocalizations.delegate, // 指定默认的文本排列方向, 由左到右或由右到左
    
    //1.注意,一定要添加自己的国际化
    MyLocationDelegate.delegate
  ],
2.如果要指定语言代码、文字代码和国家代码,支持的
      supportedLocales: [
        const Locale.fromSubtags(languageCode: 'en'),
        const Locale.fromSubtags(languageCode: 'zh'),
      ],
3.显示
Localizations.of(context, MyLocations).title

稍微封装一下

  static MyLocations of(BuildContext context) {
    return Localizations.of(context, MyLocations);
  }

代码如下

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


import 'package:flutter/cupertino.dart';

import 'MyAppLocationDelegate.dart';
import 'MyLocations.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  MyApp({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate, // 指定本地化的字符串和一些其他的值
        GlobalCupertinoLocalizations.delegate, // 对应的Cupertino风格
        GlobalWidgetsLocalizations.delegate, // 指定默认的文本排列方向, 由左到右或由右到左
        MyLocationDelegate.delegate
      ],
      locale: Locale("en"),
      // supportedLocales: [Locale("en"), Locale("zh")],
      supportedLocales: [
        const Locale.fromSubtags(languageCode: 'en'),
        const Locale.fromSubtags(languageCode: 'zh'),
      ],
      home: Scaffold(
        //标题栏
        appBar: AppBar(
          title: Text("Flutter Demo"),
        ),
        //内容区域
        body: LanguageView(),
      ),
    );
  }
}
class LanguageView extends StatefulWidget {
  LanguageView({Key key}) : super(key: key);

  @override
  _LanguageViewState createState() {
    return _LanguageViewState();
  }
}

class _LanguageViewState extends State<LanguageView> {
  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Center(
      child: Text(MyLocationDelegate.of(context).title),
    );
  }
}

3.异步加载数据

import 'dart:convert';

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

class AppLocalizations {

  // 1
  final Locale locale;

  AppLocalizations(this.locale);

  // 2
  static AppLocalizations of(BuildContext context) {
    return Localizations.of<AppLocalizations>(context, AppLocalizations);
  }

  static Map<String, Map<String, String>> _localizedStrings = {};

  // 3 异步加载数据
  Future loadJson() async {
    final jsonString = await rootBundle.loadString("assets/json/i18n.json");
    Map<String, dynamic> map = json.decode(jsonString);
    _localizedStrings = map.map((key, value) => MapEntry(key, value.cast<String, String>()));
  }

  // 4
  String get title => _localizedStrings[this.locale.languageCode]["title"];

  String get button => _localizedStrings[this.locale.languageCode]["button"];

  String get drawerTip =>
      _localizedStrings[this.locale.languageCode]["drawer_tip"];

  String get closeDrawer =>
      _localizedStrings[this.locale.languageCode]["close_drawer"];

}

在自定义的LocalizationsDelegate中

  // 3
  @override
  Future<AppLocalizations> load(Locale locale) async {
    final appLocalizations = AppLocalizations(locale);
    await appLocalizations.loadJson();
    return appLocalizations;
  }

4.国际化

1.下载插件Flutter Intl

2.配置文件(为整个项目)

image-20200819233727693

会在 pubspec.yaml中增加以下字段**

flutter_intl:  
    enabled: true

会在lib目录下增加 generated 和 l10n两个包

generated包下的intl包默认存在一个messages_all.dart和messages_en.dart文件,messages开头的文件会在添加语言后自动生成
l10n包下存在一个intl_en.arb文件

3.使用Add Locale生成其他语言的arb文件

image-20200819234431082

例如:zh_CN , 会在l10n包下生成Intl_zh_CN.arb文件 , 可在其中填入对应的文案.

4.在MaterialApp中配置

 @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      localizationsDelegates: const [
        S.delegate, //记得这个一定要写
        GlobalMaterialLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate
      ],
      supportedLocales: S.delegate.supportedLocales,
      localeListResolutionCallback: (locales, supportedLocales) {
        print(locales);
        return;
      },
      locale: Locale('zh','TW'),
      home: Scaffold(
        //标题栏
        appBar: AppBar(
          title: Text("Flutter Demo"),
        ),
        //内容区域
        body: LanguageView(),
      ),
    );
  }

5.使用

    child: Text(S.of(context).title),

注意:

  1. 假设系统语言为zh_TW , 项目并不支持,会优先寻找zh的其他语言 , 以supportedLocales顺序从上向下寻找.
  2. 支持语言的顺序为字符串排序 (如zh_A会在zh_B之前) , 并非添加语言的顺序.

完整代码:

import 'package:flutter/material.dart';
import 'package:flutter_first/generated/l10n.dart';
import 'package:get/get.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  MyApp({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return GetMaterialApp(
      localizationsDelegates: const [
        S.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate
      ],
      supportedLocales: S.delegate.supportedLocales,
        ///当传入的是不支持的语种,可以根据这个回调,返回相近,并且支持的语种
        localeResolutionCallback: (local, support) {
          ///当前软件支行的语言 也就是[supportedLocales] 中配制的语种
          if (support.contains(local)) {
            print('support  $local');
            return local;
          }
          ///如果当前软件运行的手机环境不在 [supportedLocales] 中配制的语种范围内
          ///返回一种默认的语言环境,这里使用的是中文
          print('no_support local is $local and support is $support');
          return const Locale('zh', 'CN');
        },
      locale: Locale('zh', 'TW'),
      home: Scaffold(
        //标题栏
        appBar: AppBar(
          title: Text("Flutter Demo"),
        ),
        //内容区域
        body: LanguageView(),
      ),
    );
  }
}

class LanguageView extends StatefulWidget {
  LanguageView({Key key}) : super(key: key);

  @override
  _LanguageViewState createState() {
    return _LanguageViewState();
  }
}

class _LanguageViewState extends State<LanguageView> {
  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Center(
      child: Text(S.of(context).title),
    );
  }
}

————————localeListResolutionCallback可以不用写,intl自由规则识别,写了反而不好

5.使用Get切换语言

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Center(
      child: Column(
        children: [
          OutlinedButton(onPressed: (){
            var locale = Locale.fromSubtags(languageCode: 'en', countryCode: 'US2');
            Get.updateLocale(locale);
          }, child: Text('点击')),
          Text(S.of(context).title)
        ],
      ),
    );
  }

6.使用Provider切换

if (i != null) {
       if (i == 1) {
            Provider.of<CurrentLocale>(context, listen: false)
                 .setLocale(const Locale('zh', "CH"));
      } else {
            Provider.of<CurrentLocale>(context, listen: false)
                 .setLocale(const Locale('en', "US"));
      }
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值