3.10 国际化与本地化 (Internationalization and Localization)
plaintext
复制代码
arb-dir: lib/l10n # .arb 文件存放的目录
template-arb-file: app_en.arb # 模板文件,通常是英文
output-localization-file: app_localizations.dart # 生成的本地化文件名称
```
  1. 创建 .arb 文件:在 lib/l10n 目录下创建 .arb 文件,每个文件对应一种语言。

    • app_en.arb (英文模板)
      json
      复制代码
      {
        "@@locale": "en",
        "helloWorld": "Hello World",
        "greeting": "Hello {name}",
        "@greeting": {
          "placeholders": {
            "name": {}
          }
        },
        "pluralExample": "{count, plural, one{One item} other{{count} items}}"
      }
    • app_zh.arb (中文)
      json
      复制代码
      {
        "@@locale": "zh",
        "helloWorld": "你好世界",
        "greeting": "你好 {name}",
        "pluralExample": "{count, plural, one{一个项目} other{{count} 个项目}}"
      }
  2. 生成本地化代码:运行 flutter gen-l10n 命令(如果 flutter: generate: truepubspec.yaml 中设置,则 flutter runflutter build 会自动触发)。这会在 .dart_tool/flutter_gen/gen_l10n/ 目录下生成 app_localizations.dart 和其他相关文件。

  3. MaterialApp 中配置:在 MaterialApp 中添加 localizationsDelegatessupportedLocales

    dart
    复制代码
    import 'package:flutter_gen/gen_l10n/app_localizations.dart';
    
    MaterialApp(
      localizationsDelegates: const [
        AppLocalizations.delegate, // 由 flutter gen-l10n 生成
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: const [
        Locale('en', ''), // English
        Locale('zh', ''), // Chinese
      ],
      // ...
    );
  4. 在 Widget 中使用:通过 AppLocalizations.of(context) 访问本地化字符串。

    dart
    复制代码
    Text(AppLocalizations.of(context)!.helloWorld);
    Text(AppLocalizations.of(context)!.greeting("Alice"));
    Text(AppLocalizations.of(context)!.pluralExample(1));
    Text(AppLocalizations.of(context)!.pluralExample(5));

官方文档链接

Flutter 开发中的应用案例

国际化和本地化是构建面向全球用户的应用程序的关键。通过 Flutter 提供的国际化支持,我们可以轻松地为应用添加多语言功能,提升用户体验。

案例:一个支持中英文切换的简单应用

我们将创建一个简单的 Flutter 应用,演示如何实现中英文文本的切换,以及如何处理带参数的字符串和复数形式。

步骤 1: 按照上述“实现国际化的步骤”配置项目

确保 pubspec.yamll10n.yaml.arb 文件都已正确设置,并运行 flutter gen-l10n

步骤 2: 创建 Flutter 应用 (lib/main.dart)

dart
复制代码
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; // 导入生成的本地化文件
import 'package:flutter_localizations/flutter_localizations.dart'; // 导入 Flutter 本地化委托

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

  @override
  State<LocalizationExampleScreen> createState() => _LocalizationExampleScreenState();
}

class _LocalizationExampleScreenState extends State<LocalizationExampleScreen> {
  int _itemCount = 0;

  void _incrementItemCount() {
    setState(() {
      _itemCount++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // 获取当前本地化实例
    final AppLocalizations? appLocalizations = AppLocalizations.of(context);

    // 如果 appLocalizations 为 null,说明本地化未加载或配置错误,显示默认文本
    if (appLocalizations == null) {
      return const Scaffold(
        appBar: AppBar(title: Text('Error')),
        body: Center(child: Text('Localization not loaded.')),
      );
    }

    return Scaffold(
      appBar: AppBar(
        title: Text(appLocalizations.helloWorld), // 使用本地化字符串作为标题
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              appLocalizations.greeting('Flutter User'), // 使用带参数的本地化字符串
              style: const TextStyle(fontSize: 24),
            ),
            const SizedBox(height: 20),
            Text(
              appLocalizations.pluralExample(_itemCount), // 使用复数形式的本地化字符串
              style: const TextStyle(fontSize: 24),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _incrementItemCount,
              child: const Text('增加项目'),
            ),
            const SizedBox(height: 20),
            // 切换语言的按钮
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton(
                  onPressed: () {
                    // 切换到英文
                    // 这需要重新启动 MaterialApp 或使用更高级的状态管理来改变 Locale
                    // 简单示例中,我们假设用户通过系统设置切换语言
                    // 实际应用中,可以通过 Provider 或 Bloc 来管理 Locale 状态
                    print('切换到英文 (需要重启应用或刷新 Locale)');
                  },
                  child: const Text('English'),
                ),
                ElevatedButton(
                  onPressed: () {
                    // 切换到中文
                    print('切换到中文 (需要重启应用或刷新 Locale)');
                  },
                  child: const Text('中文'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

void main() {
  runApp(MaterialApp(
    home: const LocalizationExampleScreen(),
    // 配置本地化委托和支持的语言环境
    localizationsDelegates: const [
      AppLocalizations.delegate,
      GlobalMaterialLocalizations.delegate,
      GlobalWidgetsLocalizations.delegate,
      GlobalCupertinoLocalizations.delegate,
    ],
    supportedLocales: const [
      Locale('en', ''), // English
      Locale('zh', ''), // Chinese
    ],
    // 可以通过 locale 属性设置初始语言环境,或通过设备语言环境自动检测
    // locale: const Locale('zh', ''),
  ));
}

案例分析:

  • flutter: generate: true:在 pubspec.yaml 中启用此选项后,Flutter 会自动生成本地化代码。
  • l10n.yaml:配置 .arb 文件的位置和生成的 Dart 文件名。
  • .arb 文件:JSON 格式的资源文件,键值对表示本地化字符串。{name} 是占位符,{count, plural, ...} 是复数规则。
  • AppLocalizations.delegate:由 flutter gen-l10n 命令生成,负责加载应用程序自定义的本地化字符串。
  • GlobalMaterialLocalizations.delegate:Flutter 框架提供的本地化委托,用于加载 Material Design 组件、Widget 和 Cupertino 组件的本地化字符串。
  • supportedLocales:声明应用程序支持的所有语言环境。Flutter 会根据设备的语言环境,从这个列表中选择最匹配的语言。
  • AppLocalizations.of(context)!:在 Widget 中,通过 AppLocalizations.of(context) 获取当前语言环境的本地化实例。由于 of(context) 可能返回 null(例如在 MaterialApp 之外调用),所以通常需要进行空安全检查或使用 ! 断言。
  • appLocalizations.greeting('Flutter User'):调用生成的本地化方法,传入参数来填充占位符。
  • appLocalizations.pluralExample(_itemCount):调用生成的本地化方法,传入计数器值,根据 .arb 文件中的复数规则返回正确的字符串。

这个案例清晰地展示了 Flutter 国际化和本地化的基本流程和使用方法。通过这种方式,我们可以轻松地为 Flutter 应用添加多语言支持,使其能够更好地服务于全球用户。