(五)Flutter Redux 中的国际化

在前面(四)Flutter Redux 中实现简单换肤清楚了一个简单的换肤,这次来看下Redux中实现国际化。
自定义国际化的方法有2种:
1、基于Map,该方式要我们自己手动来维护多套语言。
2、基于Intl,该方式是开发人员通过工具将翻译好的arb文件转为代码。
这边主要讲的是基于Map。Intl的网上也有很多文章。

导入库

  flutter_localizations:
    sdk: flutter

自定义国际化需要实现两个类

Delegate类

在Locale改变时加载新的Locale资源,Delegate类需要继承自LocalizationsDelegate类,实现相应的接口。LocalizationsDelegate需要提供一个泛型参数,也就是下面的 自定义的 Localizations 类。

localization_delegate.dart

class FZLocalizationDelegate extends LocalizationsDelegate {

  FZLocalizationDelegate();

  ///是否支持某个Local
  ///支持中文和英语
  @override
  bool isSupported(Locale locale) {
    return ['zh', 'en'].contains(locale.languageCode);
  }

  ///shouldReload的返回值决定当Localizations Widget重新build时,是否调用load方法重新加载Locale资源
  @override
  bool shouldReload(LocalizationsDelegate old) {
    return false;
  }

  ///根据locale,创建一个对象用于提供当前locale下的文本显示
  ///Flutter会调用此类加载相应的Locale资源类
  @override
  Future load(Locale locale) {
    return SynchronousFuture(
        MoreLocalization(locale)
    );
  }

  static FZLocalizationDelegate delegate = FZLocalizationDelegate();
}

Localizations类

提供不同语言的数据。这边的定义方式是提供1个抽象类,接着1个英文1个中文的实现类。

more_localization.dart

class MoreLocalization {

  final Locale locale;
  MoreLocalization(this.locale);

  /// 基于Map,根据当前语言的 languageCode: en或zh来获取对应的文案
  static Map _localValue = {
    'en' : EnLanguage(),
    'zh' : ChLanguage()
  };

  /// 返回当前的内容维护类
  BaseLanguage get currentLocalized {
    return _localValue[locale.languageCode];
  }

  ///通过 Localizations.of(context,type) 加载当前的 FZLocalizations
  static MoreLocalization of(BuildContext context) {
    return Localizations.of(context, MoreLocalization);
  }
}

/// 这个抽象类和它的实现类可以拉出去新建类
/// 中文和英语 语言内容维护
abstract class BaseLanguage {
  String name;
}

class EnLanguage implements BaseLanguage {
  @override
  String name = "This is English";
}

class ChLanguage implements BaseLanguage {
  @override
  String name = "这是中文";
}

无Redux,App语言随系统语言变化

main.dart
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_demo/State/Language_NoRedux/first_page.dart';
import 'package:flutter_demo/State/Language_NoRedux/localization_delegate.dart';

main() {
  runApp(ReduxDemo3());
}

class ReduxDemo3 extends StatelessWidget {

  ReduxDemo3();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ReduxDemo3',
      localizationsDelegates: [
        /// 本地化的代理类
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        /// 注册我们的Delegate
        FZLocalizationDelegate.delegate
      ],
      supportedLocales: [
        const Locale('en', 'US'), // 美国英语
        const Locale('zh', 'CN'), // 中文简体
      ],
      /// 监听系统语言切换
      localeListResolutionCallback: (deviceLocale, supportedLocales){
        print('deviceLocale: $deviceLocale');
        // 系统语言是英语: deviceLocale: [en_CN, en_CN, zh_Hans_CN]
        // 系统语言是中文: deviceLocale: [zh_CN, zh_Hans_CN, en_CN]
        print('supportedLocales: $supportedLocales');
      },
      home: FirstPage(),
    );
  }
}
first_page.dart
class FirstPageState extends State {
  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text("ReduxDemo3"),
      ),
      body: Center(
          child: Column(
            children: [
              SizedBox(height: 50,),
              Text("MoreLocalization 当前内容:${MoreLocalization.of(context).currentLocalized.name}"),
              SizedBox(height: 50,),
              /// 获取系统当前语言
              Text("Localizations 当前语言:${Localizations.localeOf(context)}"),
            ],
          )
      ),
    );
  }
}
效果

系统语言英文:
(五)Flutter Redux 中的国际化_第1张图片
系统语言中文:
(五)Flutter Redux 中的国际化_第2张图片

Redux,App语言可在App内手动变更

locale_redux.dart
final LocaleReducer = combineReducers([
  TypedReducer(_refreshLocale)
]);

Locale _refreshLocale(Locale locale, LocaleRefreshAction action) {
  locale = action.locale;
  return locale;
}

class LocaleRefreshAction {
  Locale locale;
  LocaleRefreshAction(this.locale);
}
redux_state.dart
/// 定义一个state
class ReduxState {
  Locale locale;
  ReduxState({this.locale});
}

/// 定义action,将action放到theme_redux类里去定义

/// 定义reducer
ReduxState getReduce(ReduxState state, action) {
  return ReduxState(
    locale: LocaleReducer(state.locale, action)
  );
}
redux_state.dart

这边虽然有给了全局Store默认的语言,但是在下面的 监听系统语言变更回调里 localeListResolutionCallback里有再修改一次。

import 'package:flutter_demo/State/Language_Redux/redux_state.dart';
import 'package:flutter_demo/State/Language_Redux/first_page.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_demo/State/Language_Redux/localization_delegate.dart';
import 'package:flutter_demo/State/Language_Redux/locale_redux.dart';

main() {
  /// 创建全局Store
  final store = Store(
      getReduce,
      initialState: ReduxState(
        locale: Locale("zh", 'CN')
      )
  );
  runApp(ReduxDemo3(store,));
}

class ReduxDemo3 extends StatelessWidget {

  final Store store;
  ReduxDemo3(this.store);

  @override
  Widget build(BuildContext context) {
    return StoreProvider(
        store: store,
        /// StoreBuilder后要跟上我们定义的那个State类,要不会报错,
        child: StoreBuilder(builder: (BuildContext context, Store store){
          return MaterialApp(
            title: 'ReduxDemo3',
            localizationsDelegates: [
              GlobalMaterialLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
              FZLocalizationDelegate.delegate
            ],
            /// 这边设置 locale 主要是为了在项目里手动更改语言,如果是不想手动变更,而是要随系统自动变更可以注释
            locale: store.state.locale,
            supportedLocales: [
              const Locale('en', 'US'), // 美国英语
              const Locale('zh', 'CN'), // 中文简体
            ],
            /// 监听系统语言切换
            localeListResolutionCallback: (deviceLocale, supportedLocales){
              print('deviceLocale: $deviceLocale');
              // 系统语言是英语: deviceLocale: [en_CN, en_CN, zh_Hans_CN]
              // 系统语言是中文: deviceLocale: [zh_CN, zh_Hans_CN, en_CN]
              print('supportedLocales: $supportedLocales');

              /// 系统自动检测到语言后修改Store里的语言
              if (deviceLocale.length > 0) {
                if (store.state.locale.languageCode != deviceLocale[0].languageCode) {
                  store.dispatch(LocaleRefreshAction(deviceLocale[0]));
                }
              }
            },
            home: FirstPage(),
          );
        })
    );
  }
}
first_page.dart
class FirstPageState extends State {
  @override
  Widget build(BuildContext context) {

    return StoreBuilder(
        builder: (BuildContext context, Store store){
          return Scaffold(
            appBar: AppBar(
              title: Text("ReduxDemo3"),
            ),
            body: Center(
                child: Column(
                  children: [
                    SizedBox(height: 50,),
                    FlatButton(
                        onPressed: (){
                          store.dispatch(LocaleRefreshAction(Locale('zh','CH')));
                        },
                        child: Text('手动设置APP语言为:中文')
                    ),
                    SizedBox(height: 50,),
                    FlatButton(
                        onPressed: (){
                          store.dispatch(LocaleRefreshAction(Locale('en','US')));
                        },
                        child: Text('手动设置APP语言为:英文')
                    ),
                    SizedBox(height: 50,),
                    Text("MoreLocalization 当前语言:${MoreLocalization.of(context).currentLocalized.name}"),
                    SizedBox(height: 50,),
                    Text("Localizations 当前语言:${Localizations.localeOf(context)}"),
                    SizedBox(height: 50,),
                    Text("Store 当前语言:${store.state.locale.languageCode}"),
                  ],
                )
            ),
          );
        }
    );
  }
}
效果

当前系统的语言改为了中文,所以下面3个文本显示的都是中文的内容
(五)Flutter Redux 中的国际化_第3张图片

总结

关键点就是实现 Delegate类Localizations类

你可能感兴趣的:(Flutter)