【Flutter 实战】 Intl 插件实现国际化以及修改系统组件的国际化

2020-11-26 16:11:25 浏览数 (1)

老孟导读:本文介绍如何使用 Intl 插件实现国际化以及修改系统组件的国际化文案。

Intl 官方出品,包含用于处理国际化/本地化消息,日期和数字格式和解析,双向文本以及其他国际化问题。

pub地址:https://pub.dev/packages/intl Github地址:https://github.com/dart-lang/intl

Android Studio 和 VS Code 都有 Flutter Intl 插件,方便接入。

安装插件

并不是一定要使用插件,也可以通过命令行,当然 Flutter Intl 插件简化操作, Android Studio -> File -> Setting -> Plugins -> 搜索Flutter Intl:

安装重启即可。

VS Code 的 Flutter Intl 插件:https://marketplace.visualstudio.com/items?itemName=localizely.flutter-intl

添加依赖

在项目的 pubspec.yaml 文件中添加依赖:

代码语言:javascript复制
dev_dependencies:
 ...
  flutter_localizations:
    sdk: flutter

执行命令:

代码语言:javascript复制
flutter pub get

Tool->Flutter Intl ->Initalize for the project:

成功后,在 pubspec.yaml末尾增加:

代码语言:javascript复制
flutter_intl:
  enabled: true

在lib下生成generated 和 l10n

  • generated包下的intl目录默认生成 messages_all.dartmessages_en.dart 文件,messages开头的文件无需手动修改,是自动生成的。
  • generated包下的 I10n.dart 是Localizations和Delegate的实现,无需手动修改,是自动生成的。
  • l10n包下存在一个intl_en.arb文件,文案存放在此处。

添加语言

Tool->Flutter Intl -> Add Locale:

添加中文支持:

自动生成相关文件:

添加系统国际化支持

在pubspec.yaml文件中添加包依赖:

代码语言:javascript复制
dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter

MaterialApp 修改如下:

代码语言:javascript复制
MaterialApp(
  ...
  localizationsDelegates: [
    S.delegate,
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
  supportedLocales: S.delegate.supportedLocales,
  ...
)

在 intl_en.arb 和 intl_zh.arb下添加文案

添加一个 title 文案,intl_en.arb:

代码语言:javascript复制
{
  "title": "hello word"
}

intl_zh.arb:

代码语言:javascript复制
{
  "title": "你好"
}

command s 保存,generated 目录下相关文件将会重新生成。

使用:

代码语言:javascript复制
class LocalizationDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('${S.of(context).title}'),
      ),
    );
  }
}

Intl 还可以进行日期和数字格式化等, 具体功能可参考官方文档:https://github.com/dart-lang/intl。

国际化系统组件

部分系统组件已经支持国际化,那么如何修改其国际化文案呢?下面以日期组件为例进行介绍。

新建类MyLocalizationsDelegate

代码语言:javascript复制
class MyLocalizationsDelegate
    extends LocalizationsDelegate<CupertinoLocalizations> {
  const MyLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) => locale.languageCode == 'zh';

  @override
  Future<CupertinoLocalizations> load(Locale locale) =>
      ZhCupertinoLocalizations.load(locale);

  @override
  bool shouldReload(MyLocalizationsDelegate old) => false;

  @override
  String toString() => 'DefaultCupertinoLocalizations.delegate(zh)';
}

ZhCupertinoLocalizations定义如下:

代码语言:javascript复制
class ZhCupertinoLocalizations implements CupertinoLocalizations {
  const ZhCupertinoLocalizations();

  static const List<String> _shortWeekdays = <String>[
    '自周一',
    '自周二',
    '自周三',
    '自周四',
    '自周五',
    '自周六',
    '自周日',
  ];

  static const List<String> _shortMonths = <String>[
    '1月',
    '2月',
    '3月',
    '4月',
    '5月',
    '6月',
    '7月',
    '8月',
    '9月',
    '10月',
    '11月',
    '12月',
  ];

  static const List<String> _months = <String>[
    '1月',
    '2月',
    '3月',
    '4月',
    '5月',
    '6月',
    '7月',
    '8月',
    '9月',
    '10月',
    '11月',
    '12月',
  ];

  @override
  String datePickerYear(int yearIndex) => yearIndex.toString();

  @override
  String datePickerMonth(int monthIndex) => _months[monthIndex - 1];

  @override
  String datePickerDayOfMonth(int dayIndex) => dayIndex.toString();

  @override
  String datePickerHour(int hour) => hour.toString();

  @override
  String datePickerHourSemanticsLabel(int hour) => hour.toString()   " o'clock";

  @override
  String datePickerMinute(int minute) => minute.toString().padLeft(2, '0');

  @override
  String datePickerMinuteSemanticsLabel(int minute) {
    if (minute == 1) return '1 分';
    return minute.toString()   ' 分';
  }

  @override
  String datePickerMediumDate(DateTime date) {
    return '${_shortWeekdays[date.weekday - DateTime.monday]} '
        '${_shortMonths[date.month - DateTime.january]} '
        '${date.day.toString().padRight(2)}';
  }

  @override
  DatePickerDateOrder get datePickerDateOrder => DatePickerDateOrder.mdy;

  @override
  DatePickerDateTimeOrder get datePickerDateTimeOrder =>
      DatePickerDateTimeOrder.date_time_dayPeriod;

  @override
  String get anteMeridiemAbbreviation => '上午';

  @override
  String get postMeridiemAbbreviation => '下午';

  @override
  String get todayLabel => '今天';

  @override
  String get alertDialogLabel => 'Alert';

  @override
  String timerPickerHour(int hour) => hour.toString();

  @override
  String timerPickerMinute(int minute) => minute.toString();

  @override
  String timerPickerSecond(int second) => second.toString();

  @override
  String timerPickerHourLabel(int hour) => hour == 1 ? '小时' : '小时';

  @override
  String timerPickerMinuteLabel(int minute) => '分.';

  @override
  String timerPickerSecondLabel(int second) => '秒.';

  @override
  String get cutButtonLabel => '剪贴';

  @override
  String get copyButtonLabel => '拷贝';

  @override
  String get pasteButtonLabel => '黏贴';

  @override
  String get selectAllButtonLabel => '选择全部';

  static Future<CupertinoLocalizations> load(Locale locale) {
    return SynchronousFuture<CupertinoLocalizations>(
        const ZhCupertinoLocalizations());
  }

  /// A [LocalizationsDelegate] that uses [DefaultCupertinoLocalizations.load]
  /// to create an instance of this class.
  static const LocalizationsDelegate<CupertinoLocalizations> delegate =
      MyLocalizationsDelegate();
}

注意开始的属性_shortWeekdays,这个属性表示星期几,故意写成'自周x',为了和系统的区分,在根控件MaterialApplocalizationsDelegates属性中增加:ZhCupertinoLocalizations.delegate,这个就是上面定义的国际化文件,效果如下:

注意:ZhCupertinoLocalizations.delegate要放在GlobalCupertinoLocalizations.delegate,的前面,系统加载顺序为从上到下。

效果如下:

0 人点赞