diff --git a/lib/src/easy_localization_app.dart b/lib/src/easy_localization_app.dart index 2ce7ec7f..cf2adde2 100644 --- a/lib/src/easy_localization_app.dart +++ b/lib/src/easy_localization_app.dart @@ -153,11 +153,8 @@ class _EasyLocalizationState extends State { useOnlyLangCode: widget.useOnlyLangCode, useFallbackTranslations: widget.useFallbackTranslations, path: widget.path, - onLoadError: (FlutterError e) { - setState(() { - translationsLoadError = e; - }); - }, + onLoadError: (FlutterError e) => + setState(() => translationsLoadError = e), ); // causes localization to rebuild with new language localizationController!.addListener(() { @@ -219,9 +216,12 @@ class _EasyLocalizationProvider extends InheritedWidget { // _EasyLocalizationDelegate get delegate => parent.delegate; - _EasyLocalizationProvider(this.parent, this._localeState, - {Key? key, required this.delegate}) - : currentLocale = _localeState.locale, + _EasyLocalizationProvider( + this.parent, + this._localeState, { + Key? key, + required this.delegate, + }) : currentLocale = _localeState.locale, super(key: key, child: parent.child) { EasyLocalization.logger.debug('Init provider'); } @@ -269,8 +269,10 @@ class _EasyLocalizationDelegate extends LocalizationsDelegate { /// * use only the lang code to generate i18n file path like en.json or ar.json // final bool useOnlyLangCode; - _EasyLocalizationDelegate( - {this.localizationController, this.supportedLocales}) { + _EasyLocalizationDelegate({ + this.localizationController, + this.supportedLocales, + }) { EasyLocalization.logger.debug('Init Localization Delegate'); } @@ -280,13 +282,17 @@ class _EasyLocalizationDelegate extends LocalizationsDelegate { @override Future load(Locale value) async { EasyLocalization.logger.debug('Load Localization Delegate'); - if (localizationController!.translations == null) { + + if (localizationController!.translations.isEmpty) { await localizationController!.loadTranslations(); } - Localization.load(value, - translations: localizationController!.translations, - fallbackTranslations: localizationController!.fallbackTranslations); + Localization.load( + value, + fallbackTranslations: localizationController!.fallbackTranslations, + translations: localizationController!.translations, + ); + return Future.value(Localization.instance); } diff --git a/lib/src/easy_localization_controller.dart b/lib/src/easy_localization_controller.dart index eda3cbe4..df3bed0f 100644 --- a/lib/src/easy_localization_controller.dart +++ b/lib/src/easy_localization_controller.dart @@ -8,24 +8,39 @@ import 'translations.dart'; class EasyLocalizationController extends ChangeNotifier { static Locale? _savedLocale; + static late Locale _deviceLocale; late Locale _locale; + Locale? _fallbackLocale; final Function(FlutterError e) onLoadError; + final AssetLoader assetLoader; + final String path; + + final List supportedLocales; + final bool useFallbackTranslations; + final bool saveLocale; + final bool useOnlyLangCode; + List? extraAssetLoaders; - Translations? _translations, _fallbackTranslations; - Translations? get translations => _translations; + + final Map _allTranslations = {}; + + Map get translations => _allTranslations; + + Translations? _fallbackTranslations; + Translations? get fallbackTranslations => _fallbackTranslations; EasyLocalizationController({ - required List supportedLocales, + required this.supportedLocales, required this.useFallbackTranslations, required this.saveLocale, required this.assetLoader, @@ -77,27 +92,35 @@ class EasyLocalizationController extends ChangeNotifier { //Get fallback Locale static Locale _getFallbackLocale( - List supportedLocales, Locale? fallbackLocale) { - //If fallbackLocale not set then return first from supportedLocales - if (fallbackLocale != null) { - return fallbackLocale; - } else { - return supportedLocales.first; - } + List supportedLocales, + Locale? fallbackLocale, + ) { + return fallbackLocale ?? supportedLocales.first; } Future loadTranslations() async { - Map data; try { - data = Map.from(await loadTranslationData(_locale)); - _translations = Translations(data); + Map> allTranslationData = + await loadAllTranslationData(); + + allTranslationData.forEach((key, value) { + _allTranslations.addAll({key: Translations(value)}); + }); + if (useFallbackTranslations && _fallbackLocale != null) { Map? baseLangData; + if (_locale.countryCode != null && _locale.countryCode!.isNotEmpty) { - baseLangData = - await loadBaseLangTranslationData(Locale(locale.languageCode)); + try { + baseLangData = allTranslationData[Locale(locale.languageCode)]; + } on FlutterError catch (e) { + // Disregard asset not found FlutterError when attempting to load base language fallback + EasyLocalization.logger.warning(e.message); + } } - data = Map.from(await loadTranslationData(_fallbackLocale!)); + + Map data = allTranslationData[_fallbackLocale]!; + if (baseLangData != null) { try { data.addAll(baseLangData); @@ -105,6 +128,7 @@ class EasyLocalizationController extends ChangeNotifier { data = Map.of(data)..addAll(baseLangData); } } + _fallbackTranslations = Translations(data); } } on FlutterError catch (e) { @@ -114,17 +138,6 @@ class EasyLocalizationController extends ChangeNotifier { } } - Future?> loadBaseLangTranslationData( - Locale locale) async { - try { - return await loadTranslationData(Locale(locale.languageCode)); - } on FlutterError catch (e) { - // Disregard asset not found FlutterError when attempting to load base language fallback - EasyLocalization.logger.warning(e.message); - } - return null; - } - Future> loadTranslationData(Locale locale) async => _combineAssetLoaders( path: path, @@ -134,6 +147,22 @@ class EasyLocalizationController extends ChangeNotifier { extraAssetLoaders: extraAssetLoaders, ); + Future>> loadAllTranslationData() async { + Map> data = {}; + + for (final locale in supportedLocales) { + data[locale] = await _combineAssetLoaders( + path: path, + locale: locale, + assetLoader: assetLoader, + useOnlyLangCode: useOnlyLangCode, + extraAssetLoaders: extraAssetLoaders, + ); + } + + return data; + } + Future> _combineAssetLoaders({ required String path, required Locale locale, @@ -141,8 +170,8 @@ class EasyLocalizationController extends ChangeNotifier { required bool useOnlyLangCode, List? extraAssetLoaders, }) async { - final result = {}; - final loaderFutures = ?>>[]; + final Map result = {}; + final List?>> loaderFutures = []; final Locale desiredLocale = useOnlyLangCode ? Locale(locale.languageCode) : locale; @@ -169,12 +198,12 @@ class EasyLocalizationController extends ChangeNotifier { Locale get locale => _locale; - Future setLocale(Locale l) async { - _locale = l; + Future setLocale(Locale locale) async { + _locale = locale; await loadTranslations(); notifyListeners(); EasyLocalization.logger('Locale $locale changed'); - await _saveLocale(_locale); + await _saveLocale(locale); } Future _saveLocale(Locale? locale) async { @@ -215,14 +244,17 @@ extension LocaleExtension on Locale { if (this == locale) { return true; } + if (languageCode != locale.languageCode) { return false; } + if (countryCode != null && countryCode!.isNotEmpty && countryCode != locale.countryCode) { return false; } + if (scriptCode != null && scriptCode != locale.scriptCode) { return false; } diff --git a/lib/src/localization.dart b/lib/src/localization.dart index 57742ee3..d1e273f1 100644 --- a/lib/src/localization.dart +++ b/lib/src/localization.dart @@ -5,14 +5,20 @@ import 'plural_rules.dart'; import 'translations.dart'; class Localization { - Translations? _translations, _fallbackTranslations; + Map? _translations; + + Translations? _fallbackTranslations; + late Locale _locale; final RegExp _replaceArgRegex = RegExp('{}'); + final RegExp _linkKeyMatcher = RegExp(r'(?:@(?:\.[a-z]+)?:(?:[\w\-_|.]+|\([\w\-_|.]+\)))'); + final RegExp _linkKeyPrefixMatcher = RegExp(r'^@(?:\.([a-z]+))?:'); final RegExp _bracketsMatcher = RegExp('[()]'); + final _modifiers = { 'upper': (String? val) => val!.toUpperCase(), 'lower': (String? val) => val!.toLowerCase(), @@ -22,19 +28,22 @@ class Localization { Localization(); static Localization? _instance; - static Localization get instance => _instance ?? (_instance = Localization()); + + static Localization get instance => _instance ??= Localization(); + static Localization? of(BuildContext context) => Localizations.of(context, Localization); static bool load( Locale locale, { - Translations? translations, + Map? translations, Translations? fallbackTranslations, }) { instance._locale = locale; instance._translations = translations; instance._fallbackTranslations = fallbackTranslations; - return translations == null ? false : true; + + return translations != null; } String tr( @@ -42,14 +51,15 @@ class Localization { List? args, Map? namedArgs, String? gender, + Locale? locale, }) { - late String res; - - if (gender != null) { - res = _gender(key, gender: gender); - } else { - res = _resolve(key); - } + late String res = gender == null + ? _resolve(key, locale: locale) + : _gender( + key, + gender: gender, + locale: locale, + ); res = _replaceLinks(res); @@ -58,10 +68,9 @@ class Localization { return _replaceArgs(res, args); } - String _replaceLinks(String res, {bool logging = true}) { + String _replaceLinks(String result, {bool logging = true}) { // TODO: add recursion detection and a resolve stack. - final matches = _linkKeyMatcher.allMatches(res); - var result = res; + final matches = _linkKeyMatcher.allMatches(result); for (final match in matches) { final link = match[0]!; @@ -73,7 +82,7 @@ class Localization { final linkPlaceholder = link.replaceAll(linkPrefix, '').replaceAll(_bracketsMatcher, ''); - var translated = _resolve(linkPlaceholder); + String translated = _resolve(linkPlaceholder); if (formatterName != null) { if (_modifiers.containsKey(formatterName)) { @@ -93,19 +102,23 @@ class Localization { return result; } - String _replaceArgs(String res, List? args) { - if (args == null || args.isEmpty) return res; - for (var str in args) { - res = res.replaceFirst(_replaceArgRegex, str); + String _replaceArgs(String result, List? args) { + if (args == null || args.isEmpty) return result; + + for (final str in args) { + result = result.replaceFirst(_replaceArgRegex, str); } - return res; + + return result; } - String _replaceNamedArgs(String res, Map? args) { - if (args == null || args.isEmpty) return res; + String _replaceNamedArgs(String result, Map? args) { + if (args == null || args.isEmpty) return result; + args.forEach((String key, String value) => - res = res.replaceAll(RegExp('{$key}'), value)); - return res; + result = result.replaceAll(RegExp('{$key}'), value)); + + return result; } static PluralRule? _pluralRule(String? locale, num howMany) { @@ -114,16 +127,12 @@ class Localization { } static PluralCase _pluralCaseFallback(num value) { - switch (value) { - case 0: - return PluralCase.ZERO; - case 1: - return PluralCase.ONE; - case 2: - return PluralCase.TWO; - default: - return PluralCase.OTHER; - } + return switch (value) { + 0 => PluralCase.ZERO, + 1 => PluralCase.ONE, + 2 => PluralCase.TWO, + _ => PluralCase.OTHER, + }; } String plural( @@ -133,84 +142,124 @@ class Localization { Map? namedArgs, String? name, NumberFormat? format, + Locale? locale, }) { - - late String res; - - final pluralRule = _pluralRule(_locale.languageCode, value); - final pluralCase = pluralRule != null ? pluralRule() : _pluralCaseFallback(value); - - switch (pluralCase) { - case PluralCase.ZERO: - res = _resolvePlural(key, 'zero'); - break; - case PluralCase.ONE: - res = _resolvePlural(key, 'one'); - break; - case PluralCase.TWO: - res = _resolvePlural(key, 'two'); - break; - case PluralCase.FEW: - res = _resolvePlural(key, 'few'); - break; - case PluralCase.MANY: - res = _resolvePlural(key, 'many'); - break; - case PluralCase.OTHER: - res = _resolvePlural(key, 'other'); - break; - default: - throw ArgumentError.value(value, 'howMany', 'Invalid plural argument'); - } + Locale keyLocale = locale ?? _locale; + + final pluralRule = _pluralRule(keyLocale.languageCode, value); + final pluralCase = + pluralRule != null ? pluralRule() : _pluralCaseFallback(value); + + late String result = switch (pluralCase) { + PluralCase.ZERO => _resolvePlural( + key: key, + subKey: 'zero', + locale: keyLocale, + ), + PluralCase.ONE => _resolvePlural( + key: key, + subKey: 'one', + locale: keyLocale, + ), + PluralCase.TWO => _resolvePlural( + key: key, + subKey: 'two', + locale: keyLocale, + ), + PluralCase.FEW => _resolvePlural( + key: key, + subKey: 'few', + locale: keyLocale, + ), + PluralCase.MANY => _resolvePlural( + key: key, + subKey: 'many', + locale: keyLocale, + ), + PluralCase.OTHER => _resolvePlural( + key: key, + subKey: 'other', + locale: keyLocale, + ), + }; final formattedValue = format == null ? '$value' : format.format(value); if (name != null) { namedArgs = {...?namedArgs, name: formattedValue}; } - res = _replaceNamedArgs(res, namedArgs); - return _replaceArgs(res, args ?? [formattedValue]); - } + result = _replaceNamedArgs(result, namedArgs); - String _gender(String key, {required String gender}) { - return _resolve('$key.$gender'); + return _replaceArgs(result, args ?? [formattedValue]); } - String _resolvePlural(String key, String subKey) { - if (subKey == 'other') return _resolve('$key.other'); + String _gender( + String key, { + required String gender, + Locale? locale, + }) => + _resolve('$key.$gender', locale: locale); + + String _resolvePlural({ + required String key, + required String subKey, + Locale? locale, + }) { + if (subKey == 'other') return _resolve('$key.other', locale: locale); + + String tag = '$key.$subKey'; + String resource = _resolve( + tag, + logging: false, + fallback: _fallbackTranslations != null, + locale: locale, + ); - final tag = '$key.$subKey'; - var resource = _resolve(tag, logging: false, fallback: _fallbackTranslations != null); if (resource == tag) { - resource = _resolve('$key.other'); + resource = _resolve('$key.other', locale: locale); } + return resource; } - String _resolve(String key, {bool logging = true, bool fallback = true}) { - var resource = _translations?.get(key); + String _resolve( + String key, { + Locale? locale, + bool logging = true, + bool fallback = true, + }) { + String? resource = _getTranslation(locale)?.get(key); + if (resource == null) { if (logging) { EasyLocalization.logger.warning('Localization key [$key] not found'); } + if (_fallbackTranslations == null || !fallback) { return key; - } else { - resource = _fallbackTranslations?.get(key); - if (resource == null) { - if (logging) { - EasyLocalization.logger - .warning('Fallback localization key [$key] not found'); - } - return key; + } + + resource = _fallbackTranslations?.get(key); + + if (resource == null) { + if (logging) { + EasyLocalization.logger + .warning('Fallback localization key [$key] not found'); } + return key; } } + return resource; } - bool exists(String key){ - return _translations?.get(key) != null; + bool exists(String key, [Locale? locale]) => + _getTranslation(locale)?.get(key) != null; + + Translations? _getTranslation([Locale? locale]) { + Locale keyLocale = locale ?? _locale; + + return _translations![keyLocale]; } } diff --git a/lib/src/public.dart b/lib/src/public.dart index ba419496..ed73d76b 100644 --- a/lib/src/public.dart +++ b/lib/src/public.dart @@ -37,17 +37,27 @@ String tr( List? args, Map? namedArgs, String? gender, + Locale? locale, }) { return context != null - ? Localization.of(context)! - .tr(key, args: args, namedArgs: namedArgs, gender: gender) - : Localization.instance - .tr(key, args: args, namedArgs: namedArgs, gender: gender); + ? Localization.of(context)!.tr( + key, + args: args, + namedArgs: namedArgs, + gender: gender, + locale: locale, + ) + : Localization.instance.tr( + key, + args: args, + namedArgs: namedArgs, + gender: gender, + locale: locale, + ); } -bool trExists(String key) { - return Localization.instance - .exists(key); +bool trExists(String key, [Locale? locale]) { + return Localization.instance.exists(key, locale); } /// {@template plural} @@ -108,10 +118,25 @@ String plural( Map? namedArgs, String? name, NumberFormat? format, + Locale? locale, }) { return context != null - ? Localization.of(context)!.plural(key, value, - args: args, namedArgs: namedArgs, name: name, format: format) - : Localization.instance.plural(key, value, - args: args, namedArgs: namedArgs, name: name, format: format); + ? Localization.of(context)!.plural( + key, + value, + args: args, + namedArgs: namedArgs, + name: name, + format: format, + locale: locale, + ) + : Localization.instance.plural( + key, + value, + args: args, + namedArgs: namedArgs, + name: name, + format: format, + locale: locale, + ); } diff --git a/lib/src/public_ext.dart b/lib/src/public_ext.dart index 876099a1..95b1a390 100644 --- a/lib/src/public_ext.dart +++ b/lib/src/public_ext.dart @@ -14,31 +14,35 @@ import 'public.dart' as ez; /// ``` extension TextTranslateExtension on Text { /// {@macro tr} - Text tr( - {List? args, - BuildContext? context, - Map? namedArgs, - String? gender}) => + Text tr({ + List? args, + BuildContext? context, + Map? namedArgs, + String? gender, + Locale? locale, + }) => Text( - ez.tr( - data ?? '', - context: context, - args: args, - namedArgs: namedArgs, - gender: gender, - ), - key: key, - style: style, - strutStyle: strutStyle, - textAlign: textAlign, - textDirection: textDirection, + ez.tr( + data ?? '', + context: context, + args: args, + namedArgs: namedArgs, + gender: gender, locale: locale, - softWrap: softWrap, - overflow: overflow, - textScaleFactor: textScaleFactor, - maxLines: maxLines, - semanticsLabel: semanticsLabel, - textWidthBasis: textWidthBasis); + ), + key: key, + style: style, + strutStyle: strutStyle, + textAlign: textAlign, + textDirection: textDirection, + locale: locale, + softWrap: softWrap, + overflow: overflow, + textScaleFactor: textScaleFactor, + maxLines: maxLines, + semanticsLabel: semanticsLabel, + textWidthBasis: textWidthBasis, + ); /// {@macro plural} Text plural( @@ -48,29 +52,32 @@ extension TextTranslateExtension on Text { Map? namedArgs, String? name, NumberFormat? format, + Locale? locale, }) => Text( - ez.plural( - data ?? '', - value, - context: context, - args: args, - namedArgs: namedArgs, - name: name, - format: format, - ), - key: key, - style: style, - strutStyle: strutStyle, - textAlign: textAlign, - textDirection: textDirection, + ez.plural( + data ?? '', + value, + context: context, + args: args, + namedArgs: namedArgs, + name: name, + format: format, locale: locale, - softWrap: softWrap, - overflow: overflow, - textScaleFactor: textScaleFactor, - maxLines: maxLines, - semanticsLabel: semanticsLabel, - textWidthBasis: textWidthBasis); + ), + key: key, + style: style, + strutStyle: strutStyle, + textAlign: textAlign, + textDirection: textDirection, + locale: locale, + softWrap: softWrap, + overflow: overflow, + textScaleFactor: textScaleFactor, + maxLines: maxLines, + semanticsLabel: semanticsLabel, + textWidthBasis: textWidthBasis, + ); } /// Strings extension method for access to [tr()] and [plural()] @@ -87,8 +94,13 @@ extension StringTranslateExtension on String { String? gender, BuildContext? context, }) => - ez.tr(this, - context: context, args: args, namedArgs: namedArgs, gender: gender); + ez.tr( + this, + context: context, + args: args, + namedArgs: namedArgs, + gender: gender, + ); bool trExists() => ez.trExists(this); @@ -133,12 +145,6 @@ extension BuildContextEasyLocalizationExtension on BuildContext { Future setLocale(Locale val) async => EasyLocalization.of(this)!.setLocale(val); - /// Old Change app locale - @Deprecated( - 'This is the func used in the old version of EasyLocalization. The modern func is `setLocale(val)` . ' - 'This feature was deprecated after v3.0.0') - set locale(Locale val) => EasyLocalization.of(this)!.setLocale(val); - /// Get List of supported locales. List get supportedLocales => EasyLocalization.of(this)!.supportedLocales; diff --git a/lib/src/translations.dart b/lib/src/translations.dart index 6dd89b59..155a0586 100644 --- a/lib/src/translations.dart +++ b/lib/src/translations.dart @@ -1,5 +1,6 @@ class Translations { final Map? _translations; + final Map _nestedKeysCache; Translations(this._translations) : _nestedKeysCache = {}; @@ -13,9 +14,7 @@ class Translations { /// If we failed to find the key as a nested key, then fall back /// to looking it up like normal. - returnValue ??= _translations?[key]; - - return returnValue; + return returnValue ??= _translations?[key]; } String? getNested(String key) { diff --git a/lib/src/utils.dart b/lib/src/utils.dart index b059b954..98cf3984 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -1,34 +1,5 @@ part of 'easy_localization_app.dart'; -/// Convert string locale [localeString] to [Locale] -@Deprecated('Deprecated on Easy Localization 3.0') -Locale localeFromString(String localeString) { - final localeList = localeString.split('_'); - switch (localeList.length) { - case 2: - return localeList.last.length == 4 // scriptCode length is 4 - ? Locale.fromSubtags( - languageCode: localeList.first, - scriptCode: localeList.last, - ) - : Locale(localeList.first, localeList.last); - case 3: - return Locale.fromSubtags( - languageCode: localeList.first, - scriptCode: localeList[1], - countryCode: localeList.last, - ); - default: - return Locale(localeList.first); - } -} - -/// Convert [locale] to Srting with custom [separator] -@Deprecated('Deprecated on Easy Localization 3.0') -String localeToString(Locale locale, {String separator = '_'}) { - return locale.toString().split('_').join(separator); -} - /// [Easy Localization] locale helper extension LocaleToStringHelper on Locale { /// Convert [locale] to String with custom separator @@ -42,23 +13,20 @@ extension StringToLocaleHelper on String { /// Convert string to [Locale] object Locale toLocale({String separator = '_'}) { final localeList = split(separator); - switch (localeList.length) { - case 2: - return localeList.last.length == 4 // scriptCode length is 4 - ? Locale.fromSubtags( - languageCode: localeList.first, - scriptCode: localeList.last, - ) - : Locale(localeList.first, localeList.last); - case 3: - return Locale.fromSubtags( + return switch (localeList.length) { + 2 => localeList.last.length == 4 // scriptCode length is 4 + ? Locale.fromSubtags( + languageCode: localeList.first, + scriptCode: localeList.last, + ) + : Locale(localeList.first, localeList.last), + 3 => Locale.fromSubtags( languageCode: localeList.first, scriptCode: localeList[1], countryCode: localeList.last, - ); - default: - return Locale(localeList.first); - } + ), + _ => Locale(localeList.first), + }; } } diff --git a/lib/src/widgets.dart b/lib/src/widgets.dart index 0993a1a6..b12375bd 100644 --- a/lib/src/widgets.dart +++ b/lib/src/widgets.dart @@ -1,41 +1,51 @@ import 'package:flutter/material.dart'; class FutureErrorWidget extends StatelessWidget { - final String msg; - const FutureErrorWidget({Key? key, this.msg = 'Loading ...'}) - : super(key: key); + final String massage; + + const FutureErrorWidget({ + super.key, + this.massage = 'Loading ...', + }); + @override Widget build(BuildContext context) { return Container( color: Colors.white, - child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon( - Icons.error_outline, - color: Colors.red, - size: 64, - textDirection: TextDirection.ltr, - ), - const SizedBox(height: 20), - const Text( - 'Easy Localization:', - textAlign: TextAlign.center, - textDirection: TextDirection.ltr, - style: TextStyle( - fontWeight: FontWeight.w700, color: Colors.red, fontSize: 25.0), - ), - const SizedBox(height: 10), - Text( - '"$msg"', - textAlign: TextAlign.center, - textDirection: TextDirection.ltr, - style: const TextStyle( - fontWeight: FontWeight.w500, color: Colors.red, fontSize: 14.0), - ), - const SizedBox(height: 30), - // Center( - // child: CircularProgressIndicator() - // ), - ]), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.error_outline, + color: Colors.red, + size: 64, + textDirection: TextDirection.ltr, + ), + const SizedBox(height: 20), + const Text( + 'Easy Localization:', + textAlign: TextAlign.center, + textDirection: TextDirection.ltr, + style: TextStyle( + fontWeight: FontWeight.w700, + color: Colors.red, + fontSize: 25.0, + ), + ), + const SizedBox(height: 10), + Text( + '"$massage"', + textAlign: TextAlign.center, + textDirection: TextDirection.ltr, + style: const TextStyle( + fontWeight: FontWeight.w500, + color: Colors.red, + fontSize: 14.0, + ), + ), + const SizedBox(height: 30), + ], + ), ); } } diff --git a/pubspec.yaml b/pubspec.yaml index 45fe0b03..0b9d4ef7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,27 +1,25 @@ name: easy_localization description: Easy and Fast internationalizing and localization your Flutter Apps, this package simplify the internationalizing process . -# author: AISSAT abdelwahab homepage: https://github.com/aissat/easy_localization issue_tracker: https://github.com/aissat/easy_localization/issues -# publish_to: none version: 3.0.5 environment: - sdk: '>=2.12.0 <4.0.0' + sdk: ">=3.3.0 <4.0.0" dependencies: flutter: sdk: flutter - shared_preferences: '>=2.0.0 <3.0.0' - intl: '>=0.17.0-0 <=0.19.0' - args: ^2.3.1 - path: ^1.8.1 - easy_logger: ^0.0.2 flutter_localizations: sdk: flutter + shared_preferences: ">=2.2.3" + intl: ">=0.18.0" + args: ^2.5.0 + path: ^1.9.0 + easy_logger: ^0.0.2 dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.1 + flutter_lints: ^3.0.2 diff --git a/test/easy_localization_language_specific_test.dart b/test/easy_localization_language_specific_test.dart index 2dce5467..d1cc96f6 100644 --- a/test/easy_localization_language_specific_test.dart +++ b/test/easy_localization_language_specific_test.dart @@ -8,58 +8,71 @@ import 'package:flutter_test/flutter_test.dart'; import 'utils/test_asset_loaders.dart'; void main() { - group('language-specific-plurals', () { - var r = EasyLocalizationController( - forceLocale: const Locale('fb'), - supportedLocales: [const Locale('en'), const Locale('ru'), const Locale('fb')], - fallbackLocale: const Locale('fb'), - path: 'path', - useOnlyLangCode: true, - useFallbackTranslations: true, - onLoadError: (FlutterError e) { - log(e.toString()); - }, - saveLocale: false, - assetLoader: const JsonAssetLoader()); + group('language-specific-plurals', () { + var r = EasyLocalizationController( + forceLocale: const Locale('fb'), + supportedLocales: [ + const Locale('en'), + const Locale('ru'), + const Locale('fb') + ], + fallbackLocale: const Locale('fb'), + path: 'path', + useOnlyLangCode: true, + useFallbackTranslations: true, + onLoadError: (FlutterError e) { + log(e.toString()); + }, + saveLocale: false, + assetLoader: const JsonAssetLoader()); - setUpAll(() async { - await r.loadTranslations(); - - }); + setUpAll(() async { + await r.loadTranslations(); + }); - test('english one', () async { - Localization.load(const Locale('en'), - translations: r.translations, - fallbackTranslations: r.fallbackTranslations); - expect(Localization.instance.plural('hat', 1), 'one hat'); - }); - test('english other', () async { - Localization.load(const Locale('en'), - translations: r.translations, - fallbackTranslations: r.fallbackTranslations); - expect(Localization.instance.plural('hat', 2), 'other hats'); - expect(Localization.instance.plural('hat', 0), 'other hats'); - expect(Localization.instance.plural('hat', 3), 'other hats'); - }); - test('russian one', () async { - Localization.load(const Locale('ru'), - translations: r.translations, - fallbackTranslations: r.fallbackTranslations); - expect(Localization.instance.plural('hat', 1), 'one hat'); - }); - test('russian few', () async { - Localization.load(const Locale('ru'), - translations: r.translations, - fallbackTranslations: r.fallbackTranslations); - expect(Localization.instance.plural('hat', 2), 'few hats'); - expect(Localization.instance.plural('hat', 3), 'few hats'); - }); - test('russian many', () async { - Localization.load(const Locale('ru'), - translations: r.translations, - fallbackTranslations: r.fallbackTranslations); - expect(Localization.instance.plural('hat', 0), 'many hats'); - expect(Localization.instance.plural('hat', 5), 'many hats'); - }); + test('english one', () async { + Localization.load( + const Locale('en'), + translations: r.translations, + fallbackTranslations: r.fallbackTranslations, + ); + expect(Localization.instance.plural('hat', 1), 'one hat'); + }); + test('english other', () async { + Localization.load( + const Locale('en'), + translations: r.translations, + fallbackTranslations: r.fallbackTranslations, + ); + expect(Localization.instance.plural('hat', 2), 'other hats'); + expect(Localization.instance.plural('hat', 0), 'other hats'); + expect(Localization.instance.plural('hat', 3), 'other hats'); + }); + test('russian one', () async { + Localization.load( + const Locale('ru'), + translations: r.translations, + fallbackTranslations: r.fallbackTranslations, + ); + expect(Localization.instance.plural('hat', 1), 'one hat'); + }); + test('russian few', () async { + Localization.load( + const Locale('ru'), + translations: r.translations, + fallbackTranslations: r.fallbackTranslations, + ); + expect(Localization.instance.plural('hat', 2), 'few hats'); + expect(Localization.instance.plural('hat', 3), 'few hats'); + }); + test('russian many', () async { + Localization.load( + const Locale('ru'), + translations: r.translations, + fallbackTranslations: r.fallbackTranslations, + ); + expect(Localization.instance.plural('hat', 0), 'many hats'); + expect(Localization.instance.plural('hat', 5), 'many hats'); }); -} \ No newline at end of file + }); +} diff --git a/test/easy_localization_test.dart b/test/easy_localization_test.dart index 5dff2aa3..352996d3 100644 --- a/test/easy_localization_test.dart +++ b/test/easy_localization_test.dart @@ -64,9 +64,11 @@ void main() { test('load() with fallback succeeds', () async { expect( - Localization.load(const Locale('en'), - translations: r1.translations, - fallbackTranslations: r2.translations), + Localization.load( + const Locale('en'), + translations: r1.translations, + fallbackTranslations: r2.fallbackTranslations, + ), true); }); @@ -243,9 +245,11 @@ void main() { setUpAll(() async { await r.loadTranslations(); - Localization.load(const Locale('en'), - translations: r.translations, - fallbackTranslations: r.fallbackTranslations); + Localization.load( + const Locale('en'), + translations: r.translations, + fallbackTranslations: r.fallbackTranslations, + ); }); test('finds and returns resource', () { expect(Localization.instance.tr('test'), 'test');