Easy and Fast internationalization for your Flutter Apps

Overview

Easy and Fast internationalization for your Flutter Apps

Pub Version likes likes likes Code Climate issues GitHub closed issues GitHub contributors GitHub repo size GitHub forks GitHub stars Coveralls github branch GitHub Workflow Status CodeFactor Grade GitHub license Sponsors PRs Welcome

Why easy_localization?

  • πŸš€ Easy translations for many languages
  • πŸ”Œ Load translations as JSON, CSV, Yaml, Xml using Easy Localization Loader
  • πŸ’Ύ React and persist to locale changes
  • ⚑ Supports plural, gender, nesting, RTL locales and more
  • ↩️ Fallback locale keys redirection
  • ⁉️ Error widget for missing translations
  • ❀️ Extension methods on Text and BuildContext
  • πŸ’» Code generation for localization files and keys.
  • πŸ›‘οΈ Null safety
  • πŸ–¨οΈ Customizable logger.

Getting Started

πŸ”© Installation

Add to your pubspec.yaml:

dependencies:
  easy_localization: 
   

Create folder and add translation files like this

assets
└── translations
    β”œβ”€β”€ {languageCode}.{ext}                  //only language code
    └── {languageCode}-{countryCode}.{ext}    //or full locale code

Example:

assets
└── translations
    β”œβ”€β”€ en.json
    └── en-US.json 

Declare your assets localization directory in pubspec.yaml:

flutter:
  assets:
    - assets/translations/

πŸ”Œ Loading translations from other resources

You can use JSON,CSV,HTTP,XML,Yaml files, etc.

See Easy Localization Loader for more info.

⚠️ Note on iOS

For translation to work on iOS you need to add supported locales to ios/Runner/Info.plist as described here.

Example:

<key>CFBundleLocalizationskey>
<array>
	<string>enstring>
	<string>nbstring>
array>

βš™οΈ Configuration app

Add EasyLocalization widget like in example

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:easy_localization/easy_localization.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await EasyLocalization.ensureInitialized();
  
  runApp(
    EasyLocalization(
      supportedLocales: [Locale('en', 'US'), Locale('de', 'DE')],
      path: 'assets/translations', // <-- change the path of the translation files 
      fallbackLocale: Locale('en', 'US'),
      child: MyApp()
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      home: MyHomePage()
    );
  }
}

Full example

πŸ“œ Easy localization widget properties

Properties Required Default Description
key false Widget key.
child true Place for your main page widget.
supportedLocales true List of supported locales.
path true Path to your folder with localization files.
assetLoader false RootBundleAssetLoader() Class loader for localization files. You can use custom loaders from Easy Localization Loader or create your own class.
fallbackLocale false Returns the locale when the locale is not in the list supportedLocales.
startLocale false Overrides device locale.
saveLocale false true Save locale in device storage.
useFallbackTranslations false false If a localization key is not found in the locale file, try to use the fallbackLocale file.
useOnlyLangCode false false Trigger for using only language code for reading localization files.

Example:
en.json //useOnlyLangCode: true
en-US.json //useOnlyLangCode: false
errorWidget false FutureErrorWidget() Shows a custom error widget when an error occurs.

Usage

πŸ”₯ Initialize library

Call EasyLocalization.ensureInitialized() in your main before runApp.

void main() async{
  // ...
  // Needs to be called so that we can await for EasyLocalization.ensureInitialized();
  WidgetsFlutterBinding.ensureInitialized();

  await EasyLocalization.ensureInitialized();
  // ...
  runApp(....)
  // ...
}

πŸ”₯ Change or get locale

Easy localization uses extension methods [BuildContext] for access to locale.

It's the easiest way change locale or get parameters πŸ˜‰ .

ℹ️ No breaking changes, you can use old the static method EasyLocalization.of(context)

Example:

context.setLocale(Locale('en', 'US'));

print(context.locale.toString());

πŸ”₯ Translate tr()

Main function for translate your language keys

You can use extension methods of [String] or [Text] widget, you can also use tr() as a static function.

Text('title').tr() //Text widget

print('title'.tr()); //String

var title = tr('title') //Static function

Arguments:

Name Type Description
args List List of localized strings. Replaces {} left to right
namedArgs Map Map of localized strings. Replaces the name keys {key_name} according to its name
gender String Gender switcher. Changes the localized string based on gender string

Example:

{
   "msg":"{} are written in the {} language",
   "msg_named":"Easy localization is written in the {lang} language",
   "msg_mixed":"{} are written in the {lang} language",
   "gender":{
      "male":"Hi man ;) {}",
      "female":"Hello girl :) {}",
      "other":"Hello {}"
   }
}
// args
Text('msg').tr(args: ['Easy localization', 'Dart']),

// namedArgs
Text('msg_named').tr(namedArgs: {'lang': 'Dart'}),

// args and namedArgs
Text('msg_mixed').tr(args: ['Easy localization'], namedArgs: {'lang': 'Dart'}),

// gender
Text('gender').tr(gender: _gender ? "female" : "male"),

πŸ”₯ Plurals plural()

You can translate with pluralization. To insert a number in the translated string, use {}. Number formatting supported, for more information read NumberFormat class documentation.

You can use extension methods of [String] or [Text] widget, you can also use plural() as a static function.

Arguments:

Name Type Description
value num Number value for pluralization
args List List of localized strings. Replaces {} left to right
namedArgs Map Map of localized strings. Replaces the name keys {key_name} according to its name
name String Name of number value. Replaces {$name} to value
format NumberFormat Formats a numeric value using a NumberFormat class

Example:

{
  "day": {
    "zero":"{} Π΄Π½Π΅ΠΉ",
    "one": "{} дСнь",
    "two": "{} дня",
    "few": "{} дня",
    "many": "{} Π΄Π½Π΅ΠΉ",
    "other": "{} Π΄Π½Π΅ΠΉ"
  },
  "money": {
    "zero": "You not have money",
    "one": "You have {} dollar",
    "many": "You have {} dollars",
    "other": "You have {} dollars"
  },
  "money_args": {
    "zero": "{} has no money",
    "one": "{} has {} dollar",
    "many": "{} has {} dollars",
    "other": "{} has {} dollars"
  },
  "money_named_args": {
    "zero": "{name} has no money",
    "one": "{name} has {money} dollar",
    "many": "{name} has {money} dollars",
    "other": "{name} has {money} dollars"
  }
}

⚠️ Key "other" required!

//Text widget with format
Text('money').plural(1000000, format: NumberFormat.compact(locale: context.locale.toString())) // output: You have 1M dollars

//String
print('day'.plural(21)); // output: 21 дСнь

//Static function
var money = plural('money', 10.23) // output: You have 10.23 dollars

//Static function with arguments
var money = plural('money_args', 10.23, args: ['John', '10.23'])  // output: John has 10.23 dollars

//Static function with named arguments
var money = plural('money_named_args', 10.23, namedArgs: {'name': 'Jane', 'money': '10.23'})  // output: Jane has 10.23 dollars
var money = plural('money_named_args', 10.23, namedArgs: {'name': 'Jane'}, name: 'money')  // output: Jane has 10.23 dollars

πŸ”₯ Linked translations:

If there's a translation key that will always have the same concrete text as another one you can just link to it. To link to another translation key, all you have to do is to prefix its contents with an @: sign followed by the full name of the translation key including the namespace you want to link to.

Example:

{
  ...
  "example": {
    "hello": "Hello",
    "world": "World!",
    "helloWorld": "@:example.hello @:example.world"
  }
  ...
}
print('example.helloWorld'.tr()); //Output: Hello World!

You can also do nested anonymous and named arguments inside the linked messages.

Example:

{
  ...
  "date": "{currentDate}.",
  "dateLogging": "INFO: the date today is @:date"
  ...
}
print('dateLogging'.tr(namedArguments: {'currentDate': DateTime.now().toIso8601String()})); //Output: INFO: the date today is 2020-11-27T16:40:42.657.

Formatting linked translations:

Formatting linked locale messages If the language distinguishes cases of character, you may need to control the case of the linked locale messages. Linked messages can be formatted with modifier @.modifier:key

The below modifiers are available currently.

  • upper: Uppercase all characters in the linked message.
  • lower: Lowercase all characters in the linked message.
  • capitalize: Capitalize the first character in the linked message.

Example:

{
  ...
  "example": {
    "fullName": "Full Name",
    "emptyNameError": "Please fill in your @.lower:example.fullName"
  }
  ...
}

Output:

print('example.emptyNameError'.tr()); //Output: Please fill in your full name

πŸ”₯ Reset locale resetLocale()

Reset locale to device locale

Example:

RaisedButton(
  onPressed: (){
    context.resetLocale();
  },
  child: Text(LocaleKeys.reset_locale).tr(),
)

πŸ”₯ Get device locale deviceLocale

Get device locale

Example:

print(${context.deviceLocale.toString()}) // OUTPUT: en_US

πŸ”₯ Delete save locale deleteSaveLocale()

Clears a saved locale from device storage

Example:

RaisedButton(
  onPressed: (){
    context.deleteSaveLocale();
  },
  child: Text(LocaleKeys.reset_locale).tr(),
)

πŸ”₯ Get Easy localization widget properties

At any time, you can take the main properties of the Easy localization widget using [BuildContext].

Are supported: supportedLocales, fallbackLocale, localizationDelegates.

Example:

print(context.supportedLocales); // output: [en_US, ar_DZ, de_DE, ru_RU]

print(context.fallbackLocale); // output: en_US

πŸ’» Code generation

Code generation supports only json files, for more information run in terminal flutter pub run easy_localization:generate -h

Command line arguments

Arguments Short Default Description
--help -h Help info
--source-dir -S resources/langs Folder containing localization files
--source-file -s First file File to use for localization
--output-dir -O lib/generated Output folder stores for the generated file
--output-file -o codegen_loader.g.dart Output file name
--format -f json Support json or keys formats
--[no-]skip-unnecessary-keys -u false Ignores keys defining nested object except for pluarl(), gender() keywords.

πŸ”Œ Localization asset loader class

Steps:

  1. Open your terminal in the folder's path containing your project
  2. Run in terminal flutter pub run easy_localization:generate
  3. Change asset loader and past import.
import 'generated/codegen_loader.g.dart';
...
void main(){
  runApp(EasyLocalization(
    child: MyApp(),
    supportedLocales: [Locale('en', 'US'), Locale('ar', 'DZ')],
    path: 'resources/langs',
    assetLoader: CodegenLoader()
  ));
}
...
  1. All done!

πŸ”‘ Localization keys

If you have many localization keys and are confused, key generation will help you. The code editor will automatically prompt keys

Steps:

  1. Open your terminal in the folder's path containing your project
  2. Run in terminal flutter pub run easy_localization:generate -f keys -o locale_keys.g.dart
  3. Past import.
import 'generated/locale_keys.g.dart';
  1. All done!

How to use generated keys:

print(LocaleKeys.title.tr()); //String
//or
Text(LocaleKeys.title).tr(); //Widget

πŸ–¨οΈ Logger

[Easy Localization] logger based on [Easy Logger]

You can customize logger for you project

Show only lost keys message

Lost translations keys logged like warning messages. Change [Easy Logger] level for display only errors and warnings.

EasyLocalization.logger.enableLevels = [LevelMessages.error, LevelMessages.warning];

Logger off

For disable logger, change Build Modes in [Easy Logger] to empty List;

EasyLocalization.logger.enableBuildModes = [];

Catching logger messages

For catching logger messages you need override default printer function.

EasyLogPrinter customLogPrinter = (
  Object object, {
  String name,
  StackTrace stackTrace,
  LevelMessages level,
}) {
  ///Your function
  print('$name: ${object.toString()}');
};

/// override printer to custom
EasyLocalization.logger.printer = customLogPrinter;

Read more about Easy Logger

βž• Extensions helpers

String to locale

'en_US'.toLocale(); // Locale('en', 'US')

//with custom separator
'en|US'.toLocale(separator: '|') // Locale('en', 'US')

Locale to String with separator

Locale('en', 'US').toStringWithSeparator(separator: '|') // en|US

Screenshots

Arabic RTL English LTR Error widget
Arabic RTL English LTR Error widget

Donations

We need your support. Projects like this can not be successful without support from the community. If you find this project useful, and would like to support further development and ongoing maintenance, please consider donating.

Sponsors

Contributors thanks

contributors

Comments
  • Black screen problem when opening the app.

    Black screen problem when opening the app.

    Using the sample application in the repo, I recorded a video showing the error in both the emulator and the real device. You can see the obvious error in the emulator. It happens very fast on the real device. You can see 16,22 and 26 seconds in the video by watching at a speed of 0.25. Occurs when getting locale values from shared preferences. I have the same problem in my own applications where installed the this plugin. An extremely frustrating situation.

    https://www.youtube.com/watch?v=idAvuFG6BmI

    opened by hkndzdr 29
  • Localization key [key] not found after update to version 3.0.0

    Localization key [key] not found after update to version 3.0.0

    Hi I'm switching my app to null safety so I've imported version 3.0.0 of this package, but when I run my app or my unit test I get this message on the log:

    [🌎 Easy Localization] [WARNING] Localization key [email_label] not found
    [🌎 Easy Localization] [WARNING] Localization key [password_label] not found
    [🌎 Easy Localization] [WARNING] Localization key [login_btn] not found
    

    For context I'm using the CodegenLoader asset loader and Text('email_label').tr() in Widgets

    This is my main:

    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await EasyLocalization.ensureInitialized();
      await intl.initializeDateFormatting("en");
    
      runApp(AppWidget());
    }
    
    class AppWidget extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return EasyLocalization(
          supportedLocales: [
            Locale('en'),
            Locale('it'),
          ],
          path: "assets/translations",
          assetLoader: CodegenLoader(),
          fallbackLocale: Locale('en'),
          child: // ...
        );
      }
    }
    
    
    bug help wanted 
    opened by Supercaly 25
  • Unconsistent _osLocale

    Unconsistent _osLocale

    This bug isn't easy reproducible in debug, only in release mode and I don't know how to fix it.

    Edit: We found a way to reproduce it, here and there is an open issue on flutter repo. There also is a workaround providen by @Overman775

    On first launch, it starts in french (fr_FR) on a french iPhone (SE or 6). On second launch, it starts in english (en_US)

    Then it randomly starts in french or english depending on some unknown dark magic...

    I added required keys in Info.plist:

    <key>CFBundleLocalizations</key>
    <array>
    	<string>fr</string>
    	<string>en</string>
    	<string>ca</string>
    	<string>de</string>
    	<string>es</string>
    	<string>eu</string>
    	<string>it</string>
    	<string>nl</string>
    	<string>zh</string>
    </array>
    

    And also

    <key>CFBundleDevelopmentRegion</key>
    <string>fr</string>
    
    <key>CFBundleAllowMixedLocalizations</key>
    <true/>
    

    I ran flutter clean.

    When I run flutter run ios it works nicely but when I deploy it to testflight it doesn't.

    Here are the logs I gathered with the console:

    1st launch:

    14:49:44.220356+0200	Runner	flutter: EasyLocalization
    14:49:44.221033+0200	Runner	flutter: initState
    14:49:44.224536+0200	Runner	flutter: easy localization: Build
    14:49:44.224589+0200	Runner	flutter: easy localization: Device locale fr_FR
    14:49:44.224626+0200	Runner	flutter: _osLocale fr_FR
    14:49:44.224682+0200	Runner	flutter: _checkInitLocale locale: fr _osLocale: fr
    14:49:44.224719+0200	Runner	flutter: localePath assets/langs/st/fr.json
    

    2nd launch:

    14:50:04.279576+0200	Runner	flutter: EasyLocalization
    14:50:04.290749+0200	Runner	flutter: initState
    14:50:04.291415+0200	Runner	flutter: easy localization: Build
    14:50:04.293339+0200	Runner	flutter: easy localization: Device locale en_US
    14:50:04.293450+0200	Runner	flutter: _osLocale en_US
    14:50:04.293597+0200	Runner	flutter: _checkInitLocale locale: fr _osLocale: en
    14:50:04.293724+0200	Runner	flutter: _checkInitLocale locale: en _osLocale: en
    14:50:04.293760+0200	Runner	flutter: localePath assets/langs/st/en.json
    

    Here is my setup:

    final String assetsLocalePath = 'assets/langs/st/';
    final List<String> supportedLocales = [
      'fr',
      'en',
      'ca',
      'de',
      'es',
      'eu',
      'it',
      'nl',
      'zh',
    ];
    
    runApp(EasyLocalization(
          path: assetsLocalePath,
          useOnlyLangCode: true,
          child: MyApp(),
          saveLocale: false,
          supportedLocales:
              supportedLocales.map((locale) => Locale(locale)).toList(),
        ));
    

    What shall I do? Thanks a lot!

    bug 
    opened by HugoHeneault 25
  • Rebuild the wrapper widget architecture

    Rebuild the wrapper widget architecture

    @aissat @Overman775 I found the time today and rebuild the architecture layer of the top level wrapper widget. I eliminated the Intl stuff completly from the config, since I believe it is much safer / more maintainable to just trust the flutter core framework to resolve the device language config and work through the delegate, offering an override logic through the safe persistance. All features are working as expected & tests are passing. Here are the notables:

    • The initialisation of the wrapper is now happening asynchronously, meaning that no more loader or err or widgets are needed, but it will simply refreshes if a persistet locale is found. Otherwise, it is left to the system to select the locale as usual and the library will adapt to it. This will eliminate #39 #98 and #96. Also better architecture not to block anything with async work before the actual app widget.
    • I eliminated the fallback locale, since there is more advanced login to selecting it. I think this should be left up to the system. Generally, according to flutter docs, the first entry of the array will be used as fallback. However, in some cases some translation delegates might not be supporting a fallback or the system has other settings that determine preferred language. I think it is unsafe to force the fallback onto the system through a direct override.
    • I commented out the Intl. Related tests. Im not sure, what the Intl.defaultLocale setting actually does. Everything works fine without it. Am I overlooking something here? If so, ping me and ill set it in my implementation.
    • I would consider defaulting the language saving to false.
    • Doc updates are pending, wanted to get your feedback first.

    Cheers, Moritz

    opened by moritzmorgenroth 24
  • Unable to load asset *translation path*

    Unable to load asset *translation path*

    Hey, with latest version easy_localization: ^3.0.1-dev.

    I get this error when opening the app. Unable to load asset *translation path*

    Please help, Thanks

    opened by naamapps 23
  • Locale resetting back to english after restart of app

    Locale resetting back to english after restart of app

    Hi, There is a set language page in my app I am setting the locale when the language is changed. This is where I am setting the locale :

     LanguagePage({Key key}) : super(key: key);
    
     @override
     _LanguagePageState createState() => _LanguagePageState();
    }
    
    class _LanguagePageState extends State<LanguagePage> {
     String selectedLanguage;
     bool shouldTranslateEntireApp = false;
     Future whenDoneIsPressed() async {
       BlocProvider.of<LanguageBloc>(context)
           .add(LanguageUpdating(language: selectedLanguage, shouldTranslateEntireApp: shouldTranslateEntireApp));
     }
    
     @override
     void initState() {
       BlocProvider.of<LanguageBloc>(context).add(LanguageOpened());
    
       super.initState();
     }
    
     @override
     Widget build(BuildContext context) {
       return SafeArea(
         child: Scaffold(
           body: BlocConsumer<LanguageBloc, LanguageState>(listener: (context, state) async {
             if (state is LanguageInitial) {
               setState(() {
                 shouldTranslateEntireApp = state.enableSystemWide;
                 selectedLanguage = state.selectedLanguage;
               });
             }
             if (state is LanguageUpdated) {
               if (state.enableSystemWide == true) {
                 var codes = languagesTextAndCode[state.selectedLanguage].split("-");
                 EasyLocalization.of(context).locale = Locale(codes.first, codes.last);
    
                 // data.changeLocale(
                 //     locale: Locale(codes.first, codes.last));
               }
               if (state.isLoggedIn == true) {
                 Navigator.of(context).pop();
               } else {
                 await Navigator.of(context).pushReplacementNamed(Routes.onBoarding);
               }
             }
           }, builder: (context, state) {
             var languages = {};
             if (state is LanguageInitial) {
               languages = state.languages;
             }
             return Column(
               children: <Widget>[
                 Padding(
                   padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
                   child: Text(
                     StringRes.appName,
                     textAlign: TextAlign.center,
                     style: Helper.contentStyle(language: 'k', fontSize: 36).copyWith(color: Theme.of(context).accentColor),
                   ).tr(),
                 ),
                 Text(
                   'Choose your language to continue',
                   textAlign: TextAlign.center,
                 ),
                 SizedBox(height: 16),
                 Expanded(
                   child: GridView.count(
                     primary: false,
                     padding: const EdgeInsets.all(16),
                     crossAxisSpacing: 8,
                     mainAxisSpacing: 8,
                     childAspectRatio: 3 / 1,
                     crossAxisCount: 2,
                     children: <Widget>[
                       ...(languages).entries.map((entry) {
                         var language = entry.key;
                         return LanguageButton(
                             language: entry.value,
                             selected: selectedLanguage == language,
                             onTap: () {
                               setState(() => selectedLanguage = language);
                             });
                       })
                     ],
                   ),
                 ),
                 SizedBox(height: 16),
                 Row(
                   children: <Widget>[
                     SizedBox(
                       width: 20,
                     ),
                     Icon(Icons.public),
                     SizedBox(width: 4),
                     Expanded(child: Text(StringRes.translateApp).tr()),
                     Checkbox(
                       value: shouldTranslateEntireApp,
                       onChanged: (check) => setState(() => shouldTranslateEntireApp = check),
                     ),
                   ],
                 ),
                 SizedBox(height: 10),
                 FractionallySizedBox(
                   widthFactor: 0.5,
                   child: RaisedButton(
                     onPressed: whenDoneIsPressed,
                     child: Text("Done"),
                   ),
                 ),
                 SizedBox(height: 10),
               ],
             );
           }),
         ),
       );
     }
    }
    
    

    This is where I am getting the locale in main.dart

         return MaterialApp(
            localizationsDelegates: [
              GlobalMaterialLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
              EasyLocalization.of(context).delegate,
            ],
    
            supportedLocales: EasyLocalization.of(context).supportedLocales,
            locale:
                EasyLocalization.of(context).locale, // navigatorKey: navigatorKey,
            debugShowCheckedModeBanner: false,
            theme: state.isDark == true
                ? Theme.darkTheme(context)
                : Theme.lightTheme(context),
            routes: Routes.routes,
            onUnknownRoute: Routes.Page404,
          );
    

    but when I restart the app the locale is set back to English... is there any way to set the locale permanently?

    opened by harivamshi81189 22
  • Simplify, reword doc and make note on iOS

    Simplify, reword doc and make note on iOS

    Hi, so i made 3 commits:

    1. add a note on iOS and link to change log and example
    2. simplify and reword features and header
    3. change and cleaned up a lot! not sure you want to use this, but let me know what you think
    opened by erf 20
  • Localization not working for some languanges

    Localization not working for some languanges

    Hi Guys!

    Love your library! I have added Spanish as the first localization and it worked great!

    Now I have added a few more and they are not working.. any idea what can be causing this issue?

    Locales added: hi (Hindi), ru (Russian), pt (Portuguese)

    I get the following error when switching to any of them:

    W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->getObject(Ljava/lang/Object;J)Ljava/lang/Object; (greylist, linking, allowed) W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->putInt(Ljava/lang/Object;JI)V (greylist, linking, allowed) W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->getObject(Ljava/lang/Object;J)Ljava/lang/Object; (greylist, linking, allowed) W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->putLong(Ljava/lang/Object;JJ)V (greylist, linking, allowed) W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->getInt(Ljava/lang/Object;J)I (greylist, linking, allowed) W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->getLong(Ljava/lang/Object;J)J (greylist,core-platform-api, linking, allowed) I/flutter (25488): Instance of 'Prefs', k_last_locale: save success: true W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->getObject(Ljava/lang/Object;J)Ljava/lang/Object; (greylist, linking, allowed) W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->putObject(Ljava/lang/Object;JLjava/lang/Object;)V (greylist, linking, allowed) I/flutter (25488): 2020-11-27T10:49:51.714417 D FirestoreController._initDeviceListener.<ac>: _aDeviceChangesStream: {date: 11/27/2020, device_name: MI 8 Pro, plan_type: PlanType.Junior, device_id: 01f025cea8d82f17, locale: Hindi, timestamp: 1606466759710} W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->putInt(Ljava/lang/Object;JI)V (greylist, linking, allowed) I/flutter (25488): [WARNING] Easy Localization: Localization key [Learn] not found I/flutter (25488): [WARNING] Easy Localization: Localization key [Play] not found I/flutter (25488): [WARNING] Easy Localization: Localization key [Menu] not found W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->putLong(Ljava/lang/Object;JJ)V (greylist, linking, allowed) I/flutter (25488): 2020-11-27T10:49:52.123196 D FirestoreController.updateDeviceLocale: updateDeviceLocale success W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->getObject(Ljava/lang/Object;J)Ljava/lang/Object; (greylist, linking, allowed) W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->getObject(Ljava/lang/Object;J)Ljava/lang/Object; (greylist, linking, allowed) W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->getInt(Ljava/lang/Object;J)I (greylist, linking, allowed) W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->getLong(Ljava/lang/Object;J)J (greylist,core-platform-api, linking, allowed) W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->getObject(Ljava/lang/Object;J)Ljava/lang/Object; (greylist, linking, allowed) I/chatty (25488): uid=10549(com.alefapps.learn_english_kids) FirestoreWorker identical 1 line W/rn_english_kid(25488): Accessing hidden method Lsun/misc/Unsafe;->getObject(Ljava/lang/Object;J)Ljava/lang/Object; (greylist, linking, allowed)

    Best regards, Asaf

    waiting for customer response 
    opened by asafvaron90 18
  • Limitations of preloaderWidget/Color

    Limitations of preloaderWidget/Color

    The asynchronous startup initialisation of the library enforces the use of preloaderWidget/Color in order to provide a smooth experience to our users.

    In order to provide a smooth transition to our users though, we would need to present a widget that is somewhat similar to the widget that is going to be presented after the initialisation ( which is the application's main widget ). The issue here is that this widget will probably have text that cannot be translated because easy_localization is not initialised yet. So the only real option here is to either show a blank color with preloaderColor or a very simple loading widget with preloaderWidget.

    My proposal is the following:

      // ensureInitialized ensures that the last used locale is loaded from SharedPrefs
      // and that the app will have the correct locale from 1st frame.
      // Omitting this will result in the app always using the fallbackLocale
      await EasyLocalization.ensureInitialized();
    

    This will be called at main before runApp as other libraries like Hive recommend developers to do. ( Keep in mind that as long as we block the execution of runApp the native splash screen is shown which i believe is something expected from the flutter community )

    In order to not break the api of the library, i recommend adding ensureInitialized as an option for developers to use, in order to make the library more flexible on this matter.

    @aissat

    enhancement 
    opened by spiritinlife 17
  • Cleanup README.md by linking to changelog and example

    Cleanup README.md by linking to changelog and example

    Se PR: https://github.com/aissat/easy_localization/pull/167

    I found README.md a bit large, including both the CHANGELOG.md and example.

    I suggest instead linking to separate files for this.

    BTW: Great library! :-)

    opened by erf 16
  • Different approach on localization

    Different approach on localization

    Hello @aissat @danilofuchs Take a look at this, it is a big change but this is how i would like to proceed with localization :)

    !!! This is still under development and shouldn't be merged !!!

    Main things:

    1. Lazy cache nested keys for better performance
    2. Simplify the usage of the library by exposing only one class EasyLocalization and hide EasyLocalizationProvider and EasyLocalizationDelegate
    3. Use EasyLocalization.of(context) to interact with the library
    4. Add supportedLocales, fallbackLocale and localeResolutionCallback to be exposed and set in MaterialApp

    I tried to remove the current complexity and confusion of proper translations configuration.

    Example usage ( also seen in example/main )

    void main() => runApp(EasyLocalization(
          supportedLocales: [Locale('en', 'US'), Locale('ar', 'DZ')],
          fallbackLocale: Locale('en', 'US'),
          path: 'resources/langs',
          useOnlyLangCode: true,
          // optional assetLoader default used is RootBundleAssetLoader which uses flutter's assetloader
          // assetLoader: NetworkAssetLoader(),
          child: MyApp(),
        ));
    
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          localizationsDelegates: [
            GlobalMaterialLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate,
            EasyLocalization.of(context).delegate,
          ],
          supportedLocales: EasyLocalization.of(context).supportedLocales,
          // locale is either the deviceLocale or the MaterialApp widget locale.
          // This function is responsible for returning a locale that is supported by your app
          // if the app is opened for the first time and we only have the deviceLocale information.
          localeResolutionCallback:
              EasyLocalization.of(context).localeResolutionCallback,
          locale: EasyLocalization.of(context).locale,
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Easy localization'),
        );
      }
    }
    
    

    Changing locale with

     EasyLocalization.of(context).changeLocale(locale: Locale("en", "US"))
    
    opened by spiritinlife 15
  • Add comments lines to the translation json file

    Add comments lines to the translation json file

    Hey, I know that json file does not allows to add comments, but is there a way to do it for Easy localization? Most of the time the translation files are too big and difficult to read. I would like to add comments lines in order to separate the translation file based on my flutter screens. Thanks

    Example: //screen 1 {"settings": "Settings"} //screen 2 {"welcome": "Benvenuto"}

    opened by giogithub89 0
  • Localized languages are not showing in iOS App Store

    Localized languages are not showing in iOS App Store

    I added 4 translations for my app and the app shows the correct language on both iOS and Android. However, the 4 languages I have are not showing in the iOS App Store. Only "English" is to be seen.

    Current App Store page:

    image

    Expected App Store page:

    image

    I followed everything in the localization example.. My Info.plist has:

    <key>CFBundleLocalizations</key>
        <array>
            <string>en</string>
            <string>es</string>
            <string>de</string>
            <string>ar</string>
    </array>
    

    in my main.dart, I configured the languages like this:

      runApp(
        EasyLocalization(
          supportedLocales: [
            Locale('en'),
            Locale('es'),
            Locale('de'),
            Locale('ar'),
          ],
          path: 'assets/translations',
          fallbackLocale: Locale('en'),
          child: MyApp(),
        ),
      );
    

    In Xcode, I can see the 4 languages in image

    but not in image

    This might be the reason, but I'm not sure what to use here, or if this is the right place to edit.

    image

    Can you please advise? a small fix might be needed in the "Easy localization" code or in the documentation.

    opened by ishomam 2
  • Saved locale code not found after changing the locale code caused null error

    Saved locale code not found after changing the locale code caused null error

    I have an app with 2 languages, Russian and English. Yesterday I decided to remove the Russian language and replace it with the Kazakh language. I have changed the JSON file name (from ru.json to kk.json), locale code in EasyLocalization initializer (from 'ru' to 'kk'), then in InfoPlist (from 'ru' to 'kk') and also run a script to generate translation keys and loader. Everything seems fine in the first app installation (clean installation). Then I publish the app to stores. When my users that had saved and selected locale 'ru' installed the new update, they had a grey screen with a null error at startup. I recreated this case on my own and found that the easy_localization plugin doesn't check for null or emptiness of saved locale in local storage. I had a fallback locale set to EN that doesn't work in this case, also set useFallbackTranslations: true - also doesn't work. Logs at debug console stops tracking at EasyLocalization initialization without any useful information. I ask you to make an additional check for the presence of the saved locale. Or you can resave the locale code to a new value if it is not in the local repository. If my implementation is wrong, please correct me.

    final configuredApp = AppConfig( envType: EnvironmentType.development, appInternalId: 1, child: DevicePreview( enabled: true, builder: (context) => EasyLocalization( supportedLocales: [Locale('kk'), Locale('en')], startLocale: Locale('en'), fallbackLocale: Locale('en'), path: 'assets/translations', assetLoader: CodegenLoader(), useFallbackTranslations: true, child: MyApp(), ), ), ); runApp(configuredApp);

    Screens: [https://disk.yandex.ru/i/w-nGZL0DggaWHQ](error at startup) [https://disk.yandex.ru/i/CUNHKS30gQT2IQ](debug result)

    opened by deeeznuds 0
  • Why are these files being created in the Android APK?

    Why are these files being created in the Android APK?

    Our real localization files are in assets/locale and we have 8 of them. However there are 4 other json files that are not in our source folder ANYWHERE. How can they be getting in the final APK? Any ideas? Is it coming from some 3rd party library perhaps?

    From APK explorer:

    Screen Shot 2022-12-09 at 4 23 21 PM
    • en.json
    • en-US.json
    • ar.json
    • ar-DZ.json
    {
      "test": "test",
      "day": {
        "zero": "{} days",
        "one": "{} day",
        "two": "{} days",
        "few": "{} few days",
        "many": "{} many days",
        "other": "{} other days"
      },
      "hat": {
        "zero": "no hats",
        "one": "one hat",
        "two": "two hats",
        "few": "few hats",
        "many": "many hats",
        "other": "other hats"
      },
      "hat_other": {
        "other": "other hats"
      }
    }
    
    opened by tim-eucalyptus 0
  • trExists extension added

    trExists extension added

    This feature is very useful to develop custom methods to handle flavour based translations and other use cases.

    For example: "kyc": { "redFlavour": "Know your customer", "blueFlavour": "Verify address", "default": "Perform KYC" }

    By using trExists() extension method, we can write our own custom method to check if a translation is available for a flavour else use the default value.

    opened by hm-tamim 0
Owner
Aye7
Just coding & coding ...
Aye7
A flutter plugin for integrating Mobile Money Payments to your flutter apps

Add Mobile Money payments to your flutter apps using the FlutterWave api gateway. Features Recieve Payments through Mobile Money in Uganda Supports MT

null 5 Nov 9, 2022
Flutter Package to implement Feedback System in your @Flutter project. Taking Feedback from users made Easy!

Flutter App Feedback Taking feedback from the user made easy! Simply integrate flutter_app_feedback package into your Flutter project and you are read

Mihir Paldhikar 2 Nov 16, 2021
A fully responsive BMI calculator app made using flutter and dart with beautiful minimalistic user interface design and easy to use .

BMI_Calculator_Flutter A fully responsive BMI calculator app made using flutter and dart with beautiful minimalistic user interface design and easy to

null 1 Oct 9, 2021
A Dart-written Android app to make taking notes, tasks and events easy and straight forward

A Dart-written Android app to make taking notes, tasks and events easy and straight forward

n0pe 3 Nov 15, 2022
Prove your identity on demand and manage your finance with Flutter

Identt-User-Flutter IdenTT Prove your identity on demand and manage your finance. View Admin Panel Demo || View App Demo About The Project Problem: Mo

IdenTT 4 May 17, 2022
mezza 0 Nov 24, 2021
Use dynamic and beautiful card view pagers (horizontal direction) to help you create great apps.

Use dynamic and beautiful card view pagers (horizontal direction) to help you create great apps. Preview Mobile Vertical Card Pager Web Web Link Insta

Jeongtae Kim 27 Dec 9, 2022
A simple Todo app designed to simply use GraphQL as backend and provide an easy to use UI/UX.

simple_todo_app A simple Todo app designed to simply use GraphQL as backend and provide an easy to use UI/UX. A breakdown of the project and explanati

Emir HalΔ±cΔ± 2 Oct 9, 2022
Flutter OSM - OSM Plugin For Flutter Apps

flutter_osm_plugin osm plugin for flutter apps (only Android for now, iOS will b

null 1 Mar 29, 2022
Firebase + Flutter sample apps with code snippets, supported by comprehensive articles for each implementation.

FlutterFire Samples This repo is created to contain various sample apps demonstrating the integration of Firebase with Flutter. The final goal is to c

Souvik Biswas 186 Dec 24, 2022
A flutter clean architecture series, the way we build clean apps.

Flutter Clean Archeticture Series ?? "Making the world a better place" βœ… Full Articles You can check out the full Medium articles on devmuaz βœ… Branche

AbdulMuaz Aqeel 267 Jan 4, 2023
Examples showing how to use Rid in order to build Dart/Flutter apps integrated with Rust.

Examples showing how to use Rid in order to build Dart/Flutter apps integrated with Rust.

Thorsten Lorenz 205 Dec 24, 2022
A Flutter starter-kit for production-level apps.

Flutter Starter Introduction We wanted to take Flutter a step further and accelerate the process of building production-level apps. Presenting our sol

GeekyAnts 374 Dec 30, 2022
Learn how to incorporate Firebase into our Flutter apps

Flash Chat ⚑️ Our Goal The objective of this tutorial is to learn how to incorporate Firebase into our Flutter apps. We'll be using Firebase Cloud Fir

null 0 Oct 27, 2021
Cooking apps - Cooking App made using flutter framework

cooking_apps Cooking App made using flutter framework. This template app contain

Viraj Shah 1 Jan 24, 2022
Mongolian vertical script widgets for Flutter apps

mongol This library is a collection of Flutter widgets for displaying traditional Mongolian vertical text. The primary widgets include: MongolText: ve

null 56 Dec 12, 2022
fl_heatmap - A heatmap build for Flutter apps

fl_heatmap - A heatmap build for Flutter apps

Timo BΓ€hr 6 Sep 19, 2022
Google UI is an open-source UI library for developing cross-platform apps using Flutter with Material Design 2.0

Google UI Google UI is an open-source UI library for developing cross-platform apps using Flutter with "Material Design 2.0" Table of contents Install

Ed Sulaiman 25 Dec 24, 2022
A collection of sample apps that use Stream

Flutter samples Quick Links Register to get an API key for Stream Chat Flutter Chat Tutorial Chat UI Kit Flutter SDK Repo What is Stream? Stream allow

Stream 247 Dec 21, 2022