Flutter本地化文件生成插件flutter_sheet_localization_generator的使用

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

Flutter本地化文件生成插件flutter_sheet_localization_generator的使用

flutter_sheet_localization_generator 是一个用于从在线Google Sheet文件生成Flutter本地化代理的插件。通过这个插件,你可以轻松地将Google Sheets中的翻译数据转换为Dart代码,从而实现多语言支持。以下是详细的使用步骤和完整的示例代码。

1. 安装

首先,在你的 pubspec.yaml 文件中添加以下依赖项:

dependencies:
  flutter_sheet_localization: ^latest_version
  flutter_localizations:
    sdk: flutter

dev_dependencies:
  flutter_sheet_localization_generator: ^latest_version
  build_runner: ^latest_version

请确保将 ^latest_version 替换为实际的最新版本号。

2. 使用步骤

2.1 创建Google Sheet

创建一个包含翻译内容的Google Sheet文件,格式如下:

  • 第一行是表头:

    • 第一列:Key
    • 后续列:支持的语言代码(如 enfr 等)
  • 后续行是具体的翻译内容:

    • 第一列:标签键(可以使用点分隔符表示层次结构)
    • 后续列:对应语言的翻译内容

示例表格:

Key (Comments) en fr
example.man(Gender.male) This is a man title on home page man homme
example.man(Gender.female) This is a woman title on home page woman femme
dates.month.february February Février
templated.hello Hello {{first_name}}! Hello Bonjour
plurals.man(Plural.zero) men hommes
plurals.man(Plural.one) man homme
plurals.man(Plural.multiple) men hommes

确保你的Google Sheet文件是共享的,并且可以从链接中提取 DOCIDSHEETID。例如,从链接 https://docs.google.com/spreadsheets/d/DOCID/edit#gid=SHEETID 中提取 DOCIDSHEETID

2.2 声明本地化代理

lib/localization.dart 文件中声明 AppLocalizationsDelegate 类,并使用 @SheetLocalization 注解指向你的Google Sheet文件:

import 'package:flutter/widgets.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_sheet_localization/flutter_sheet_localization.dart';

part 'localization.g.dart';

@SheetLocalization("DOCID", "SHEETID", 1) // <- 请替换为实际的 DOCID 和 SHEETID
// 每次重新生成时需要递增 version 参数
class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizationsData> {
  const AppLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) => localizedLabels.containsKey(locale);

  @override
  Future<AppLocalizationsData> load(Locale locale) =>
      SynchronousFuture<AppLocalizationsData>(localizedLabels[locale]!);

  @override
  bool shouldReload(AppLocalizationsDelegate old) => false;
}
2.3 生成本地化文件

运行以下命令生成 lib/localization.g.dart 文件:

flutter packages pub run build_runner build
2.4 配置应用

更新你的Flutter应用以使用新创建的本地化代理:

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

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Locale? _currentLocale;

  @override
  void initState() {
    _currentLocale = localizedLabels.keys.first;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      locale: _currentLocale,
      localizationsDelegates: [
        const AppLocalizationsDelegate(), // <- 自定义代理
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: localizedLabels.keys.toList(), // <- 支持的语言
      home: MyHomePage(
        title: 'Internationalization demo',
        locale: _currentLocale!,
        onLocaleChanged: (locale) {
          if (_currentLocale != locale) {
            setState(() => _currentLocale = locale);
          }
        },
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage({
    Key? key,
    required this.title,
    required this.locale,
    required this.onLocaleChanged,
  }) : super(key: key);

  final String title;
  final Locale locale;
  final ValueChanged<Locale> onLocaleChanged;

  @override
  Widget build(BuildContext context) {
    final labels = context.localizations; // <- 访问标签

    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Column(
        children: <Widget>[
          DropdownButton<Locale>(
            key: Key('Picker'),
            value: locale,
            items: localizedLabels.keys.map((locale) {
              return DropdownMenuItem<Locale>(
                value: locale,
                child: Text(
                  locale.toString(),
                ),
              );
            }).toList(),
            onChanged: (locale) {
              if (locale != null) onLocaleChanged(locale);
            },
          ),
          Expanded(
            child: Column(
              children: <Widget>[
                Text(labels.dates.month.february),
                Text(labels.multiline),
                Text(labels.templated.hello(firstName: 'World')),
                Text(labels.templated.contact(gender: Gender.male, lastName: 'John')),
                Text(labels.templated.contact(gender: Gender.female, lastName: 'Jane')),
                Text('0 ' + labels.plurals.man(plural: 0.plural())),
                Text('1 ' + labels.plurals.man(plural: 1.plural())),
                Text('5 ' + labels.plurals.man(plural: 5.plural())),
                Text(labels.templated.numbers.simple(price: 10)),
                Text(labels.templated.numbers.formatted(price: 10)),
                Text(labels.templated.date.simple(date: DateTime.now())),
                Text(labels.templated.date.pattern(date: DateTime.now())),
              ],
            ),
          ),
        ],
      ),
    );
  }
}
2.5 显示标签

在你的Dart代码中,可以通过 AppLocalizations.of(context) 访问生成的标签:

final labels = AppLocalizations.of(context);
print(labels.dates.month.february);
print(labels.templated.hello(firstName: "World"));
print(labels.templated.contact(Gender.male, lastName: "John"));

3. 重新生成

由于 build_runner 的缓存机制,它无法检测到远程Google Sheet的变化。因此,每次你需要重新生成时,只需递增 @SheetLocalization 注解中的 version 参数,然后再次运行 build_runner

4. Google Sheet格式

Google Sheet文件应遵循以下格式:

  • 第一行是表头:

    • 第一列:Key
    • 后续列:支持的语言代码(如 enfr 等)
  • 后续行是具体的翻译内容:

    • 第一列:标签键(可以使用点分隔符表示层次结构)
    • 后续列:对应语言的翻译内容
忽略列

如果你需要添加注释或其他不需要生成的列,可以在列名中使用括号,例如 (Comments),这样该列将被忽略。

条件标签

你可以通过在键的末尾添加条件来创建条件标签,例如:

  • example.man(Gender.male)
  • example.man(Gender.female)
动态标签

你可以在翻译值中插入 {{KEY}} 模板,以便在代码中使用动态参数。例如:

/// Sheet
values.hello, "Hello {{first_name}}!"

/// Code
print(labels.values.hello(firstName: "World"));
类型参数

你还可以为参数指定类型(如 intdoublenumDateTime),方法是在键后缀中添加类型,例如:

/// Sheet
values.price, "The price is {{price:double}}$"

/// Code
print(labels.values.price(price: 10.5));
格式化参数

你可以通过在值的末尾添加格式化规则来指定如何格式化模板值。例如:

/// Sheet
values.price, "Price : {{price:double[compactCurrency]}}"

/// Code
print(labels.values.price(price: 2.00));
/// Sheet
values.today, "Today : {{date:DateTime[EEE, M/d/y]}}"

/// Code
print(labels.values.today(date: DateTime.now()));

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

1 回复

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


当然,以下是一个关于如何使用 flutter_sheet_localization_generator 插件来生成 Flutter 本地化文件的示例代码和步骤。这个插件可以极大地简化从 Google Sheets 导入本地化字符串的过程。

步骤 1: 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 flutter_sheet_localization_generator 依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter

dev_dependencies:
  flutter_sheet_localization_generator: ^x.y.z  # 替换为最新版本号
  build_runner: ^x.y.z  # 确保使用兼容版本

步骤 2: 准备 Google Sheets

创建一个包含本地化字符串的 Google Sheets 文档,并确保它有一个特定的结构,例如:

key en zh es
greeting Hello 你好 Hola
farewell Goodbye 再见 Adiós

步骤 3: 配置 build.yaml

在你的项目根目录下创建一个或编辑现有的 build.yaml 文件,添加以下配置:

targets:
  $default:
    builders:
      flutter_sheet_localization_generator:
        enabled: true
        options:
          google_sheets_id: 'YOUR_GOOGLE_SHEETS_ID'  # 替换为你的 Google Sheets ID
          output_dir: 'lib/l10n'  # 输出目录

步骤 4: 运行生成器

在终端中运行以下命令来生成本地化文件:

flutter pub run build_runner build

这个命令会根据 Google Sheets 中的数据在指定的 output_dir(这里是 lib/l10n)中生成本地化文件。

步骤 5: 使用生成的本地化文件

生成的本地化文件通常包含 *.arb 文件,你可以在 Flutter 应用中使用它们。首先,确保你的 MaterialAppCupertinoApp 使用 LocalizationsLocalizationsDelegate

假设生成的本地化文件名为 messages_en.arbmessages_zh.arb 等,你可以创建一个 l10n 目录来存放这些文件,并在 Flutter 应用中加载它们。

以下是一个简单的示例:

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

import 'l10n/messages_all.dart';  // 自动生成的文件

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      localizationsDelegates: [
        // 添加自动生成的委托
        S.delegate,
        // 其他本地化委托
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: S.delegate.supportedLocales,
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final S localizations = S.of(context);
    return Scaffold(
      appBar: AppBar(
        title: Text(localizations.greeting),
      ),
      body: Center(
        child: Text(localizations.farewell),
      ),
    );
  }
}

注意事项

  • 确保你的 Google Sheets 是公开的,或者你有正确的权限访问它。
  • 如果 Google Sheets 结构发生变化,重新运行生成器命令以更新本地化文件。
  • 插件版本和 Flutter SDK 版本需要兼容,确保使用最新版本的插件。

这样,你就可以使用 flutter_sheet_localization_generator 插件来生成和管理 Flutter 应用的本地化文件了。

回到顶部