为您的Flutter应用提供简单、高级、快速的国际化支持

关于此库

  • ✅ 完全测试的代码(100%代码覆盖率)
  • ? 支持多种语言的简单翻译
  • ?️ 空安全
  • ? 从JSON文件加载翻译
  • ? BuildContext, String 和 Text 的扩展方法
  • ? 支持复数、嵌套、选择、RTL区域设置等
  • ↩️ 回退区域设置键重定向(可选)
  • ? 持久的区域设置存储(可选)
  • ❗ 丢失翻译的错误小部件
  • ? 通过控制器监听本地化更改
  • ? 通过控制器独立于上下文的区域设置更改

安装

添加到您的 pubspec.yaml

dependencies:
  localization_plus: <last_version>

创建文件夹并像这样添加翻译文件

i18n
    ├── {languageCode}.{ext}                  // useOnlyLangCode: true
    └── {languageCode}-{countryCode}.{ext}    // useOnlyLangCode: false (default)

示例

i18n
    ├── en.json
    └── en-US.json 

pubspec.yaml 中声明您的资源本地化目录

flutter:
  assets:
    - i18n/

? 关于 **iOS**

要在 **iOS** 上实现翻译,您需要像 这里所述那样,将支持的区域设置添加到 ios/Runner/Info.plist

示例

<key>CFBundleLocalizations</key>
<array>
	<string>en</string>
	<string>nb</string>
</array>

文档

? LocalizationPlusController 属性

属性 必需 默认值 描述
supportedLocales 支持的区域设置列表。
path 包含本地化文件的文件夹路径。
loader RootBundleAssetLoader() 本地化文件的类加载器。您可以创建自己的类。
saveLocale 更改语言后是否保存在设备上
useOnlyLangCode 用于仅使用语言代码读取本地化文件的触发器。示例:en.json //useOnlyLangCode: trueen-US.json //useOnlyLangCode: false (默认)
useFallbackTranslations 如果在区域设置文件中找不到本地化键,请尝试使用回退区域设置文件。如果未设置回退区域设置,则将第一个支持的语言设置为回退
fallbackLocale 设置在区域设置文件中找不到本地化键时要用作替代的区域设置
startLocale 如果没有保存的语言,则设置系统将启动的语言

? LocalizationPlus 小部件属性

属性 必需 默认值 描述
key 小部件键。
child 放置您的主页面小部件的地方。
控制器 LocalizationPlusController 实例。

替换翻译字符串中的参数

如果需要,可以在翻译字符串中定义占位符。所有占位符都必须放在花括号中。例如,您可以定义一个带有占位符名称的欢迎消息

{
    "welcome": "Welcome, {name}"
}

如果您的占位符全部大写,或者只有首字母大写,翻译后的值也将相应大写

"welcome": "Welcome, {NAME}" // Welcome, USER
"welcome": "Welcome, {Name}" // Welcome, User

用法/示例

import 'package:flutter/material.dart';
import 'package:localization_plus/localization_plus.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // If you wish, you can define it so that it can be accessed 
  // from anywhere in the system with a package such as the getIt library
  LocalizationPlusController controller = await LocalizationPlusController.init(
    path: 'i18n',
  );

  runApp(
    LocalizationPlus(
      controller: controller,
      supportedLocales: [
        'en_US'.toLocale(),
        'ar_DZ'.toLocale(),
        'tr_TR'.toLocale(),
        'ru_RU'.toLocale(),
      ],
      child: const MyApp()
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // Localizations
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,

      home: MyHomePage()
    );
  }
}

完整示例

? 更改区域设置

您可以通过 BuildContext 扩展方法或控制器来更改区域设置。

// via context
context.setLocale('en_US'.toLocale());

// via controller
controller.setLocale('en_US'.toLocale());

? 重置区域设置 resetLocale()

将区域设置重置为初始区域设置。如果定义了 startLocale,则将其设置为 startLocale;如果未定义,则设置为 deviceLocale

// via context
context.resetLocale()

// via controller
controller.resetLocale();

? 删除已保存的区域设置 deleteSavedLocale()

清除本地存储中已保存的区域设置

// via context
context.deleteSavedLocale()

// via controller
controller.deleteSavedLocale();

? 获取区域设置 currentLocale

返回应用程序中的当前区域设置

// via context
context.currentLocale;

// via controller
controller.currentLocale;

? 获取设备区域设置 deviceLocale

返回设备区域设置

// via context
context.deviceLocale

// via controller
controller.deviceLocale

? 获取回退区域设置 fallbackLocale

返回回退区域设置。如果 useFallbackTranslationsfalse,则返回 null。

// via context
context.fallbackLocale

// via controller
controller.fallbackLocale

? 翻译 trans()

翻译语言键的主要函数

您可以使用 [String][Text] 小部件的扩展方法,您也可以使用 trans() 作为辅助函数。

示例

{
  "notations": "Default: {arg}, Capital: {Arg}, Uppercase: {ARG}",
}

'notations'.trans(arguments: {'arg': 'test'}) // String
// Result: Default: test, Capital: Test, Uppercase: TEST


const Text('notations').trans(arguments: {'arg': 'test'}) // Text
// Result: Text instance


trans('notations', arguments: {'arg': 'test'}) // Helper function
// Result: Default: test, Capital: Test, Uppercase: TEST

参数

名称 类型 描述
arguments Map<String, String> 本地化字符串的映射。根据其名称替换名称键 {key_name}

? 复数 plural()

复数是一个复杂的问题,因为不同语言的复数规则多种多样;然而,Localization Plus 可以帮助您根据您定义的复数规则以不同的方式翻译字符串。

您可以使用 [String][Text] 小部件的扩展方法,您也可以使用 plural() 作为辅助函数。

? 必需的“other”键!

示例

{
  "clicked": {
    "zero": "Today",
    "one": "Tomorrow",
    "two": "2 days later",
    "few": "A few days later",
    "many": "Weeks later",
    "other": "After a long time"
  }
}

// String
'clicked'.plural(0) // Today
'clicked'.plural(1) // Tomorrow
'clicked'.plural(2) // 2 days late
'clicked'.plural(3) // A few days later (Depends on the language)
'clicked'.plural(11) // Weeks later (Depends on the language)
'clicked'.plural(1250) // After a long time (Depends on the language)

// Text
Text('clicked').plural(0) // Today
Text('clicked').plural(1) // Tomorrow
Text('clicked').plural(2) // 2 days late
Text('clicked').plural(3) // A few days later (Depends on the language)
Text('clicked').plural(11) // Weeks later (Depends on the language)
Text('clicked').plural(1250) // After a long time (Depends on the language)

plural('clicked', 0) // Today
plural('clicked', 1) // Tomorrow
plural('clicked', 2) // 2 days late
plural('clicked', 3) // A few days later (Depends on the language)
plural('clicked', 11) // Weeks later (Depends on the language)
plural('clicked', 1250) // After a long time (Depends on the language)

参数

名称 类型 描述
arguments Map<String, String> 本地化字符串的映射。根据其名称替换名称键 {key_name}

? 翻译选择 transChoice()

您可以创建更复杂的复数规则,为多个值的范围指定翻译字符串。

您可以使用 [String][Text] 小部件的扩展方法,您也可以使用 transChoice() 作为辅助函数。

示例

{
  "price": {
    "0": "Free",
    "1:5": "Cheap",
    "6:10": "Normal",
    "*": "Expensive"
  }
}

// String
'price'.transChoice(0) // Free
'price'.transChoice(1) // Cheap
'price'.transChoice(3) // Cheap
'price'.transChoice(6) // Normal
'price'.transChoice(10) // Normal
'price'.transChoice(1250) // Expensive

// Text
('price').transChoice(0) // Free
('price').transChoice(1) // Cheap
('price').transChoice(3) // Cheap
('price').transChoice(6) // Normal
('price').transChoice(10) // Normal
('price').transChoice(1250) // Expensive

transChoice('price', 0) // Free
transChoice('price', 1) // Cheap
transChoice('price', 3) // Cheap
transChoice('price', 6) // Normal
transChoice('price', 10) // Normal
transChoice('price', 1250) // Expensive

参数

名称 类型 描述
arguments Map<String, String> 本地化字符串的映射。根据其名称替换名称键 {key_name}

? 监听区域设置更改

您可以通过控制器来监听区域设置更改。

controller.addListener(() {
  // Locale changed
  // Refetch language dependent remote data etc.
});

? 链接翻译

如果有一个翻译键将始终具有与另一个键相同的具体文本,您可以直接链接到它。要链接到另一个翻译键,您所要做的就是在其内容前加上 @: 符号,后跟您想要链接的完整翻译键名称,包括命名空间。

{
  "hello": "Hello",
  "world": "World",
  "hello_world": "@:hello @:world"
}

您还可以在链接的消息中包含嵌套的匿名和命名参数。

格式化链接翻译

如果语言区分字符大小写,您可能需要控制链接区域设置消息的大小写。可以使用修饰符 @.modifier:key 格式化链接消息。

目前可用的修饰符如下。

  • upper: 将链接消息中的所有字符转换为大写。
  • lower: 将链接消息中的所有字符转换为小写。
  • capitalize: 将链接消息的首字母大写。

示例

{
  ...
  "hello": "Hello",
  "world": "World",
  "hello_world": "@.upper:hello @.lower:world" // HELLO world
  ...
}

? 检查翻译是否存在 transExists()

您可以检查一个键是否具有翻译

'notations'.transExists() // String
// Result: true

transExists('not_exists') // Helper function
// Result: false

? 扩展

String 扩展

'en_US'.toLocale(); // Locale('en', 'US')

//with custom separator
'en|US'.toLocale(separator: '|') // Locale('en', 'US')

Build Context 扩展

context.currentLocale // get current locale

context.deviceLocale // get device locale

context.fallbackLocale // get fallback locale

context.supportedLocales // get supported locales

context.localizationDelegates // get localization delegates

屏幕截图

阿拉伯语 RTL 英语 LTR 土耳其语 LTR 俄语 LTR
Arabic RTL English LTR Turkish LTR Russian LTR

GitHub

查看 Github