easy_localization
轻松快速地国际化您的 Flutter 应用,此包使用 JSON 文件简化了国际化过程。
为什么选择 easy_localization
- 简化 Flutter 中的国际化过程。
- 使用 JSON 文件。
- 从远程或后端加载翻译。
- 保存应用程序状态。
- 支持
复数 - 支持
性别 - 支持 Flutter 扩展。
更新日志
[1.4.1]
-
优化且干净的代码
-
修复了许多问题
-
为字符串添加了扩展
// after 1.4.1 Text('title'.tr()), Text('switch'.tr( gender: _gender ? "female" : "male")), Text('counter'.plural(counter)),
[1.4.0]
-
重构代码,将调用
AppLocalizations.of(context).tr()改为AppLocalizations.of(context).plural()tr()和plural()// after 1.4.0 Text( tr('switch', gender: _gender ? "female" : "male"), ),// before 1.4.0 Text( AppLocalizations.of(context).tr('switch', gender: _gender ? "female" : "male"), ), -
为 Text widget 添加了 Flutter 扩展
// after 1.4.0 Text('switch').tr( gender: _gender ? "female" : "male"), Text('counter').plural(counter),
[1.3.5]
-
合并了
gender()和tr()。{ "switch":{ "male": "Hi man ;)", "female": "Hello girl :)" } }Text( AppLocalizations.of(context).tr('switch', gender: _gender ? "female" : "male"), ), -
使用参数
args来处理性别。{ "switch":{ "male": "Hi man ;) {}", "female": "Hello girl :) {}" } }Text( AppLocalizations.of(context).tr('switch', args:["Naama"] gender: _gender ? "female" : "male"), ),
[1.3.4]
-
添加了性别 [女性,男性]
gender()。{ "switch":{ "male": "Hi man ;)", "female": "Hello girl :)" } }Text( AppLocalizations.of(context).gender('switch', _gender ? "female" : "male"), ),
[1.3.3+1]
-
更新了
plural(),感谢 shushper。{ "text": { "day": { "zero":"{} дней", "one": "{} день", "two": "{} дня", "few": "{} дня", "many": "{} дней", "other": "{} дней" } } }
[1.3.3]
- 移除了
data.savedLocale。 - 优化且干净的代码
- 修复了许多问题
[1.3.2]
-
plural()添加了嵌套键翻译的属性解析器{ "text": { "day": { "zero": "day", "one": "day", "other": "days" } } }new Text( AppLocalizations.of(context).plural("text.day", 2), ), -
修复了许多问题
[1.3.1]
- 添加 useOnlyLangCode 标志
[1.3.0]
- 从远程或后端加载翻译
- 修复了许多问题
[1.2.1]
- 支持 shared_preferences
- 保存选定的本地化
[1.2.0]
- 添加了嵌套键翻译的属性解析器
- 如果元素或路径不存在,则返回翻译键
{
"title": "Hello",
"msg": "Hello {} in the {} world ",
"clickMe": "Click me",
"profile": {
"reset_password": {
"title": "Reset Password",
"username": "Username",
"password": "password"
}
},
"clicked": {
"zero": "You clicked {} times!",
"one": "You clicked {} time!",
"two":"You clicked {} times!",
"few":"You clicked {} times!",
"many":"You clicked {} times!",
"other": "You clicked {} times!"
}
}
new Text(
AppLocalizations.of(context).tr('profile.reset_password.title'),
),
[1.0.4]
- 添加了对国家代码的支持
[1.0.3]
- 更新了
tr()函数,添加了多参数
[1.0.2]
- 添加了字符串复数化。
- 向
tr()函数添加了参数。
入门
配置
将此添加到您的 package 的 pubspec.yaml 文件中
dependencies:
# stable version install from https://pub.dev/packages
easy_localization: <last_version>
# Dev version install from git REPO
easy_localization:
git: https://github.com/aissat/easy_localization.git
从本地资源加载翻译
你必须在项目的根目录创建一个文件夹:path。一些例子
/assets/"langs", "i18n", "locale" 或任何名称...
/resources/"langs", "i18n", "locale" 或任何名称...
在此文件夹内,必须放置包含翻译键的 *json* 文件。
path/${languageCode}-${countryCode}.json
示例
- en.json 到 en-US.json
- ar.json 到 ar-DZ.json
- zh.json 到 zh-CN.json
- zh.json 到 zh-TW.json
必须在 pubspec.yaml 文件中将子目录声明为资源。
flutter:
assets:
- {`path`/{languageCode}-{countryCode}.json}
下一步
import 'package:example/my_flutter_app_icons.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:easy_localization/easy_localization.dart';
void main() => runApp(EasyLocalization(child: MyApp()));
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
var data = EasyLocalizationProvider.of(context).data;
return EasyLocalizationProvider(
data: data,
child: MaterialApp(
title: 'Flutter Demo',
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
//app-specific localization
EasyLocalizationDelegate(
locale: data.locale,
path: 'resources/langs',
//useOnlyLangCode: true,
// loadPath: 'https://raw.githubusercontent.com/aissat/easy_localization/master/example/resources/langs'
),
],
supportedLocales: [Locale('en', 'US'), Locale('ar', 'DZ')],
locale: data.locale,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Easy localization'),
),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int counter = 0;
bool _gender = true;
incrementCounter() {
setState(() {
counter++;
});
}
switchGender(bool val) {
setState(() {
_gender = val;
});
}
@override
Widget build(BuildContext context) {
var data = EasyLocalizationProvider.of(context).data;
return EasyLocalizationProvider(
data: data,
child: Scaffold(
appBar: AppBar(
title: Text(tr("title")),
actions: <Widget>[
FlatButton(
child: Text("English"),
color: Localizations.localeOf(context).languageCode == "en"
? Colors.lightBlueAccent
: Colors.blue,
onPressed: () {
this.setState(() {
data.changeLocale(Locale("en", "US"));
print(Localizations.localeOf(context).languageCode);
});
},
),
FlatButton(
child: Text("عربي"),
color: Localizations.localeOf(context).languageCode == "ar"
? Colors.lightBlueAccent
: Colors.blue,
onPressed: () {
this.setState(() {
data.changeLocale(Locale("ar", "DZ"));
print(Localizations.localeOf(context).languageCode);
});
},
)
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Spacer(
flex: 1,
),
Text(
'switch.with_arg',
style: TextStyle(
color: Colors.grey.shade600,
fontSize: 19,
fontWeight: FontWeight.bold),
).tr(args: ["aissat"], gender: _gender ? "female" : "male"),
Text(
tr('switch', gender: _gender ? "female" : "male"),
style: TextStyle(
color: Colors.grey.shade600,
fontSize: 15,
fontWeight: FontWeight.bold),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(MyFlutterApp.male_1),
Switch(value: _gender, onChanged: switchGender),
Icon(MyFlutterApp.female_1),
],
),
Spacer(
flex: 1,
),
Text(tr('msg', args: ['aissat', 'Flutter'])),
// Text(plural('clicked', counter)),
Text('clicked').plural(counter),
FlatButton(
onPressed: () {
incrementCounter();
},
child: Text('clickMe').tr(),
),
SizedBox(height: 15,),
Text(
plural('amount', counter,
format: NumberFormat.currency(
locale: Localizations.localeOf(context).toString(),
symbol: "€")),
style: TextStyle(
color: Colors.grey.shade900,
fontSize: 18,
fontWeight: FontWeight.bold)
),
SizedBox(height: 20,),
Text('profile.reset_password.title').tr(),
Spacer(
flex: 2,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: incrementCounter,
child: Text('+1'),
),
),
);
}
}
从后端加载翻译
你需要有一个后端端点 (loadPath) 来加载资源,并且你的端点必须包含翻译键。
示例
String loadPath = 'https://raw.githubusercontent.com/aissat/easy_localization/master/example/resources/langs'
'${
loadPath}/${languageCode}-${countryCode}.json'
- 'https://raw.githubusercontent.com/aissat/easy_localization/master/example/resources/langs/en-US.json'
- 'https://raw.githubusercontent.com/aissat/easy_localization/master/example/resources/langs/ar-DZ.json'
下一步
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:easy_localization/easy_localization.dart';
void main() => runApp(EasyLocalization(child: MyApp()));
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
var data = EasyLocalizationProvider.of(context).data;
return EasyLocalizationProvider(
data: data,
child: MaterialApp(
title: 'Flutter Demo',
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
//app-specific localization
EasyLocalizationDelegate(
locale: data.locale,
loadPath: 'https://raw.githubusercontent.com/aissat/easy_localization/master/example/resources/langs'),
],
supportedLocales: [Locale('en', 'US'), Locale('ar', 'DZ')],
locale: data.locale,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Easy localization'),
),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int counter = 0;
incrementCounter() {
setState(() {
counter++;
});
}
@override
Widget build(BuildContext context) {
var data = EasyLocalizationProvider.of(context).data;
return EasyLocalizationProvider(
data: data,
child: Scaffold(
appBar: AppBar(
title: Text(tr('title')),
actions: <Widget>[
FlatButton(
child: Text("English"),
color: Localizations.localeOf(context).languageCode == "en"
? Colors.lightBlueAccent
: Colors.blue,
onPressed: () {
this.setState(() {
data.changeLocale(Locale("en","US"));
print(Localizations.localeOf(context).languageCode);
});
},
),
FlatButton(
child: Text("عربي"),
color: Localizations.localeOf(context).languageCode == "ar"
? Colors.lightBlueAccent
: Colors.blue,
onPressed: () {
this.setState(() {
data.changeLocale(Locale("ar","DZ"));
print(Localizations.localeOf(context).languageCode);
});
},
)
],
),
body: Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(AppLocalizations.of(context)
.tr('msg', args: ['aissat', 'Flutter'])),
new Text(plural('clicked', counter)),
new FlatButton(
onPressed: () async {
incrementCounter();
},
child: new Text(tr('clickMe')),
),
new Text(
tr('profile.reset_password.title'),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: incrementCounter,
child: Text('+1'),
),
),
);
}
}
屏幕截图
| 阿拉伯语 RTL | 英语 LTR |
|---|---|
![]() |
![]() |

