Open4

Flutterで多言語対応していく(検討中)

koji-1009koji-1009

Flutterの多言語対応については公式ドキュメントが詳しい。

https://docs.flutter.dev/development/accessibility-and-localization/internationalization

のだけれども、どうにも AppLocalizations を使いたくないという気持ちが出てしまう。
また自分が普段使っているマイクロサービス化された開発だと、統合するアプリケーションでは利用できても、ライブラリ化された箇所では利用できなかったりする。

koji-1009koji-1009

半ば実験中なのだけれども、Riverpodを使って多言語対応させる方法を書いてみる。


文字列を入力するファイルを作る。
ベースを localization.dart とし、日本語のデータを追加するファイルを localization_ja.dart とでもすることにする。

localization.dart

part 'localization_ja.dart';

class Localization {
  const Localization({
    required this.appName,
  });

  final String appName;
}

localizaziton_ja.dart

part of 'localization.dart';

const _ja = Localization(
  appName: 'アプリケーション',
);

あとは、これを Provider を使って配布できるようにするだけ。

import 'package:hooks_riverpod/hooks_riverpod.dart';

final localizationProvider = Provider(
  (ref) => _ja,
);

同一ファイルなので、 _ をつけてprivateにすることができる。


この対応をすることで、あとはProviderで Locale を配布することができれば、自動的に表示される文字列が切り替わるようになる。

localization_en.dart として英語の文字列を管理するファイルを追加する。

localization_en.dart

part of 'localization.dart';

const _en = Localization(
  appName: 'Application',
);

あとは、次のProviderが動くようにすれば良い。

final localizationProvider = Provider(
  (ref) {
    final locale = ref.watch(localeProvider);
    if (locale.languageCode == 'ja') {
      return _ja;
    }

    return _en;
  },
);
koji-1009koji-1009

Riverpodで Locale を配布する方法はいくつかあるようなので、それを参照すれば良い。
今回の場合、アプリケーションに与える文字列をいじってしまっているので、ちょっとだけ工夫が必要になってくる。

今試しているのは下記のような実装。


まず、 LocaleStateProvider で配布しておく。

import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

const kDefaultLocale = Locale('en');

final localeProvider = StateProvider(
  (ref) => kDefaultLocale,
);

続いて MaterialApp に次の実装を追加しておく。

MaterialApp(
  localeResolutionCallback: (locale, supportedLocales) {
    final languageCodes = supportedLocales.map((e) => e.languageCode);
    if (locale != null) {
      if (languageCodes.contains(locale.languageCode)) {
        WidgetsBinding.instance.addPostFrameCallback((_) {
          ref.read(localeProvider.notifier).state = locale;
        });

        return locale;
      }
    }

    WidgetsBinding.instance.addPostFrameCallback((_) {
      ref.read(localeProvider.notifier).state = kDefaultLocale;
    });

    return kDefaultLocale;
  },
~~~
);

これで、先ほど作った localizationProvider の中身が切り替わるようになる。

koji-1009koji-1009

クラッシュの危険とか、パフォーマンスの問題とかあるかもとは思っているで、色々と調査をしていきたい。