How can I add a localizationsDelegate form another package that uses "EasyLocalization"?

60 Views Asked by At

I have a package that uses the EasyLocalization package for localization, and I want to add localizationsDelegate of this package to my main project.

I know that I can add something like this with flutter_intl package to pubspec.yaml:

flutter_intl:
  main_locale: en
  enabled: true
  class_name: MyPackageLocalization

And add the MyPackageLocalization.delegate to my localizationsDelegates inside the MaterialApp:

...
MaterialApp(
  localizationsDelegates: [
    ...context.localizationDelegates,
    MyPackageLocalization.delegate,
  ],
  supportedLocales: context.supportedLocales,
...

But, how can I do it with the EasyLocalization package?

1

There are 1 best solutions below

0
Hamed On BEST ANSWER

I found the solution, first of all, we need to define a MultiTranslationAssetLoader class:

class MultiTranslationAssetLoader extends AssetLoader {
  const MultiTranslationAssetLoader(this.loaders);

  final List<dynamic> loaders;

  @override
  Future<Map<String, dynamic>> load(String path, Locale locale) async {
    final result = <String, dynamic>{};
    final loaderFutures = <Future<Map<String, dynamic>?>>[];

    for (final loader in loaders) {
      loaderFutures.add(loader.load(path, locale));
    }

    (await Future.wait(loaderFutures))
        .whereNotNull()
        .forEach(result.addAllRecursive);

    return result;
  }
}

extension _MapExtension<K> on Map<K, dynamic> {
  void addAllRecursive(Map<K, dynamic> other) {
    for (final entry in other.entries) {
      final oldValue = this[entry.key];
      final newValue = entry.value;

      if (oldValue is Map<K, dynamic> && newValue is Map<K, dynamic>) {
        oldValue.addAllRecursive(newValue);

        continue;
      }

      this[entry.key] = newValue;
    }
  }
}

Then we can use it as follows:

runApp(
  EasyLocalization(
    supportedLocales: const <Locale>[
      Locale('en'),
    ],
    fallbackLocale: const Locale('en'),
    assetLoader: const MultiTranslationAssetLoader(
      [
        TranslationsLoader(),
        TranslationsLoader(packageName: 'package_example'),
      ],
    ),
    path: 'lib/l10n/translations',
    child: const MainApp(),
  ),
);

Here is a sample implementation of TranslationsLoader:

class TranslationsLoader extends AssetLoader {
  const TranslationsLoader({this.packageName});

  final String? packageName;

  @override
  Future<Map<String, dynamic>?> load(String path, Locale locale) =>
      _getMapLocales(locale);

  Future<Map<String, dynamic>> _getMapLocales(Locale locale) async {
    String getPath({Locale locale = const Locale('en')}) =>
        '${packageName != null ? 'packages/$packageName/' : ''}lib/l10n/translations/$locale.json';

    try {
      return jsonDecode(await rootBundle.loadString(getPath(locale: locale)));
    } catch (e) {
      return jsonDecode(await rootBundle.loadString(getPath()));
    }
  }
}

This article helped me to solve this problem:

How to localize packages with easy_localization