Flutter本地化管理插件localization_plus的使用

Flutter本地化管理插件localization_plus的使用

简介

localization_plus 是一个用于 Flutter 应用程序的国际化插件。它支持多种语言、复杂规则的复数处理、设备语言检测等功能。

安装

首先,在 pubspec.yaml 文件中添加依赖:

dependencies:
  localization_plus: <last_version>

创建包含翻译文件的目录结构:

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>

使用示例

以下是一个完整的示例,展示如何使用 localization_plus 插件进行国际化。

初始化控制器

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

GetIt getIt = GetIt.instance;

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

  LocalizationPlusController controller = await LocalizationPlusController.init(
    path: 'i18n',
    supportedLocales: [
      'en_US'.toLocale(),
      'ar_SA'.toLocale(),
      'tr_TR'.toLocale(),
      'ru_RU'.toLocale(),
    ],
    fallbackLocale: 'en_US'.toLocale(),
    useFallbackTranslations: true,
  );

  getIt.registerLazySingleton<LocalizationPlusController>(() => controller);

  runApp(
    LocalizationPlus(
      controller: getIt<LocalizationPlusController>(),
      child: const MyApp(),
    ),
  );
}

主应用页面

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.currentLocale,

      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

主页面状态

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int counter = 0;
  Map<String, String> languageTitles = {
    'tr_TR': 'Türkçe (Türkiye)',
    'en_US': 'English (United States)',
    'ar_SA': 'العربية (المملكة العربية السعودية)',
    'ru_RU': 'русский (Россия)',
  };

  @override
  void initState() {
    super.initState();

    getIt<LocalizationPlusController>().addListener(() {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(context.currentLocale.toString()),
        ),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('hello'.trans()),
        actions: [
          TextButton(
            child: Text(languageTitles[context.currentLocale.toString()]!),
            onPressed: () => showLanguageDialog(context),
          )
        ],
      ),
      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.all(10.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Card(
                child: Container(
                  width: double.infinity,
                  padding: const EdgeInsets.all(8.0),
                  child: Column(
                    children: [
                      Text('notations'.trans(arguments: {'arg': 'test'})),
                      const SizedBox(height: 10),
                      Text(trans('welcome', arguments: {'username': 'fatih'})),
                      const SizedBox(height: 10),
                      Text('goodbye'.trans(arguments: {'username': 'fatih'})),
                      const SizedBox(height: 10),
                      Text('locale'.trans(arguments: {'language': context.currentLocale.toString()})),
                      const SizedBox(height: 10),
                      Text('I love programming.'.trans()),
                      const SizedBox(height: 10),
                      Text('${'user.profile.firstname'.trans()} ${'user.profile.lastname'.trans()}'),
                      const SizedBox(height: 10),
                      const Text('fallback').trans(),
                      const SizedBox(height: 10),
                      Text(ResponseStatusType.serverError.description),
                    ],
                  ),
                ),
              ),
              const SizedBox(height: 10),
              Card(
                child: Container(
                  width: double.infinity,
                  padding: const EdgeInsets.all(8.0),
                  child: Column(
                    children: [
                      Text('price'.transChoice(counter)),
                      const SizedBox(height: 10),
                      Text('clicked'.plural(counter)),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceAround,
                        children: [
                          FilledButton(
                            onPressed: () => counter > 0 ? setState(() => counter--) : null,
                            child: const Icon(Icons.exposure_minus_1),
                          ),
                          Text(counter.toString()),
                          FilledButton(
                            onPressed: () => counter < 15 ? setState(() => counter++) : null,
                            child: const Icon(Icons.exposure_plus_1),
                          ),
                        ],
                      )
                    ],
                  ),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }

  void showLanguageDialog(BuildContext context) {
    showDialog<void>(
      context: context,
      builder: (BuildContext context) => AlertDialog(
        contentPadding: EdgeInsets.zero,
        content: SingleChildScrollView(
          child: Column(
            children: context.supportedLocales
                .map(
                  (locale) => ListTile(
                    title: Text(languageTitles[locale.toString()].toString()),
                    selected: locale == context.currentLocale,
                    onTap: () {
                      Navigator.pop(context);
                      context.setLocale(locale);
                    },
                  ),
                )
                .toList(),
          ),
        ),
      ),
    );
  }
}

功能说明

改变语言

你可以通过 BuildContext 或者 controller 来改变语言:

// 通过上下文
context.setLocale('en_US'.toLocale());

// 通过控制器
controller.setLocale('en_US'.toLocale());

重置语言

可以通过 resetLocale() 方法来重置语言到初始值:

// 通过上下文
context.resetLocale();

// 通过控制器
controller.resetLocale();

删除保存的语言

可以通过 deleteSavedLocale() 方法来删除保存的语言:

// 通过上下文
context.deleteSavedLocale();

// 通过控制器
controller.deleteSavedLocale();

获取当前语言

可以通过 currentLocale 方法来获取当前语言:

// 通过上下文
context.currentLocale;

// 通过控制器
controller.currentLocale;

获取设备语言

可以通过 deviceLocale 方法来获取设备语言:

// 通过上下文
context.deviceLocale

// 通过控制器
controller.deviceLocale

获取备用语言

可以通过 fallbackLocale 方法来获取备用语言:

// 通过上下文
context.fallbackLocale

// 通过控制器
controller.fallbackLocale

翻译字符串

使用 trans() 方法来翻译字符串:

// 字符串
'notations'.trans(arguments: {'arg': 'test'})

// Text 组件
const Text('notations').trans(arguments: {'arg': 'test'})

// 帮助函数
trans('notations', arguments: {'arg': 'test'})

复数处理

使用 plural() 方法来处理复数形式:

// 字符串
'clicked'.plural(0) // Today
'clicked'.plural(1) // Tomorrow
'clicked'.plural(2) // 2 days later
'clicked'.plural(3) // A few days later (根据语言)
'clicked'.plural(11) // Weeks later (根据语言)
'clicked'.plural(1250) // After a long time (根据语言)

选择性翻译

使用 transChoice() 方法来处理选择性翻译:

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

监听语言变化

可以通过 addListener() 方法来监听语言变化:

controller.addListener(() {
  // 语言已更改
  // 重新加载与语言相关的远程数据等
});

链接翻译

如果某个翻译总是与另一个翻译相同,可以使用链接翻译:

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

检查翻译是否存在

可以使用 transExists() 方法来检查翻译是否存在:

'notations'.transExists() // true

transExists('not_exists') // false

扩展功能

字符串扩展

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

// 自定义分隔符
'en|US'.toLocale(separator: '|') // Locale('en', 'US')

枚举扩展

{
  "enums": {
    "response_status_type": {
      "successful": "Successful",
      "server_error": "Server Error"
    }
  },
}

// 枚举值
ResponseStatusType.successful.description; // Successful
ResponseStatusType.serverError.description; // Server Error

BuildContext 扩展

context.currentLocale // 获取当前语言

context.deviceLocale // 获取设备语言

context.fallbackLocale // 获取备用语言

context.supportedLocales // 获取支持的语言

context.localizationDelegates // 获取本地化代理

更多关于Flutter本地化管理插件localization_plus的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter本地化管理插件localization_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


localization_plus 是一个用于 Flutter 应用的本地化管理的插件,它可以帮助开发者轻松地实现多语言支持。以下是关于如何使用 localization_plus 插件的详细步骤。

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 localization_plus 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  localization_plus: ^1.0.0  # 请检查最新版本

然后运行 flutter pub get 来获取依赖包。

2. 创建本地化文件

在项目中创建一个文件夹来存放本地化文件,例如 lib/l10n。然后为每种支持的语言创建一个 JSON 文件。例如:

  • lib/l10n/en.json (英语)
  • lib/l10n/es.json (西班牙语)

这些 JSON 文件的内容将包含键值对,表示不同语言的翻译。例如:

lib/l10n/en.json:

{
  "hello": "Hello",
  "welcome": "Welcome to the app"
}

lib/l10n/es.json:

{
  "hello": "Hola",
  "welcome": "Bienvenido a la aplicación"
}

3. 初始化 LocalizationPlus

在你的 main.dart 文件中,初始化 LocalizationPlus,并设置默认语言和可用的语言列表:

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  await LocalizationPlus.init(
    defaultLang: 'en',  // 默认语言
    supportedLangs: ['en', 'es'],  // 支持的语言列表
    assetsDir: 'lib/l10n',  // 本地化文件所在的目录
  );

  runApp(MyApp());
}

4. 使用 LocalizationPlus

在你的应用中使用 LocalizationPlus 来获取翻译文本。你可以通过 LocalizationPlus.instance.translate 方法来获取特定键的翻译。

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Localization Example'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(LocalizationPlus.instance.translate('hello')),
              Text(LocalizationPlus.instance.translate('welcome')),
            ],
          ),
        ),
      ),
    );
  }
}

5. 切换语言

你可以在运行时切换应用的语言。例如,通过按钮切换语言:

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

class LanguageSwitcher extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: () async {
            await LocalizationPlus.instance.setLanguage('en');
          },
          child: Text('English'),
        ),
        ElevatedButton(
          onPressed: () async {
            await LocalizationPlus.instance.setLanguage('es');
          },
          child: Text('Spanish'),
        ),
      ],
    );
  }
}

6. 监听语言变化

如果你希望在语言变化时更新 UI,可以使用 LocalizationPlus.instance.onLocaleChanged 监听器:

LocalizationPlus.instance.onLocaleChanged.listen((locale) {
  // 更新 UI 或执行其他操作
});
回到顶部