Flutter多语言翻译插件flutter_arb_translator的使用

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

Flutter多语言翻译插件 flutter_arb_translator 的使用

flutter_arb_translator 是一个简化 Flutter ARB 文件翻译的命令行工具。它支持多种翻译服务,如 Azure Cognitive Services、Yandex、Google Cloud、DeepL 和 Amazon Translate,并允许灵活调整翻译选项。

安装

在您的项目中添加 flutter_arb_translatordev_dependencies

dev_dependencies:
  flutter_arb_translator: ^1.0.15

示例

使用此插件可以翻译包含注释、复数和占位符的 ARB 文件。例如,将以下文件翻译成西班牙语:

原始 ARB 文件(英语)

{
  "appName": "Demo app",
  "pageHomeTitle": "Welcome {firstName}",
  "@pageHomeTitle": {
    "description": "Welcome message on the Home screen",
    "placeholders": {
      "firstName": {
        "type": "String",
        "example": "John Doe"
      }
    }
  },
  "pageHomeInboxCount": "{count, plural, zero{You have no new messages} one{You have 1 new message} other{You have {count} new messages}}",
  "@pageHomeInboxCount": {
    "description": "New messages count on the Home screen",
    "placeholders": {
      "count": {}
    }
  },
  "pageHomeBirthday": "{sex, select, male{His birthday} female{Her birthday} other{Their birthday}}",
  "@pageHomeBirthday": {
    "description": "Birthday message on the Home screen",
    "placeholders": {
      "sex": {}
    }
  }
}

翻译后的 ARB 文件(西班牙语)

{
  "appName": "Aplicación de demostración",
  "pageHomeTitle": "Bienvenidos {firstName}",
  "@pageHomeTitle": {
    "description": "Welcome message on the Home screen",
    "placeholders": {
      "firstName": {
        "type": "String",
        "example": "John Doe"
      }
    }
  },
  "pageHomeInboxCount": "{count, plural, zero{No tienes mensajes nuevos} one{Tienes 1 mensaje nuevo} other{Has {count} nuevos mensajes}}",
  "@pageHomeInboxCount": {
    "description": "New messages count on the Home screen",
    "placeholders": {
      "count": {}
    }
  },
  "pageHomeBirthday": "{sex, select, male{Su cumpleaños} female{Su cumpleaños} other{Su cumpleaños}}",
  "@pageHomeBirthday": {
    "description": "Birthday message on the Home screen",
    "placeholders": {
      "sex": {}
    }
  }
}

使用指南

1. 设置配置文件

在项目的根目录下创建一个 dev_assets 文件夹,并在此文件夹中创建 flutter_arb_translator_config.json 文件。该文件的内容包含可选的 JSON 对象,完整的文件示例如下:

{
  "AzureCognitiveServices": {
    "SubscriptionKey": "<required>",
    "Region": "<optional>"
  },
  "YandexCloud": {
    "APIKey": "<required>"
  },
  "GoogleCloud": {
    "ProjectId": "<required>",
    "PrivateKey": "<required>",
    "ClientEmail": "<required>"
  },
  "DeepL": {
    "Url": "https://api.deepl.com",
    "ApiKey": "<required>"
  },
  "AmazonTranslate": {
    "AccessKeyId": "<required>",
    "SecretAccessKey": "<required>",
    "Region": "<required>"
  }
}

如果要使用 Azure 翻译服务,则只需要在配置文件中包含 AzureCognitiveServices 部分,而 YandexCloud、GoogleCloud、AmazonTranslate 和 DeepL 部分可以省略。

2. 设置翻译服务配置

Azure

Azure Cognitive Services 翻译服务使用订阅密钥进行授权。请参阅此处了解如何创建或查找订阅密钥。获取密钥后,将其放入 dev_assets/flutter_arb_translator_config.json 中的 AzureCognitiveServices JSON 对象中:

{
  "AzureCognitiveServices": {
    "SubscriptionKey": "*********************************",
    "Region": "your_region"
  }
}

Yandex

Yandex 翻译服务使用 API 密钥进行授权。请参阅此处了解如何创建 API 密钥。获取密钥后,将其放入 dev_assets/flutter_arb_translator_config.json 中的 YandexCloud JSON 对象中:

{
  "YandexCloud": {
    "APIKey": "********************"
  }
}

Google Cloud

Google Cloud 翻译服务使用服务账户进行授权。您需要创建一个新的服务账户或使用现有的账户,并将其私钥导出为 JSON 格式。然后将 project_idprivate_keyclient_email 放入 dev_assets/flutter_arb_translator_config.json 中的 GoogleCloud 对象中:

{
  "GoogleCloud": {
    "ProjectId": "your_project_id",
    "PrivateKey": "-----BEGIN PRIVATE KEY-----\n****private_key_content*****\n-----END PRIVATE KEY-----\n",
    "ClientEmail": "your_client_email"
  }
}

DeepL

DeepL 翻译服务使用 API 密钥进行授权。请参阅此处了解如何创建 API 密钥。获取密钥后,将其放入 dev_assets/flutter_arb_translator_config.json 中的 DeepL JSON 对象中:

{
  "DeepL": {
    "Url": "https://api.deepl.com",
    "ApiKey": "********-****-****-****-************"
  }
}

如果您使用的是免费的 DeepL API 密钥,请更新 DeepL 配置中的 Url 值。

Amazon Translate

Amazon Translate 翻译服务使用访问密钥进行授权。请参阅此处了解如何创建访问密钥。获取密钥后,将其放入 dev_assets/flutter_arb_translator_config.json 中的 AmazonTranslate JSON 对象中:

{
  "AmazonTranslate": {
    "AccessKeyId": "<required>",
    "SecretAccessKey": "<required>",
    "Region": "<required>"
  }
}

使用方法

假设您将 ARB 文件存储在 lib/l10n 文件夹中,并希望使用 Azure Cognitive Services 翻译器将 app_en.arb 翻译成西班牙语和意大利语。运行以下命令:

flutter pub run flutter_arb_translator:main --from en --to es --to it --service azure

当命令完成后,它会写入 lib/l10n/app_es.arblib/l10n/app_it.arb 文件,其中包含翻译内容。就是这样,如果想查看所有可用选项,请键入:

flutter pub run flutter_arb_translator:main -h

命令行选项

选项 描述
dir (可选)包含 .arb 文件的目录。默认设置为 lib/l10n
service (必填)使用的翻译服务。[azure, yandex, google, deepl, amazon]
from (必填)主语言,ARB 将从此语言翻译为目标语言。示例:--from en
to (必填)目标语言列表,至少需要指定一种语言。示例:--to es,pt--to es --to pt
key (可选)如果定义了,只翻译给定键的项。示例:-k key1 -k key2
ignore (可选)如果定义了,跳过给定键的项。示例:--ignore key1,key2
override (可选)如果为 true 并且目标语言的 ARB 文件已存在,则所有项都将被新翻译替换。默认值为 false
interactive (可选)提示是否应用翻译。默认值为 false
translate-equal (可选)如果为 true 并且目标语言的 ARB 文件条目与源 ARB 文件条目相等时也会翻译。默认值为 false
prefix (可选)用于查找文件的前缀。默认值为 app

示例 Demo

以下是一个简单的 Flutter 应用程序示例,展示了如何使用 flutter_arb_translator 工具来处理多语言支持。

lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

/// lib/l10n 已经包含西班牙语的翻译,但不包含意大利语和德语的翻译。
/// 如果您运行应用程序并尝试更改语言,直到您使用 flutter_arb_translator 工具添加它们之前,它将会失败。

/// 1. 打开 dev_assets/flutter_arb_translator_config.json
/// 2. 添加 AzureCognitiveServices 或 YandexCloud 或 GoogleCloud 配置
/// 3. 运行以下命令:
/// flutter pub run flutter_arb_translator:main --from en --to de --to it --service azure
/// 其中 --service azure 取决于您想要使用的翻译服务。对于 Yandex,使用 --service yandex;对于 Google Cloud,使用 --service google;对于 DeepL,使用 --service deepl。
/// 完成这些步骤后,翻译将被创建,您可以更改语言。

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

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _supportedLocales = const [
    Locale('en', ''), // 英语,无国家代码
    Locale('es', ''), // 西班牙语,无国家代码
    Locale('it', ''), // 意大利语,无国家代码
    Locale('de', ''), // 德语,无国家代码
  ];

  String _selectedLocale = 'en';

  void _changeLocale(String newLocale) {
    if (newLocale.isEmpty) {
      return;
    }

    if (!_supportedLocales.map((x) => x.languageCode).contains(newLocale)) {
      return;
    }

    setState(() {
      _selectedLocale = newLocale;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      localizationsDelegates: AppLocalizations.localizationsDelegates,
      supportedLocales: _supportedLocales,
      locale: Locale(_selectedLocale),
      home: MyHomePage(
        title: 'Demo Home Page',
        supportedLocales: _supportedLocales,
        selectedLocale: _selectedLocale,
        selectLocale: _changeLocale,
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({
    Key? key,
    required this.title,
    required this.supportedLocales,
    required this.selectedLocale,
    required this.selectLocale,
  }) : super(key: key);

  final String title;
  final List<Locale> supportedLocales;
  final String selectedLocale;
  final void Function(String) selectLocale;

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    final locale = AppLocalizations.of(context)!;

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  locale.pick_language,
                  style: Theme.of(context).textTheme.bodyLarge,
                ),
                const SizedBox(
                  height: 4,
                ),
                DropdownButton<String>(
                  isExpanded: true,
                  value: widget.selectedLocale,
                  items: widget.supportedLocales
                      .map(
                        (x) => DropdownMenuItem<String>(
                          value: x.languageCode,
                          child: Text(x.languageCode),
                        ),
                      )
                      .toList(),
                  onChanged: (String? v) {
                    if (v == null) {
                      return;
                    }

                    widget.selectLocale.call(v);
                  },
                ),
                Text(
                  locale.make_sure_you_added_italian_and_deutsch_translations,
                  style: Theme.of(context).textTheme.bodyLarge!.copyWith(
                        fontSize:
                            Theme.of(context).textTheme.bodyLarge!.fontSize! *
                                0.85,
                      ),
                ),
              ],
            ),
            Expanded(
              child: Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Text(
                      '${locale.you_have_pushed_the_button_this_many_times}:',
                    ),
                    Text(
                      '$_counter',
                      style: Theme.of(context).textTheme.displaySmall,
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: locale.increment,
        child: const Icon(Icons.add),
      ),
    );
  }
}

通过上述步骤,您可以轻松地将您的 Flutter 应用程序扩展为支持多语言,并利用 flutter_arb_translator 插件自动化翻译过程。


更多关于Flutter多语言翻译插件flutter_arb_translator的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter多语言翻译插件flutter_arb_translator的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter项目中实现多语言支持时,flutter_arb_translator 是一个有用的工具,它可以帮助你将ARB(Application Resource Bundle)文件翻译成不同的语言。ARB文件是Flutter用于存储本地化字符串的文件格式。

以下是如何在Flutter项目中使用 flutter_arb_translator 的一个简单示例。请注意,由于flutter_arb_translator 本身可能是一个假设的或特定实现的库(实际上Flutter社区更常用intl_translation等官方工具),以下代码主要展示了如何处理和翻译ARB文件的基本概念,并假设有一个类似的工具来辅助这一过程。

首先,确保你的Flutter项目中已经添加了相关的依赖项(这里假设flutter_arb_translator是一个存在的pub包,实际上你可能需要使用其他类似工具)。

# pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  # 假设 flutter_arb_translator 存在,实际上你可能需要查找并添加正确的包
  flutter_arb_translator: ^x.y.z 

然后,你可以创建一个ARB文件来存储你的本地化字符串。例如,创建一个messages_en.arb文件:

// messages_en.arb
{
  "welcome_message": "Welcome to our app!",
  "goodbye_message": "Goodbye!"
}

接下来,假设你有一个翻译工具或脚本(这里以伪代码形式展示flutter_arb_translator的使用),它会读取这个ARB文件并生成其他语言的ARB文件。

// 伪代码示例,展示如何使用 flutter_arb_translator 假设它存在
import 'package:flutter_arb_translator/flutter_arb_translator.dart';

void main() {
  // 读取原始的ARB文件
  String englishArbContent = File('assets/locales/messages_en.arb').readAsStringSync();

  // 使用翻译工具进行翻译(这里假设有一个translate方法)
  // 注意:实际的flutter_arb_translator库可能有不同的API,这里仅为示例
  Map<String, String> translatedMessages = FlutterArbTranslator.translate(
    englishArbContent,
    sourceLanguage: 'en',
    targetLanguage: 'es', // 例如,翻译成西班牙语
  );

  // 将翻译后的内容写入新的ARB文件
  File('assets/locales/messages_es.arb').writeAsStringSync(jsonEncode(translatedMessages));
}

注意:上面的代码是假设性的,因为实际上flutter_arb_translator可能并不存在,或者它的API可能与上面的示例不同。在实际操作中,你可能需要使用其他工具或手动翻译ARB文件。

一个更实际的方法是使用intl_translation工具结合Google Sheets或第三方翻译服务来管理翻译过程。以下是如何使用intl_translation生成ARB文件的步骤:

  1. 安装intl_translation工具:
flutter pub global activate intl_translation
  1. 在你的Flutter项目中创建一个intl_messages.dart文件,并定义你的本地化字符串:
// intl_messages.dart
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class Messages {
  Messages._();

  static Map<String, Map<String, String>> _localizedValues;
  static IntlLocalizations localizations;

  static Map<String, String> of(Locale locale) {
    locale = locale ?? Locale("en", "");

    final String languageCode = locale.languageCode;
    final String countryCode = locale.countryCode?.isEmpty ?? true ? "" : locale.countryCode!;
    final String localeName = "$languageCode${countryCode.isEmpty ? "" : "_$countryCode"}";

    return _localizedValues[localeName] ?? _localizedValues["en"]!;
  }

  static Future<void> load(Locale locale) async {
    localizations = IntlLocalizations(locale: locale);
    await initializeMessages(locale.toString());
  }

  static String get welcome_message {
    return Intl.message(
      'Welcome to our app!',
      name: 'welcome_message',
      desc: 'Welcome screen greeting message',
    );
  }

  static String get goodbye_message {
    return Intl.message(
      'Goodbye!',
      name: 'goodbye_message',
      desc: 'Goodbye message',
    );
  }
}
  1. 使用flutter pub run intl_translation:extract_to_arb命令提取ARB模板文件,然后手动或使用翻译服务填充这些文件。

  2. 使用flutter pub run intl_translation:generate_from_arb命令生成本地化的Dart文件。

通过这些步骤,你可以在Flutter项目中实现多语言支持,而无需依赖一个假设的flutter_arb_translator库。

回到顶部