Flutter本地化支持插件toml_localizations的使用

发布于 1周前 作者 bupafengyu 来自 Flutter

Flutter本地化支持插件toml_localizations的使用

toml_localizations 是一个为 Flutter 设计的轻量级 TOML 本地化包。

安装

首先,在你的 pubspec.yaml 文件中添加 toml_localizationsflutter_localizations 作为依赖项:

dependencies:
  flutter_localizations:
    sdk: flutter
  toml_localizations: <last-version>

添加资源文件

在项目中为每种语言添加一个 TOML 文件,并在 pubspec.yaml 中定义这些文件的路径。例如,假设你有以下目录结构:

assets/
  toml_translations/
    en-US.toml
    nb.toml

pubspec.yaml 文件中添加如下配置:

flutter:
  assets:
    - assets/toml_translations/

确保 TOML 文件名与 supportedLocales 中的语言和地区代码完全匹配。例如,Locale('en', 'US') 对应的文件名为 assets/toml_translations/en-US.toml

添加本地化委托和受支持的语言地区

MaterialApp 中添加 TomlLocalizationsDelegate 并设置 supportedLocales 为受支持的语言和地区代码:

MaterialApp(
  localizationsDelegates: [
    // 来自 flutter_localization 的委托
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
    // toml localizations 委托
    TomlLocalizationsDelegate(path: 'assets/toml_translations')
  ],
  supportedLocales: [
    Locale('en', 'GB'),
    Locale('en', 'US'),
    Locale('en'),
    Locale('nb'),
  ],
  theme: ThemeData(
    primarySwatch: Colors.blue,
    visualDensity: VisualDensity.adaptivePlatformDensity,
  ),
  home: const MyHomePage(),
);

iOS 注意事项

如果你的应用运行在 iOS 上,需要在 ios/Runner/Info.plist 文件中添加受支持的语言和地区代码。例如:

<key>CFBundleLocalizations</key>
<array>
  <string>en</string>
  <string>en-GB</string>
  <string>en-US</string>
  <string>nb</string>
</array>

格式

一个示例 TOML 文件可能如下所示:

str = "The quick brown fox jumps over the lazy dog."

literal_str = 'C:\\Users\\nodejs\\templates'

multiline_str = """\
The quick brown \
fox jumps over \
the lazy dog.\
"""

literal_multiline_str = '''
The first newline is
trimmed in raw strings.
   All other whitespace
   is preserved.
'''

list = [ 'one', 'two', 'three' ]

提示: TOML 支持多种字符串表示方式。有关更多信息,请参阅 TOML 文档。

API

你可以通过以下方式翻译字符串或其他类型:

TomlLocalizations.of(context)!.value(this);

为了简化代码,你可以添加一个扩展方法到 String 类中:

extension LocalizedString on String {
  String tr(BuildContext context) => TomlLocalizations.of(context)!.value(this);
}

这样你就可以像下面这样翻译字符串了:

'Hi'.tr(context)

示例

查看 示例代码

import 'package:flutter/material.dart';
import 'package:toml_localizations/toml_localizations.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

extension LocalizedString on String {
  String tr(BuildContext context) => TomlLocalizations.of(context)!.value(this);
}

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: [
        ...GlobalMaterialLocalizations.delegates,
        TomlLocalizationsDelegate(path: 'assets'),
      ],
      supportedLocales: const [
        Locale('nb'),
        Locale('en', 'GB'),
        Locale('en', 'US'),
        Locale('en'),
      ],
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    final List<String> list = TomlLocalizations.of(context)!.value('list').cast<String>();
    return Scaffold(
      appBar: AppBar(
        title: const Text('toml_localizations'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Text('str'.tr(context)),
          const SizedBox(height: 12),
          Text('literal_str'.tr(context)),
          const SizedBox(height: 12),
          Text('multiline_str'.tr(context)),
          const SizedBox(height: 12),
          Text('literal_multiline_str'.tr(context)),
          for (final str in list) Text(str)
        ],
      ),
    );
  }
}

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

1 回复

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


在Flutter项目中实现本地化支持通常涉及多个步骤,包括设置本地化文件、配置MaterialApp以及使用适当的本地化插件。toml_localizations插件是一个较为特定的插件,用于从TOML文件中加载本地化资源。尽管这个插件在Flutter社区中可能不是最常用的本地化解决方案,但我们可以展示如何使用它来实现本地化支持。

以下是一个基于toml_localizations插件的Flutter本地化支持示例:

1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  toml_localizations: ^x.y.z  # 请替换为最新版本号

然后运行flutter pub get来安装依赖。

2. 准备TOML本地化文件

创建TOML文件来存储本地化内容。例如,创建l10n/messages_en.tomll10n/messages_fr.toml文件:

l10n/messages_en.toml

[greetings]
hello = "Hello"
goodbye = "Goodbye"

l10n/messages_fr.toml

[greetings]
hello = "Bonjour"
goodbye = "Au revoir"

3. 加载TOML文件并实现本地化委托

创建一个新的Dart文件,比如toml_localization_delegate.dart,来加载TOML文件并实现LocalizationsDelegate

import 'package:flutter/material.dart';
import 'package:toml_localizations/toml_localizations.dart';
import 'dart:convert';
import 'dart:io';

class TomlLocalizationDelegate extends LocalizationsDelegate<TomlLocalizations> {
  const TomlLocalizationDelegate();

  @override
  bool isSupported(Locale locale) {
    // 根据你的TOML文件支持的语言返回true或false
    return ['en', 'fr'].contains(locale.languageCode);
  }

  @override
  Future<TomlLocalizations> load(Locale locale) async {
    // 根据locale加载对应的TOML文件
    String languageCode = locale.languageCode;
    String filePath = 'assets/l10n/messages_$languageCode.toml';
    String tomlContent = await rootBundle.loadString(filePath);
    Map<String, dynamic> tomlData = TomlDecoder().decode(tomlContent);
    return TomlLocalizations(tomlData);
  }

  @override
  bool shouldReload(TomlLocalizationDelegate oldDelegate) {
    // 通常返回false,除非本地化数据可能发生变化
    return false;
  }
}

class TomlLocalizations {
  final Map<String, dynamic> data;

  TomlLocalizations(this.data);

  String text(String key) {
    // 简单的键路径解析,可以根据需要复杂化
    List<String> parts = key.split('.');
    Map<String, dynamic> currentMap = data;
    for (String part in parts) {
      if (currentMap.containsKey(part)) {
        currentMap = currentMap[part] as Map<String, dynamic>;
      } else {
        return key; // 如果没有找到,返回key本身作为回退
      }
    }
    return currentMap.toString(); // 返回最终的文本值
  }
}

注意:上面的TomlLocalizations类是一个非常简单的实现,仅用于演示目的。在实际应用中,你可能需要更复杂的逻辑来处理嵌套的TOML结构和不同类型的值。

4. 在MaterialApp中使用本地化委托

最后,在你的MaterialApp中使用自定义的本地化委托:

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      localizationsDelegates: [
        TomlLocalizationDelegate(),
        // 其他本地化委托,比如GlobalMaterialLocalizations.delegate等
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: [
        Locale('en', ''),
        Locale('fr', ''),
      ],
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    TomlLocalizations localizations = Localizations.of<TomlLocalizations>(context, TomlLocalizationDelegate());
    return Scaffold(
      appBar: AppBar(
        title: Text(localizations.text('greetings.hello')),
      ),
      body: Center(
        child: Text(localizations.text('greetings.goodbye')),
      ),
    );
  }
}

注意:在Localizations.of<TomlLocalizations>调用中传递TomlLocalizationDelegate()可能不是最佳实践,因为通常Flutter框架会管理这些委托。然而,由于toml_localizations不是一个官方支持的插件,这里可能需要一些变通方法。在实际应用中,你可能需要调整这部分代码以确保它符合你的具体需求和插件的实现方式。

这个示例展示了如何使用toml_localizations插件从TOML文件中加载本地化内容,并在Flutter应用中显示。根据你的具体需求,你可能需要调整TOML文件的解析逻辑和本地化委托的实现。

回到顶部