在前面(四)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<MoreLocalization> {
FZLocalizationDelegate();
///是否支持某个Local
///支持中文和英语
@override
bool isSupported(Locale locale) {
return ['zh', 'en'].contains(locale.languageCode);
}
///shouldReload的返回值决定当Localizations Widget重新build时,是否调用load方法重新加载Locale资源
@override
bool shouldReload(LocalizationsDelegate<MoreLocalization> old) {
return false;
}
///根据locale,创建一个对象用于提供当前locale下的文本显示
///Flutter会调用此类加载相应的Locale资源类
@override
Future<MoreLocalization> load(Locale locale) {
return SynchronousFuture<MoreLocalization>(
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<String, BaseLanguage> _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<FirstPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("ReduxDemo3"),
),
body: Center(
child: Column(
children: <Widget>[
SizedBox(height: 50,),
Text("MoreLocalization 当前内容:${MoreLocalization.of(context).currentLocalized.name}"),
SizedBox(height: 50,),
/// 获取系统当前语言
Text("Localizations 当前语言:${Localizations.localeOf(context)}"),
],
)
),
);
}
}
效果
系统语言英文:
系统语言中文:
Redux,App语言可在App内手动变更
locale_redux.dart
final LocaleReducer = combineReducers<Locale>([
TypedReducer<Locale, LocaleRefreshAction>(_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<ReduxState>(
getReduce,
initialState: ReduxState(
locale: Locale("zh", 'CN')
)
);
runApp(ReduxDemo3(store,));
}
class ReduxDemo3 extends StatelessWidget {
final Store<ReduxState> store;
ReduxDemo3(this.store);
@override
Widget build(BuildContext context) {
return StoreProvider(
store: store,
/// StoreBuilder后要跟上我们定义的那个State类,要不会报错,
child: StoreBuilder<ReduxState>(builder: (BuildContext context, Store<ReduxState> 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<FirstPage> {
@override
Widget build(BuildContext context) {
return StoreBuilder<ReduxState>(
builder: (BuildContext context, Store<ReduxState> store){
return Scaffold(
appBar: AppBar(
title: Text("ReduxDemo3"),
),
body: Center(
child: Column(
children: <Widget>[
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个文本显示的都是中文的内容
总结
关键点就是实现 Delegate类、Localizations类