internationalizing/localizing Flutter 应用的不同方法
Different methods of internationalizing/localizing Flutter apps
根据Flutter docs,我们可以通过2种方法添加本地化消息:
方法一
将以下内容添加到 pubspec.yaml
文件中。
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: ^0.17.0
flutter:
generate: true
创建一个 <project-root>/l10n.yaml
文件包含:
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: demo_localizations.dart
在 <project-root/l10n.yaml>
中,为您的翻译文件创建 app_locale.arb
。例如:
app_en.arb
{
"@@locale": "en",
"helloWorld": "Hello World!"
}
app_es.arb
{
"@@locale": "es",
"helloWorld": "Hola Mundo!"
}
demo_localizations.dart
将生成并可以像这样导入到 main.dart
:
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/demo_localizations.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: DemoLocalizations.localizationsDelegates,
supportedLocales: DemoLocalizations.supportedLocales,
title: 'My app',
home: ... ,
);
}
}
方法 2:为应用的本地化资源定义 class
将以下内容添加到 pubspec.yaml
文件中。
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: ^0.17.0
intl_translation:
flutter:
generate: true
创建一个使用 initializeMessages()
和 Intl.message()
.
的 DemoLocalizations
class
class DemoLocalizations {
DemoLocalizations(this.localeName);
static Future<DemoLocalizations> load(Locale locale) {
final String name = locale.countryCode == null || locale.countryCode!.isEmpty
? locale.languageCode
: locale.toString();
final String localeName = Intl.canonicalizedLocale(name);
return initializeMessages(localeName).then((_) {
return DemoLocalizations(localeName);
});
}
static DemoLocalizations of(BuildContext context) {
return Localizations.of<DemoLocalizations>(context, DemoLocalizations)!;
}
final String localeName;
String get title {
return Intl.message(
'Hello World',
name: 'title',
desc: 'Title for the Demo application',
locale: localeName,
);
}
}
创建 DemoLocalizationsDelegate
class.
class DemoLocalizationsDelegate extends LocalizationsDelegate<DemoLocalizations> {
const DemoLocalizationsDelegate();
@override
bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);
@override
Future<DemoLocalizations> load(Locale locale) => DemoLocalizations.load(locale);
@override
bool shouldReload(DemoLocalizationsDelegate old) => false;
}
运行
flutter pub run intl_translation:extract_to_arb --output-dir=lib/l10n lib/demo_localizations.dart
生成intl_messages.arb
文件。添加 intl_en.arb
和 intl_es.arb
作为您的翻译文件。
以应用根目录为当前目录,运行
flutter pub run intl_translation:generate_from_arb --output-dir=lib/l10n --no-use-deferred-loading lib/demo_localizations.dart lib/l10n/intl_*.arb
为每个 intl_<locale>.arb
文件和 intl_messages_all.dart
生成 intl_messages_<locale>.dart
,这会导入所有消息文件。
将所需的 class 导入 main.dart
。
import 'package:flutter/material.dart';
import 'demo_localizations.dart';
import 'package:intl/intl.dart';
import 'l10n/messages_all.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: DemoLocalizations.localizationsDelegates,
supportedLocales: DemoLocalizations.supportedLocales,
title: 'My app',
home: ... ,
);
}
}
这两种方法有区别吗?我可以知道为什么我们使用方法 2 因为涉及更多的步骤吗?
intl 包的缺点,它需要在上下文中调用 class。
例如
S.of(context).nameOfLocalizedText
我认为值得尝试一种不同的方法来创建 class 静态字符串和本地化切换器指的是当前语言环境。并且只在没有上下文的情况下调用 class 。不幸的是,我没有示例,但您可以尝试为语言切换器创建一个 class,一个用于将 JSON 映射到 class 的 class 映射器,以及包含语言字典的 map。希望对您有所帮助。
简单的答案是,您描述为“方法 #1”的是最新版本的如何在 Flutter 中执行此操作而无需外部手段。现在比以往任何时候都更简单,无需外部包。
其他方法来自“以前”,您必须做更多的工作才能启动它 运行,这就是为什么有这么多替代软件包,其中一些现在似乎已过时, Flutter 系统本身发生了变化,变得更简单、更有用。
根据Flutter docs,我们可以通过2种方法添加本地化消息:
方法一
将以下内容添加到
pubspec.yaml
文件中。dependencies: flutter: sdk: flutter flutter_localizations: sdk: flutter intl: ^0.17.0 flutter: generate: true
创建一个
<project-root>/l10n.yaml
文件包含:arb-dir: lib/l10n template-arb-file: app_en.arb output-localization-file: demo_localizations.dart
在
<project-root/l10n.yaml>
中,为您的翻译文件创建app_locale.arb
。例如:app_en.arb
{ "@@locale": "en", "helloWorld": "Hello World!" }
app_es.arb
{ "@@locale": "es", "helloWorld": "Hola Mundo!" }
demo_localizations.dart
将生成并可以像这样导入到main.dart
:import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/demo_localizations.dart'; class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( localizationsDelegates: DemoLocalizations.localizationsDelegates, supportedLocales: DemoLocalizations.supportedLocales, title: 'My app', home: ... , ); } }
方法 2:为应用的本地化资源定义 class
将以下内容添加到
pubspec.yaml
文件中。dependencies: flutter: sdk: flutter flutter_localizations: sdk: flutter intl: ^0.17.0 intl_translation: flutter: generate: true
创建一个使用
的initializeMessages()
和Intl.message()
.DemoLocalizations
classclass DemoLocalizations { DemoLocalizations(this.localeName); static Future<DemoLocalizations> load(Locale locale) { final String name = locale.countryCode == null || locale.countryCode!.isEmpty ? locale.languageCode : locale.toString(); final String localeName = Intl.canonicalizedLocale(name); return initializeMessages(localeName).then((_) { return DemoLocalizations(localeName); }); } static DemoLocalizations of(BuildContext context) { return Localizations.of<DemoLocalizations>(context, DemoLocalizations)!; } final String localeName; String get title { return Intl.message( 'Hello World', name: 'title', desc: 'Title for the Demo application', locale: localeName, ); } }
创建
DemoLocalizationsDelegate
class.class DemoLocalizationsDelegate extends LocalizationsDelegate<DemoLocalizations> { const DemoLocalizationsDelegate(); @override bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode); @override Future<DemoLocalizations> load(Locale locale) => DemoLocalizations.load(locale); @override bool shouldReload(DemoLocalizationsDelegate old) => false; }
运行
flutter pub run intl_translation:extract_to_arb --output-dir=lib/l10n lib/demo_localizations.dart
生成
intl_messages.arb
文件。添加intl_en.arb
和intl_es.arb
作为您的翻译文件。以应用根目录为当前目录,运行
flutter pub run intl_translation:generate_from_arb --output-dir=lib/l10n --no-use-deferred-loading lib/demo_localizations.dart lib/l10n/intl_*.arb
为每个
intl_<locale>.arb
文件和intl_messages_all.dart
生成intl_messages_<locale>.dart
,这会导入所有消息文件。将所需的 class 导入
main.dart
。import 'package:flutter/material.dart'; import 'demo_localizations.dart'; import 'package:intl/intl.dart'; import 'l10n/messages_all.dart'; class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( localizationsDelegates: DemoLocalizations.localizationsDelegates, supportedLocales: DemoLocalizations.supportedLocales, title: 'My app', home: ... , ); } }
这两种方法有区别吗?我可以知道为什么我们使用方法 2 因为涉及更多的步骤吗?
intl 包的缺点,它需要在上下文中调用 class。 例如
S.of(context).nameOfLocalizedText
我认为值得尝试一种不同的方法来创建 class 静态字符串和本地化切换器指的是当前语言环境。并且只在没有上下文的情况下调用 class 。不幸的是,我没有示例,但您可以尝试为语言切换器创建一个 class,一个用于将 JSON 映射到 class 的 class 映射器,以及包含语言字典的 map
简单的答案是,您描述为“方法 #1”的是最新版本的如何在 Flutter 中执行此操作而无需外部手段。现在比以往任何时候都更简单,无需外部包。
其他方法来自“以前”,您必须做更多的工作才能启动它 运行,这就是为什么有这么多替代软件包,其中一些现在似乎已过时, Flutter 系统本身发生了变化,变得更简单、更有用。