多语言(国际化)

国际化(internationalization 简称 i18n
  终端(手机)系统语言切换时,flutter 应用跟随切换
 
内容
  组件(Widget)国际化
    例如:日历、弹窗等常用组件的国际化

  文本国际化(包括文本的顺序)
    自定义文本的国际化

1、组件国际化
 
使用步骤:
(1)、在 pubspec.yaml 中引入 flutter_localizations
 
(2)、设置 MaterialApp
    ①、import 'package:flutter_localizations/flutter_localizations.dart';
    ②、 localizationsDelegates(指定哪些组件需要进行国际化)
    ③、supportedLocales(指定要支持哪些语言)
 
例如:在 main.dart 中添加以上设置内容
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import '09_form/form_05_datepicker.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: "Flutter Demo",
      home: Home(),
      debugShowCheckedModeBanner: false,
      // 国际化
      localizationsDelegates: [
        // 本地化代理
        GlobalMaterialLocalizations.delegate, // Material 国际化
        GlobalCupertinoLocalizations.delegate, // Cupertino 国际化
        GlobalWidgetsLocalizations.delegate, // 组件国际化
      ],
      supportedLocales: [
        Locale('en', 'US'), // 美国英语
        Locale('zh', 'CN'), // 简体中文
      ],
    );
  }
}

 

(3)、查看组件效果
  在模拟器上,切换语言,然后,查看组件效果(例如:日历)

 

2、文本国际化

使用步骤:

(1)、创建本地化类 CustomLocalizations
(2)、创建本地化类的代理
      CustomLocalizationsDelegate extends LocalizationsDelegate<CustomLocalizations>
        isSupported(当前本地化,是否在有效的语言范围内)
        shouldReload(本地化重新构建时,是否调用 load 方法,加载本地化资源)
        load(语言发生变更时,加载对应的本地化资源)
// CustomLocalizations.dart

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

class CustomLocalizations {
  final Locale locale;
  CustomLocalizations(this.locale);

  static final Map<String, Map<String, String>> _localizedValues = {
    'en': {
      'title': 'Home',
      'greet': 'Hello',
    },
    'zh': {
      'title': '首页',
      'greet': '你好',
    }
  };

  String? t(String key) {
    return _localizedValues[locale.languageCode]![key];
  }

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

  static CustomLocalizationsDelegate delegate = CustomLocalizationsDelegate();
}

class CustomLocalizationsDelegate
    extends LocalizationsDelegate<CustomLocalizations> {
  // 当前本地化,是否在有效的语言范围内
  @override
  bool isSupported(Locale locale) {
    return ['en', 'zh'].contains(locale.languageCode);
  }

  // 语言发生变更时,加载对应的本地化资源
  @override
  Future<CustomLocalizations> load(Locale locale) {
    return SynchronousFuture(CustomLocalizations(locale));
  }

  // 本地化重新构建时,是否调用 load 方法,加载本地化资源
  @override
  bool shouldReload(covariant LocalizationsDelegate<CustomLocalizations> old) {
    return false;
  }
}

 

(3)、使用本地化类 CustomLocalizations.delegate
// main.dart

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import '11_theme/theme_01_i18n.dart';
import '11_theme/CustomLocalizations.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Demo",
      home: const Home(),
      debugShowCheckedModeBanner: false,
      // 国际化
      localizationsDelegates: [
        // 本地化代理
        CustomLocalizations.delegate,
        GlobalMaterialLocalizations.delegate, // Material 国际化
        GlobalCupertinoLocalizations.delegate, // Cupertino 国际化
        GlobalWidgetsLocalizations.delegate, // 组件国际化
      ],
      supportedLocales: const [
        Locale('en', 'US'), // 美国英语
        Locale('zh', 'CN'), // 简体中文
      ],
    );
  }
}

 

(4)、新建一个 theme_01_i18n.dart 文件,使用文本国际化,查看效果

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // 文本国际化
        title: Text(
          Localizations.of(context, CustomLocalizations).t('title'),
        ),
      ),
      body: const HomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Center(
      // 文本国际化
      child: Text(
        Localizations.of(context, CustomLocalizations).t('greet'),
        style: const TextStyle(fontSize: 60),
      ),
    );
  }
}

 

3、加载语言包

使用步骤:
(1)、检测当前语言
  loadResolutionCallback
    locale.languageCode (语言代码,例如:en、zh)
    locale.countryCode (国家代码,例如:US、CN)
// main.dart

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import '11_theme/theme_01_i18n.dart';
import '11_theme/CustomLocalizations.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Demo",
      home: const Home(),
      debugShowCheckedModeBanner: false,
      // 国际化
      localizationsDelegates: [
        // 本地化代理
        CustomLocalizations.delegate,
        GlobalMaterialLocalizations.delegate, // Material 国际化
        GlobalCupertinoLocalizations.delegate, // Cupertino 国际化
        GlobalWidgetsLocalizations.delegate, // 组件国际化
      ],
      supportedLocales: const [
        Locale('en', 'US'), // 美国英语
        Locale('zh', 'CN'), // 简体中文
      ],
      // 检测当前语言
      localeResolutionCallback: (locale, supportedLocales) {
        print('device locale: $locale'); // device locale: zh_Hans_CN
        print('supportedLocales: $supportedLocales'); // [en_US, zh_CN]
        for (var supportedLocale in supportedLocales) {
          print('supportedLocale: $supportedLocale');
          // supportedLocale: en_US
          // supportedLocale: zh_CN
          if (supportedLocale.languageCode == locale?.languageCode &&
              supportedLocale.countryCode == locale?.countryCode) {
            return supportedLocale;
          }
        }
        return supportedLocales.first;
      },
    );
  }
}

 

(2)、设置语言包
  ①、创建语言文件

 

  ②、在 pubspec.yaml 中配置语言资源

 

(3)、异步加载语言包
  ①、在 CustomLocalizations 中,添加 loadJson() 方法
  ②、在 CustomLocalizationsDelegate 中,调用 CustomLocalizations 的 loadJson() 方法
// CustomLocalizations.dart

import 'dart:convert';

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

class CustomLocalizations {
  final Locale locale;
  CustomLocalizations(this.locale);

  // static final Map<String, Map<String, String>> _localizedValues = {
  //   'en': {
  //     'title': 'Home',
  //     'greet': 'Hello',
  //   },
  //   'zh': {
  //     'title': '首页',
  //     'greet': '你好',
  //   }
  // };

  // String? t(String key) {
  //   return _localizedValues[locale.languageCode]![key];
  // }

  // 加载本地语言包
  late Map<String, String> _localizedValues;

  Future<bool> loadJson() async {
    String jsonString =
        await rootBundle.loadString('lang/${locale.languageCode}.json');
    Map<String, dynamic> jsonMap = jsonDecode(jsonString);
    _localizedValues =
        jsonMap.map((key, value) => MapEntry(key, value.toString()));
    print('_localizedValues, $_localizedValues');
    // _localizedValues, {title: 主页, greet: 你好 Flutter}
    return true;
  }

  String? t(String key) {
    return _localizedValues[key];
  }

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

  static CustomLocalizationsDelegate delegate = CustomLocalizationsDelegate();
}

class CustomLocalizationsDelegate
    extends LocalizationsDelegate<CustomLocalizations> {
  // 当前本地化,是否在有效的语言范围内
  @override
  bool isSupported(Locale locale) {
    return ['en', 'zh'].contains(locale.languageCode);
  }

  // 语言发生变更时,加载对应的本地化资源
  @override
  // Future<CustomLocalizations> load(Locale locale) {
  //   return SynchronousFuture(CustomLocalizations(locale));
  // }
  Future<CustomLocalizations> load(Locale locale) async {
    CustomLocalizations localizations = CustomLocalizations(locale);
    await localizations.loadJson();
    return localizations;
  }

  // 本地化重新构建时,是否调用 load 方法,加载本地化资源
  @override
  bool shouldReload(covariant LocalizationsDelegate<CustomLocalizations> old) {
    return false;
  }
}

(4)、重新启动应用,切换语言,查看效果

 

posted @ 2022-06-30 17:53  rogerwu  阅读(442)  评论(0编辑  收藏  举报