Flutter-IntlのFlutterと連動した多言語対応

IntlのFlutterでの多言語対応について。

Intlの例えばDateFormatの書式指定をきちんと日本語対応したものにしたいなど、Flutterとどのように連携させればいいのかちょっと記述する。

Intlについて

Flutter/Dartの国際化およびローカリゼーション機能を提供しているパッケージで、Localeクラスを指定することにより、多言語メッセージへの対応、数値、日付等の書式設定ができる機能を持っている。

intl | Dart package
Contains code to deal with internationalized/localized messages, date and number formatting and parsing, bi-directional ...

Localeを特に指定しない場合は「en_US」が設定されているものとして処理されるため、他の言語を使用する場合は、正しく設定もしくは利用する必要がある。

使用される言語設定の方法

基本的に、DateFormatやNumberFormatの書式指定クラスにはパラメータとしてLocaleを指定することができるようになっている。

また指定しない場合は「Intl.defaultLocale」のSTATICプロパティに設定されている言語設定が使われる。

FlutterでIntlの言語指定

対応方法としては大まかに2種類ある。

  • MaterialLocalizationsを利用する方法
  • Intl.defaultLocaleを変更する方法

MaterialLocalizationsを利用する方法

こちらはIntlを直接利用する方法ではないのだけど、DateFormatのいくつかの書式設定とNumberFormat. decimalPatternがメソッドとして用意されていて、それぞれがアプリケーション内で使用する場合、利用する言語環境のものが使用できるようになっている。

以下がそれの対応表。

MaterialLocalizations Intl
formatYear DateFormat.y
formatCompactDate DateFormat.yMD
formatShortDate DateFormat.yMMMD
formatMediumDate DateFormat.MMMEd
formatFullDate DateFormat.yMMMMEEEEd
formatMonthYear DateFormat.yMMMM
formatShortMonthDay DateFormat.MMMd
formatDecimal NumberFormat. decimalPattern

ウィジェットのビルド時に、MaterialLocalizations.of(context)でインスタンスを取り出し、該当するメソッドを利用する。特殊な書式でなければこれでいいのではないかと思う。

これを使用するには、MaterialAppのlocalizationsDelegatesにGlobalMaterialLocalizations.delegateを追加登録する必要がある。

Intl.defaultLocaleを変更する方法

Androidの言語設定で、英語、日本語等に変更した場合、Intl.defaultLocaleが何もしなくても連動してくれればいいのだけども、そういうことはなく、自分で実装しなければいけない。

ただIntl.defaultLocaleを変更すれば、DateFormatのフォーマッタをそのまま呼び出し利用することができるので便利だとは思う。

具体的な実装としてはIntl.defaultLocaleを変更するLocalizationsDelegateを作り、それをMaterialAppのlocalizationsDelegatesに指定する。

それが以下のクラス。

class IntlDelegate extends LocalizationsDelegate {
  @override
  bool isSupported(Locale locale) {
    return true;
  }

  @override
  Future load(Locale locale) {
    Intl.defaultLocale = locale.toString();
    return Future(() {});
  }

  @override
  bool shouldReload(covariant LocalizationsDelegate old) {
    return false;
  }
}

言語の切り替えが行われた場合、loadが呼び出されるのでIntl.defaultLocaleを変更し何もしないFutureを返している。

本来LocalizationsDelegateはジェネリッククラスなので何かクラスを指定する必要があるかもしれないけど、とりあえず動作しているのでいいかな?

補足 ローカライゼーションインスタンスを用意する方法

MaterialLocalizationsもしくはCupertinoLocalizationsみたいなものを自前で用意するにはどうするのか。

MaterialLocalizations class - material library - Dart API
API docs for the MaterialLocalizations class from the material library, for the Dart programming language.

クラス構成としては以下の様になると思う。

PlantUML Syntax:<br />
class ILocalizations<br />
class GlobalLocalizations implements ILocalizations {<br />
LocalizationsDelegate<ILocalizations> delegate;<br />
}<br />
class DefaultLocalizations implements ILocalizations<br />
class LocalizationsDelegate<T><br />
class _ILocalizationsDelegate extends LocalizationsDelegate<br />
_ILocalizationsDelegate *- ILocalizations : T<br />
GlobalLocalizations *- _ILocalizationsDelegate : delegate<br />

  • ILocalizations
    リソースを提供するベースとするインターフェースクラス。
  • DefaultLocalizations
    多言語対応が行えるILocalizationsの実装で、delegateメンバでMaterialAppに渡すためのLocalizationsDelegateを渡せるようにしている。
  • GlobalLocalizations
    US Englishの情報を固定値として取り出せるようにしているILocalizationsの実装。
  • _ILocalizationsDelegat
    MaterialAppに渡すLocalizationsDelegateの実装。

上記クラスを用意することで、ILocalizations.of(context)でILocalizationsのインスタンスが取得できるので、保持する多言語版のリソース情報を取得できる。

詳細の実装についてはMaterialLocalizations、CupertinoLocalizationsを参考にすると良いと思う。
それほど難しくないし。

コメント

タイトルとURLをコピーしました