Skip to content

Flutter - 国际化

国际化(Internationalization)(通常缩写为 i18n)是设计和开发你的应用程序的过程,使其无需进行工程更改即可轻松适应各种语言和地区。本地化(Localization)(l10n)是后续过程,通过添加特定于语言环境的组件和翻译文本,将国际化的应用程序适应特定区域或语言。

Flutter 为 i18n 和 l10n 提供了出色的支持,使你的应用能够触及全球用户。

  • Locale: 代表用户首选语言和可选地区(国家代码)的对象。示例:Locale('en')(英语),Locale('en', 'US')(美式英语),Locale('es', 'AR')(阿根廷西班牙语)。
  • 本地化消息(Localized Messages): 特定于每种支持的语言环境的文本字符串和其他语言环境敏感数据(如日期/时间格式、数字格式、货币)。
  • Localizations Widget: 一个 widget,提供在 widget 树中访问本地化值的功能。位于其下方的 widgets 可以获取当前的 Locale 和相应的资源。
  • LocalizationsDelegate: 一个工厂,负责创建特定 Localizations 类的实例(例如,你的应用消息、Material/Cupertino widget 翻译)。它决定支持哪些语言环境并加载相应的资源。

推荐的方法是使用 flutter_localizations 包(用于内置 widget 的翻译)和 intl 包(用于处理你的应用的特定消息和格式)。

将必要的包添加到你的 pubspec.yaml 中:

dependencies:
flutter:
sdk: flutter
# Provides Material/Cupertino localizations
flutter_localizations:
sdk: flutter
# Core internationalization utilities (messages, date/number formatting)
intl: ^0.18.0 # Use latest version
# Add this section to enable code generation for intl
flutter:
uses-material-design: true
generate: true # Required for intl code generation

运行 flutter pub get。

在你的 MaterialApp(或 CupertinoApp)中,配置本地化委托(localization delegates)和支持的语言环境(supported locales):

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
// Import generated messages (will be created later)
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'i18n Demo App', // Title might also need localization
// Define supported locales
supportedLocales: const [
Locale('en', ''), // English, no country code
Locale('es', ''), // Spanish, no country code
// Add other locales your app supports
],
// Define localization delegates
localizationsDelegates: const [
AppLocalizations.delegate, // Your app's specific messages
GlobalMaterialLocalizations.delegate, // Built-in Material widgets translations
GlobalWidgetsLocalizations.delegate, // Text direction, etc.
GlobalCupertinoLocalizations.delegate, // Built-in Cupertino widgets translations
],
// Optional: Force a locale (for testing) or let Flutter decide
// locale: Locale('es', ''),
home: MyHomePage(),
);
}
}

应用资源包(Application Resource Bundle,.arb)文件以 JSON 格式存储你的本地化消息。

  • 在项目根目录(与 pubspec.yaml 并列)创建一个名为 l10n.yaml 的新文件。配置它以指定模板 ARB 文件和输出目录:

  • 创建 arb-dir 中指定的目录(例如,lib/l10n)。

  • 在 lib/l10n 中,创建模板 ARB 文件(本例中为 app_en.arb)。此文件定义消息键、默认文本(英语)和可选描述:

  • 为其他支持的语言环境创建翻译文件(例如,app_es.arb)。复制 app_en.arb 中的键并提供翻译:

每当你修改 ARB 文件或 l10n.yaml 时,Flutter 会自动生成所需的 Dart 代码(这得益于 pubspec.yaml 中的 generate: true)。如果它没有自动运行,你可能需要触发构建或手动运行 flutter gen-l10n。

这会在 flutter_gen 目录(通常在项目视图中隐藏,但可以通过 import 访问)中生成文件,包括 app_localizations.dart 和特定语言环境的类。

导入生成的 AppLocalizations 类,并使用 AppLocalizations.of(context)!.messageKey 访问消息。

import 'package:flutter/material.dart';
// Import generated messages
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Access the localizations object
final l10n = AppLocalizations.of(context)!;
String userName = 'Flutter Dev'; // Example user name
int wombatCount = 2;
return Scaffold(
// Use localized app title
appBar: AppBar(title: Text(l10n.appTitle)),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// Use localized greeting
Text(l10n.helloWorld),
const SizedBox(height: 10),
// Use localized message with placeholder
Text(l10n.helloUser(userName)),
const SizedBox(height: 10),
// Use localized plural message
Text(l10n.nWombats(wombatCount)),
],
),
),
);
}
}
  • 设备设置: 更改测试设备或模拟器的语言设置。
  • locale 属性: 在开发期间,暂时设置 MaterialApp 中的 locale 属性以强制使用特定语言环境。

intl 包还提供了日期、数字和货币的语言环境感知格式化功能。

import 'package:intl/intl.dart';
// Inside a widget or function where 'context' is available
void showFormattedData(BuildContext context) {
final currentLocale = Localizations.localeOf(context).toString(); // e.g., 'en_US', 'es'
// Date Formatting
final now = DateTime.now();
final dateFormatter = DateFormat.yMMMd(currentLocale); // Locale-aware format
print('Formatted Date: ${dateFormatter.format(now)}');
// Number Formatting
final number = 1234567.89;
final numberFormatter = NumberFormat.decimalPattern(currentLocale);
print('Formatted Number: ${numberFormatter.format(number)}');
// Currency Formatting
final currencyFormatter = NumberFormat.currency(locale: currentLocale, symbol: '€'); // Example symbol
print('Formatted Currency: ${currencyFormatter.format(number)}');
}

国际化对于触及更广泛的受众至关重要。Flutter 的内置支持和 intl 包提供了一个强大的框架来管理翻译和特定于语言环境的数据。