Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 0b658a0

Browse files
feat: flutter_intl readme
1 parent 2be1e24 commit 0b658a0

File tree

1 file changed

+366
-10
lines changed

1 file changed

+366
-10
lines changed

‎flutter_intl/README.md

Lines changed: 366 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,372 @@
1-
# flutter_intl
1+
# 以$t形式使用flutter多语言
2+
3+
## 前言
4+
关于flutter国际化的具体介绍,大家可以移步[国际化Flutter App](https://flutterchina.club/tutorials/internationalization/)
5+
6+
本文主要介绍在flutter如何使用多语言并且如何像web使用i18n一样使用多语言($t)和实现语言切换,这对前端开发人员会更加友好。
7+
8+
## 项目地址
9+
[flutter-ui](https://github.com/efoxTeam/flutter-ui), 这是包含flutter组件介绍的开源项目,欢迎star
10+
11+
[flutter_intl](https://github.com/efoxTeam/flutter-demo/tree/master/flutter_intl) 本教程的项目源码,欢迎star
12+
13+
## 效果
14+
![英文](https://user-gold-cdn.xitu.io/2019/5/13/16ab050e3802eacd?w=742&h=1548&f=png&s=99048)
15+
16+
![中文](https://user-gold-cdn.xitu.io/2019/5/13/16ab051b0d0dd4a0?w=768&h=1536&f=png&s=194623)
17+
18+
## 如何使用
19+
### 添加依赖
20+
* 在pubspec.yaml中引入依赖
21+
``` dart
22+
dependencies:
23+
flutter_localizations:
24+
sdk: flutter
25+
```
26+
* 执行
27+
``` dart
28+
flutter packages get
29+
```
30+
### 新建文件locale
31+
``` dart
32+
locale
33+
|-en.json
34+
|-zh.json
35+
```
36+
多语言的文件
37+
* en.json
38+
``` dart
39+
{
40+
"title_page": "i18n",
41+
"title_appbar": "i18n",
42+
"content": {
43+
"currentLanguage": "The current language is English",
44+
"zh": "zh",
45+
"en": "en"
46+
}
47+
}
48+
```
49+
* zh.json
50+
``` dart
51+
{
52+
"title_page": "国际化例子",
53+
"title_appbar": "国际化例子",
54+
"content": {
55+
"currentLanguage": "当前语言是中文",
56+
"zh": "中文",
57+
"en": "英文"
58+
}
59+
}
60+
```
61+
### lib下新建lang
62+
``` dart
63+
lang
64+
|- config.dart
65+
|- index.dart
66+
```
67+
* config.dart
68+
``` dart
69+
import 'package:flutter/material.dart';
70+
71+
class ConfigLanguage {
72+
static List<Locale> supportedLocales = [
73+
Locale('zh', 'CH'),
74+
Locale('en', 'US')
75+
];
76+
77+
static Map<String, dynamic> supportLanguage = {
78+
"zh": {"code": "zh", "country_code": "CH"},
79+
"en": {"code": "en", "country_code": "US"},
80+
};
81+
82+
static dynamic defaultLanguage = {
83+
"code": "zh",
84+
"country_code": "CH"
85+
};
86+
}
87+
```
88+
config.dart作用主要是将配置性的内容统一到一个文件中
89+
* index.dart
90+
``` dart
91+
import 'package:flutter/material.dart';
92+
import 'dart:convert';
93+
import 'package:flutter/services.dart' show rootBundle;
94+
import 'package:flutter/foundation.dart' show SynchronousFuture;
95+
import 'package:flutter_intl/lang/config.dart' as I18NConfig;
96+
class AppLocalizations {
97+
Locale _locale;
98+
static Map<String, dynamic> jsonLanguage; // 语言包
99+
static AppLocalizations _inst; // inst
100+
101+
AppLocalizations(this._locale);
102+
103+
// 初始化 localizations
104+
static Future<AppLocalizations> init(Locale locale) async {
105+
_inst = AppLocalizations(locale);
106+
await getLanguageJson();
107+
return _inst;
108+
}
109+
110+
// 获取语言包
111+
static Future getLanguageJson() async {
112+
Locale _tmpLocale = _inst._locale;
113+
print('获取语言包的语种; ${_tmpLocale.languageCode}');
114+
String jsonLang;
115+
try {
116+
jsonLang = await rootBundle.loadString('locale/${_tmpLocale.languageCode}.json');
117+
} catch (e) {
118+
print('出错了');
119+
_inst._locale = Locale(I18NConfig.ConfigLanguage.defaultLanguage['code']);
120+
jsonLang = await rootBundle.loadString('locale/${I18NConfig.ConfigLanguage.defaultLanguage['code']}.json');
121+
}
122+
jsonLanguage = json.decode(jsonLang);
123+
print("当前语言: ${_inst._locale}");
124+
print("数据: $jsonLanguage");
125+
}
126+
127+
// $t 封装,目的是为了可以使用$t来获取多语言数据
128+
static String $t(String key) {
129+
var _array = key.split('.');
130+
var _dict = jsonLanguage;
131+
var retValue = '';
132+
try {
133+
_array.forEach((item) {
134+
if(_dict[item].runtimeType == Null) {
135+
retValue = key;
136+
return;
137+
}
138+
if (_dict[item].runtimeType != String) {
139+
_dict = _dict[item];
140+
} else {
141+
retValue = _dict[item];
142+
}
143+
});
144+
retValue = retValue.isEmpty ? _dict : retValue;
145+
} catch (e) {
146+
print('i18n exception');
147+
print(e);
148+
retValue = key;
149+
}
150+
151+
return retValue ?? '';
152+
}
153+
154+
}
155+
156+
157+
// 实现LocalizationsDelegate协议,用于初始化Localizations类
158+
class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
159+
final Locale locale;
160+
AppLocalizationsDelegate([this.locale]);
161+
162+
@override
163+
bool isSupported(Locale locale) {
164+
return I18NConfig.ConfigLanguage.supportLanguage.keys
165+
.toList()
166+
.contains(locale.languageCode);
167+
}
168+
169+
// 在这里初始化Localizations类
170+
@override
171+
Future<AppLocalizations> load(Locale _locale) async {
172+
print('将要加载的语言: $_locale');
173+
return await AppLocalizations.init(_locale);
174+
// return SynchronousFuture<AppLocalizations>(
175+
// AppLocalizations(_locale)
176+
// );
177+
}
178+
179+
@override
180+
bool shouldReload(LocalizationsDelegate<AppLocalizations> old) {
181+
// flase时,不执行上述重写函数
182+
return false;
183+
}
184+
}
185+
```
186+
187+
详情请看代码注释~~~~~~~~~
188+
189+
概况一下就是
190+
191+
实现一个LocalizationsDelegate协议和实现一个Localizations类,然后引入到main.dart中的MaterialApp中
192+
193+
### 处理main.dart文件
194+
``` dart
195+
import 'package:flutter/material.dart';
196+
import 'package:flutter_localizations/flutter_localizations.dart';
197+
import 'package:flutter_intl/lang/index.dart'
198+
show AppLocalizations, AppLocalizationsDelegate;
199+
import 'package:flutter_intl/lang/config.dart' show ConfigLanguage;
200+
201+
202+
void main () => runApp(MainApp());
203+
GlobalKey<_ChangeLocalizationsState> changeLocalizationsStateKey = new GlobalKey<_ChangeLocalizationsState>();
204+
class MainApp extends StatefulWidget {
205+
@override
206+
_MainAppState createState() => _MainAppState();
207+
}
208+
209+
class _MainAppState extends State<MainApp> {
210+
// 定义全局 语言代理
211+
AppLocalizationsDelegate _delegate;
212+
213+
@override
214+
void initState() {
215+
// TODO: implement initState
216+
_delegate = AppLocalizationsDelegate();
217+
super.initState();
218+
}
219+
@override
220+
Widget build(BuildContext context) {
221+
return MaterialApp(
222+
// locale: Locale('zh', 'CH'),
223+
localeResolutionCallback: (deviceLocale, supportedLocal) {
224+
print('当前设备语种 deviceLocale: $deviceLocale, 支持语种 supportedLocale: $supportedLocal}');
225+
// 判断传入语言是否支持
226+
Locale _locale = supportedLocal.contains(deviceLocale) ? deviceLocale : Locale('zh', 'CN');
227+
return _locale;
228+
},
229+
onGenerateTitle: (context) {
230+
// 设置多语言代理
231+
// AppLocalizations.setProxy(setState, _delegate);
232+
return AppLocalizations.$t('title_page');
233+
},
234+
// localizationsDelegates 列表中的元素时生成本地化集合的工厂
235+
localizationsDelegates: [
236+
GlobalMaterialLocalizations.delegate, // 为Material Components库提供本地化的字符串和其他值
237+
GlobalWidgetsLocalizations.delegate, // 定义widget默认的文本方向,从左往右或从右往左
238+
_delegate
239+
],
240+
supportedLocales: ConfigLanguage.supportedLocales,
241+
initialRoute: '/',
242+
routes: {
243+
'/': (context) =>
244+
// Home()
245+
Builder(builder: (context) {
246+
return ChangeLocalizations(
247+
key: changeLocalizationsStateKey,
248+
child: Home()
249+
);
250+
})
251+
}
252+
);
253+
}
254+
}
255+
256+
class Home extends StatelessWidget {
257+
@override
258+
Widget build(BuildContext context) {
259+
Locale locale = Localizations.localeOf(context);
260+
return Scaffold(
261+
appBar: AppBar(title: Text('${AppLocalizations.$t('title_appbar')}'),),
262+
body: ListView(
263+
children: <Widget>[
264+
Container(
265+
margin: EdgeInsets.only(top: 60),
266+
alignment: Alignment.center,
267+
child: Text('${locale.languageCode} ${locale.toString()}'),
268+
),
269+
Container(
270+
alignment: Alignment.center,
271+
child: Text('${AppLocalizations.$t('content.currentLanguage')}'),
272+
),
273+
Wrap(
274+
spacing: 8.0,
275+
alignment: WrapAlignment.center,
276+
children: <Widget>[
277+
ActionChip(
278+
backgroundColor: Theme.of(context).primaryColor,
279+
onPressed: () {
280+
changeLocalizationsStateKey.currentState.changeLocale(Locale('en', 'US'));
281+
},
282+
label: Text('${AppLocalizations.$t('content.en')}'),
283+
),
284+
ActionChip(
285+
backgroundColor: Theme.of(context).primaryColor,
286+
onPressed: () {
287+
changeLocalizationsStateKey.currentState.changeLocale(Locale('zh', 'CH'));
288+
},
289+
label: Text('${AppLocalizations.$t('content.zh')}'),
290+
)
291+
],
292+
)
293+
],
294+
)
295+
);
296+
}
297+
}
298+
299+
class ChangeLocalizations extends StatefulWidget {
300+
final Widget child;
301+
ChangeLocalizations({Key key, this.child}):super(key: key);
302+
@override
303+
_ChangeLocalizationsState createState() => _ChangeLocalizationsState();
304+
}
305+
306+
class _ChangeLocalizationsState extends State<ChangeLocalizations> {
307+
Locale _locale;
308+
@override
309+
void initState() {
310+
super.initState();
311+
}
312+
@override
313+
void didChangeDependencies() async {
314+
super.didChangeDependencies();
315+
// 获取当前设备的语言
316+
_locale = Localizations.localeOf(context);
317+
print('设备语言: $_locale');
318+
}
319+
changeLocale(Locale locale) {
320+
setState(() {
321+
_locale = locale;
322+
});
323+
}
324+
@override
325+
Widget build(BuildContext context) {
326+
return Localizations.override(
327+
context: context,
328+
locale: _locale,
329+
child: widget.child,
330+
);
331+
}
332+
}
333+
```
334+
* 在MaterialApp中指定localizationsDelegate和supportedLocales
335+
* localeResolutionCallback:在应用获取用户设置的语言区域时回调,可以根据需要return对应的Locale
336+
* onGenerateTitle: 返回对应的多语言应用标题
337+
* localizationsDelegates:localizationsDelegates 列表中的元素时生成本地化集合的工厂
338+
* supportedLocales: app支持的语言种类
339+
* Home类就是显示的类
340+
* Localizations.localeOf(context).languageCode可以获取当前app的语言类型
341+
* AppLocalizations.$t('content.currentLanguage')像web一样玩耍多语言内容
342+
343+
到这里就已经可以愉快的玩耍多语言了,用户设置不同的语言就会加载不同的语言包
344+
345+
下面实现在app内的语言切换
346+
347+
* ChangeLocalizations类使用Localizations的override方法,代码如上
348+
* 使用GlobalKey调用ChangeLocalizations的内部方法,GlobalKey<_ChangeLocalizationsState> changeLocalizationsStateKey = new GlobalKey<_ChangeLocalizationsState>(); 我们也可以将GlobalKey放入到provide中,这样可以实现多个页面进行changeLocalizationsStateKey的访问
349+
* 修改语言调用changeLocale方法,changeLocalizationsStateKey.currentState.changeLocale(Locale('en', 'US'));
350+
351+
352+
## 最后
353+
欢迎更多学习flutter的小伙伴加入QQ群 Flutter UI: 798874340
354+
355+
敬请关注我们正在开发的: [efoxTeam/futter-ui](https://github.com/efoxTeam/flutter-ui)
356+
357+
[作者](https://github.com/DIVINER-onlys)
358+
359+
360+
361+
362+
363+
364+
365+
366+
2367

3-
A new Flutter project.
4368

5-
## Getting Started
6369

7-
This project is a starting point for a Flutter application.
8370

9-
A few resources to get you started if this is your first Flutter project:
10371

11-
- [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab)
12-
- [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook)
13372

14-
For help getting started with Flutter, view our
15-
[online documentation](https://flutter.io/docs), which offers tutorials,
16-
samples, guidance on mobile development, and a full API reference.

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /