flutter

Flutter Packages and Localization

Internationalizing Flutter apps is pretty simple and straightforward as documented in the official website. But there is no clear documentation about localizing a Flutter packages and adding support for more language if package does not support them or overriding default translations. However the the process is same with some minor differences.

You may know generating localization creates a LocalizationsDelegate which we have to use in the MaterialApp. We need same for our package. We generate the delegate and use it the app.

In the Package

This localization configuration ensures that the generated files are available in the source code inside src folder and can be exported. l10n.yaml file will look like this.

arb-dir: lib/src/l10n
output-dir: lib/src/l10n/generated
synthetic-package: false
template-arb-file: intl_en.arb
output-localization-file: awesome_package_localizations.dart
output-class: AwesomePackageLocalization
nullable-getter: false
untranslated-messages-file: lib/src/l10n/untranslated.txt

Now go ahead and edit intl_en.arb located at lib/src/l10n. Also add translations for other languages that are supported by the package.

To generate localization files use flutter gen-l10n. It will also generate localization delegate.

Now export awesome_package_localizations.dart file which is generated. And that is all you need to add localization support in you Flutter package. Next thing is how to use them in an app.

In the App

We just have to use the delegate generated in the package in the MaterialApp.

return MaterialApp.router(
  title: My App',
  localizationsDelegates: const [
    ...AppLocalizations.localizationsDelegates,
    AwesomePackageLocalization.delegate, // this
  ],
  locale: Locale(LocaleService.instance.appLanguage.languageCode),
  supportedLocales: const [
    Locale('en'),
    Locale('fr'),
  ],
);

If the package does not support the locales that the app has listed as supported then it will show a warning and eventually throw an error on runtime.

So what if the package you use doesn’t support locale you need in your app?

Overriding Localization or Adding Support for New Language

Sometimes a package you are using may not provide localization for the language you needed in you app or the translations should be changed. Let’s assume awesome package does not support French and you need to add support for it without updating the package.

I would like to describe it in 3 steps as follow.

Translation

Create a localization for French language by extending AwesomePackageLocalization (generated in the package).

class AwesomePackageLocalizationFr extends AwesomePackageLocalization {
  AwesomePackageLocalizationFr(super.locale);

  @override
  String get hi => 'Salut';

  @override
  String get thankYou => 'Merci';
}

Delegate

Now create a delegate to load AwesomePackageLocalizationFr.

import 'package:intl/intl.dart' as intl;

class AwesomePackageLocalizationFrDelegate
   extends LocalizationsDelegate<AwesomePackageLocalization> {
 const AwesomePackageLocalizationFrDelegate();

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

 @override
 Future<AwesomePackageLocalization> load(Locale locale) {
   final languageCode = intl.Intl.canonicalizedLocale(locale.toString());

   return SynchronousFuture<AwesomePackageLocalization>(
     AwesomePackageLocalizationFr(languageCode),
   );
 }

 @override
 bool shouldReload(LocalizationsDelegate<AwesomePackageLocalization> old) => true;
}

Usage

To use it you can add delegate in the MaterialApp and now your app runs fine with French language even though the package did not support French originally.

return MaterialApp.router(
  title: My App',
  localizationsDelegates: const [
    ...AppLocalizations.localizationsDelegates,
    // to be able to override default value from AwesomePackageLocalization
    // this delegate must be before it because only the first delegate of each 
    // [LocalizationsDelegate.type] is used.
    AwesomePackageLocalizationNeDelegate(),
    AwesomePackageLocalization.delegate,
  ],
  locale: Locale(LocaleService.instance.appLanguage.languageCode),
  supportedLocales: const [
    Locale('en'),
    Locale('fr'),
  ],
);

That was all for adding a new language or overriding the default one. You need to make sure if you want to override a language the delegate must be before the default one.

Thanks for reading.

Leave a Comment

Your email address will not be published. Required fields are marked *