diff --git a/example/lib/main.dart b/example/lib/main.dart index 53bc748f..73725046 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -23,6 +23,7 @@ void main() async { // startLocale: Locale('de', 'DE'), // saveLocale: false, // useOnlyLangCode: true, + forcePluralCaseFallback: true, // optional assetLoader default used is RootBundleAssetLoader which uses flutter's assetloader // install easy_localization_loader for enable custom loaders diff --git a/example/resources/langs/en-US.json b/example/resources/langs/en-US.json index 7cee30b5..5a717468 100644 --- a/example/resources/langs/en-US.json +++ b/example/resources/langs/en-US.json @@ -11,12 +11,10 @@ } }, "clicked": { - "zero": "You clicked {} times!", - "one": "You clicked {} time!", - "two": "You clicked {} times!", - "few": "You clicked {} times!", - "many": "You clicked {} times!", - "other": "You clicked {} times!" + "zero": "You didn't click yet!", + "few": "You clicked a few times ({})!", + "many": "You clicked many times ({})!", + "other": "You clicked {} time(s)!" }, "amount": { "zero": "Your amount : {} ", diff --git a/lib/src/easy_localization_app.dart b/lib/src/easy_localization_app.dart index 0a49e9a0..f6e5baab 100644 --- a/lib/src/easy_localization_app.dart +++ b/lib/src/easy_localization_app.dart @@ -63,6 +63,21 @@ class EasyLocalization extends StatefulWidget { /// ``` final bool useFallbackTranslationsForEmptyResources; + /// Force use of plural strings for all languages. This will still fallback + /// to "other" if the specific rule isn't defined. + /// @Default value false + /// Example: + /// ``` + /// // Default behavior, will use "zero" rule for 0 only if the language + /// // is set to do so (e.g. for "lt" but not for "en"). + /// forcePluralCaseFallback: false + /// // Force using "zero" rule for 0 even if the language doesn't use it + /// // by default (e.g. "en"). If "zero" localization for that string + /// // doesn't exist, "other" is still used as fallback. + /// forcePluralCaseFallback: true + /// ``` + final bool forcePluralCaseFallback; + /// Path to your folder with localization files. /// Example: /// ```dart @@ -117,6 +132,7 @@ class EasyLocalization extends StatefulWidget { this.useOnlyLangCode = false, this.useFallbackTranslations = false, this.useFallbackTranslationsForEmptyResources = false, + this.forcePluralCaseFallback = false, this.assetLoader = const RootBundleAssetLoader(), this.extraAssetLoaders, this.saveLocale = true, @@ -198,6 +214,7 @@ class _EasyLocalizationState extends State { supportedLocales: widget.supportedLocales, useFallbackTranslationsForEmptyResources: widget.useFallbackTranslationsForEmptyResources, + forcePluralCaseFallback: widget.forcePluralCaseFallback, ), ); } @@ -243,6 +260,7 @@ class _EasyLocalizationProvider extends InheritedWidget { /// Get fallback locale Locale? get fallbackLocale => parent.fallbackLocale; + // Locale get startLocale => parent.startLocale; /// Change app locale @@ -278,12 +296,14 @@ class _EasyLocalizationDelegate extends LocalizationsDelegate { final List? supportedLocales; final EasyLocalizationController? localizationController; final bool useFallbackTranslationsForEmptyResources; + final bool forcePluralCaseFallback; /// * use only the lang code to generate i18n file path like en.json or ar.json // final bool useOnlyLangCode; _EasyLocalizationDelegate({ required this.useFallbackTranslationsForEmptyResources, + this.forcePluralCaseFallback = false, this.localizationController, this.supportedLocales, }) { @@ -306,6 +326,7 @@ class _EasyLocalizationDelegate extends LocalizationsDelegate { fallbackTranslations: localizationController!.fallbackTranslations, useFallbackTranslationsForEmptyResources: useFallbackTranslationsForEmptyResources, + forcePluralCaseFallback: forcePluralCaseFallback, ); return Future.value(Localization.instance); } diff --git a/lib/src/localization.dart b/lib/src/localization.dart index b153e5b1..463bf816 100644 --- a/lib/src/localization.dart +++ b/lib/src/localization.dart @@ -20,11 +20,14 @@ class Localization { }; bool _useFallbackTranslationsForEmptyResources = false; + bool _forcePluralCaseFallback = false; Localization(); static Localization? _instance; + static Localization get instance => _instance ?? (_instance = Localization()); + static Localization? of(BuildContext context) => Localizations.of(context, Localization); @@ -33,12 +36,14 @@ class Localization { Translations? translations, Translations? fallbackTranslations, bool useFallbackTranslationsForEmptyResources = false, + bool forcePluralCaseFallback = false, }) { instance._locale = locale; instance._translations = translations; instance._fallbackTranslations = fallbackTranslations; instance._useFallbackTranslationsForEmptyResources = useFallbackTranslationsForEmptyResources; + instance._forcePluralCaseFallback = forcePluralCaseFallback; return translations == null ? false : true; } @@ -114,6 +119,9 @@ class Localization { } static PluralRule? _pluralRule(String? locale, num howMany) { + if (instance._forcePluralCaseFallback) { + return () => _pluralCaseFallback(howMany); + } startRuleEvaluation(howMany); return pluralRules[locale]; } @@ -139,11 +147,11 @@ class Localization { String? name, NumberFormat? format, }) { - late String res; final pluralRule = _pluralRule(_locale.languageCode, value); - final pluralCase = pluralRule != null ? pluralRule() : _pluralCaseFallback(value); + final pluralCase = + pluralRule != null ? pluralRule() : _pluralCaseFallback(value); switch (pluralCase) { case PluralCase.ZERO: @@ -186,7 +194,8 @@ class Localization { if (subKey == 'other') return _resolve('$key.other'); final tag = '$key.$subKey'; - var resource = _resolve(tag, logging: false, fallback: _fallbackTranslations != null); + var resource = + _resolve(tag, logging: false, fallback: _fallbackTranslations != null); if (resource == tag) { resource = _resolve('$key.other'); }