关于Flutter的国际化有三种实现方式,本文主要讲述的是使用flutter_localizations的实现方式。
下面是我们最终实现的效果图:
-
项目结构
2.代码分析
assets/i18n下的两个json文件,是我们翻译中分别用到的源文件,en.json和zh.json的源码如下所示:
en.json:
{
"hello": "Hello!",
"greetTo": "Nice to meet you,{{name}}!",
"app_title":"Flutter Internationalization",
"jump_to_second_page": "Jump to the second page",
"second_page": "Second page",
"switch": "Switch"
}
zh.json
{
"hello": "你好!",
"greetTo": "{{name}},见到你很高兴!",
"app_title":"Flutter国际化",
"jump_to_second_page": "跳转到第二个界面",
"second_page": "第二个界面",
"switch": "切换"
}
翻译资源json准备完之后,在pubspec.yaml中添加所需要的依赖,如下图所示:
红框的部分就是我们项目所以需要的。
initialize_i18n.dart文件是用来加载assets/i18n下的json资源的:
import 'dart:convert';
import 'package:flutter/services.dart';
import 'constant.dart' show languages;
//加载json资源
Future<String> loadJsonFromAsset(language) async {
return await rootBundle.loadString('assets/i18n/' + language + '.json');
}
Map<String, String> convertValueToString(obj) {
Map<String, String> result = {};
obj.forEach((key, value) {
result[key] = value.toString();
});
return result;
}
Future<Map<String, Map<String, String>>> initializeI18n() async {
Map<String, Map<String, String>> values = {};
for (String language in languages) {
Map<String, dynamic> translation =
json.decode(await loadJsonFromAsset(language));
values[language] = convertValueToString(translation);
}
return values;
}
localizations.dart文件:
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'constant.dart';
//调用该类获取字符串内容
class MyLocalizations {
final Map<String, Map<String, String>> localizedValues;
final Locale locale;
MyLocalizations(this.locale, this.localizedValues);
static MyLocalizations of(BuildContext context) {
return Localizations.of<MyLocalizations>(context, MyLocalizations);
}
String get hello {
return localizedValues[locale.languageCode]['hello'];
}
greetTo(name) {
return localizedValues[locale.languageCode]['greetTo']
.replaceAll('{{name}}', name);
}
String get homeTitle {
return localizedValues[locale.languageCode]['app_title'];
}
String get jumpToSecondPage {
return localizedValues[locale.languageCode]['jump_to_second_page'];
}
String get secondPage {
return localizedValues[locale.languageCode]['second_page'];
}
String get qh {
return localizedValues[locale.languageCode]['switch'];
}
}
class MyLocalizationsDelegate extends LocalizationsDelegate<MyLocalizations> {
Map<String, Map<String, String>> localizedValues;
MyLocalizationsDelegate(this.localizedValues);
@override
bool isSupported(Locale locale) => languages.contains(locale.languageCode);
@override
Future<MyLocalizations> load(Locale locale) {
return SynchronousFuture<MyLocalizations>(
MyLocalizations(locale, localizedValues));
}
@override
bool shouldReload(LocalizationsDelegate<MyLocalizations> old) {
return false;
}
}
MyLocalizationsDelegate中的languges来自于constant.dart.
List<String> languages=['en','zh'];
最后,在main.dart中将上面的每个部分连接起来:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'constant.dart';
import 'initialize_i18n.dart';
import 'localizations.dart';
import 'pages/second_page.dart';
//import 'package:url_launcher/url_launcher.dart';
void main() async {
//加载中英文数据源
Map<String, Map<String, String>> localizedValues = await initializeI18n();
runApp(MyApp(localizedValues));
}
class MyApp extends StatefulWidget {
final Map<String, Map<String, String>> localizedValues;
MyApp(this.localizedValues);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _locale = 'en';
//切换语言
onChangeLanguage() {
if (_locale == 'en') {
setState(() {
_locale = 'zh';
});
} else {
setState(() {
_locale = 'en';
});
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [
MyLocalizationsDelegate(widget.localizedValues),//设置自己定义的代理
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,//用于兼容ios
],
locale: Locale(_locale),//设置当前的语言
supportedLocales: languages.map((language) => Locale(language, '')),
home: MyHomePage(onChangeLanguage),
);
}
}
class MyHomePage extends StatelessWidget {
final VoidCallback onChangeLanguage;
MyHomePage(this.onChangeLanguage);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text(MyLocalizations.of(context).homeTitle),
),
body: Container(
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.only(top: 30),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Text(MyLocalizations.of(context).greetTo('胡歌')),
SizedBox(
height: 20.0,
),
Container(
width: 200.0,
height: 40.0,
child: FlatButton(
color: Colors.lightBlue,
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (cxt) {
return SecondPage();
}));
},
child: Text(
MyLocalizations.of(context).jumpToSecondPage,
style: TextStyle(color: Colors.white),
)),
),
],
),
),
floatingActionButton: new FloatingActionButton(
child: Text(MyLocalizations.of(context).qh),
onPressed: onChangeLanguage),
);
}
}
在main.dart中,我们可以直接利用MyLocalizations.of(context).homeTitle等给对应的字符串赋值。点击按钮切换时,只需要切换MaterialApp中locale的值即可。
网友评论