🌏

【Flutter】RiverpodのProviderでL10nを扱う

2023/02/12に公開

はじめに

L10n対応する際に、View側のコードにどうしてもロジック部分を書かざる得ないということがあります。
そこで、ロジック部分を書くファイル内でもL10nを使用するために、RiverpodのProviderを使用して実装する方法をご紹介したいと思います。

今回の記事では、L10nを適用する方法は説明しないので、そこが分からない方は以下の記事を参考にしてみてください。
https://zenn.dev/reinf0rce/articles/618938598fc4dd

結論

app_localition_provider.dart
import 'dart:ui' as ui;

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

import 'app_localization.dart';

final appLocalizationProvider = Provider<AppLocalization>((ref) {
  ref.state = lookupAppLocalization(ui.window.locale); // デフォルトのL10n
  final observer = _LocaleObserver((locales) {
    ref.state = lookupAppLocalization(ui.window.locale); // 設定した言語のL10nに更新する
  });
  final binding = WidgetsBinding.instance;
  binding.addObserver(observer); // 言語切替検知の開始
  ref.onDispose(() => binding.removeObserver(observer));
  return ref.state;
});

/// 言語切替を検知するためのオブザーバー
class _LocaleObserver extends WidgetsBindingObserver {
  _LocaleObserver(this._didChangeLocales);

  final void Function(List<Locale>? locales) _didChangeLocales;

  
  void didChangeLocales(List<Locale>? locales) {
    _didChangeLocales(locales);
  }
}

使用例

main.dart
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:l10n_with_riverpod_example/l10n/app_localization_provider.dart';

import 'l10n/app_localization.dart';

void main() {
  runApp(
    const ProviderScope(
      child: App(),
    ),
  );
}

class App extends StatelessWidget {
  const App({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HomePage(),
      localizationsDelegates: AppLocalization.localizationsDelegates,
      supportedLocales: AppLocalization.supportedLocales,
    );
  }
}

class HomePage extends ConsumerWidget {
  const HomePage({Key? key}) : super(key: key);

  
  Widget build(BuildContext context, WidgetRef ref) {
    final l10n = ref.watch(appLocalizationProvider);
    return Scaffold(
      body: Center(
        child: Text(l10n.hello),
      ),
    );
  }
}

GitHubにコードをアップしたので気になる方はどうぞ
https://github.com/f-nakahara/l10n-with-riverpod-example

Discussion