easy_locale 0.0.8 copy "easy_locale: ^0.0.8" to clipboard
easy_locale: ^0.0.8 copied to clipboard

Easy localization & internationalization (i18n) library.

Easy Locale #

Simple, yet another easy internationalizaion package.

The features of this package are:

  • No need to apply locale in the Flutter app
  • Very simple to use

For reference, this easy_locale can be used together with other multilingual packages.

Install #

  • This easy_locale package does not set the locale in a Flutter app.

  • For an iOS app, you need to add the list of supported languages to CFBundleLocalizations in the iOS Info.plist to support the locales. Or the app may display only English even if the device set a different language in its setting.

  • Below is an example of adding language settings to the ios/Runner/Info.plist file.

<key>CFBundleLocalizations</key>
<array>
	<string>en</string>
	<string>ch</string>
	<string>ja</string>
	<string>ko</string>
</array>
  • There is nothing to configure in Android.

Examples #

Initialization #

  • It is recommended to initialize before calling runApp in the main() function. If this is not possible, you can do it in the initState of the first page screen widget of the app.

  • By calling init as shown below, you can use the language settings of the phone (device). Depending on the situation, you may add the await keyword before TranslationService.instance.init().

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  TranslationService.instance.init();
  runApp(const MyApp());
}
  • You can initialize in more detail as shown below.
TranslationService.instance.init(
    deviceLocale: true,
    defaultLocale: 'ko',
    fallbackLocale: 'en',
    useKeyAsDefaultText: true,
);

In the code above, setting deviceLocale to true. It means it will use the language applied to the current device settings. The default value is true.

If deviceLocale is set to false, the defaultLanguage will be used. In other words, if you do not want to use the phone's default language settings and want to specify a language of your choice, you can set deviceLocale to false and provide a value like "ko" to defaultLanguage to select your desired language as the default.

If a translated string cannot be found in the multilingual settings, it will look for a translated string in the language specified by fallbackLocale and use it if found. The default value is en.

If useKeyAsDefaultText is true, it means using the language code (key) as is when a translated string cannot be found. If this value is false, the language code (key) will be used with .t appended to the end and displayed on the screen.

How to use #

Localization extension #

There are two localization functions: .t and .tr.

Places to set locale texts #

By default, the translation texts are saved in easy_locales/lib/src/locale.texts.dart. This file should have the most common text translation only. This is called default translation text file.

If you are developing a package and you are using easy_locale for the internationalization of the package, you should not touch the default translation text file. Instead, you should create your own translation text in your package and apply it to easy_locale's text object by calling lo.set().

If you are developing an app, you should create a text translation file somewhere in the app project, and apply it to easy_local's text object by calling lo.set().

By using TranslationService.instance.set(), you can change existing translation strings to something else or add new ones if they do not already exist. Therefore, you can use the in-house multilingual feature to translate the strings used in the app.

TranslationService.instance.set(
  key: 'hello',
  locale: 'en',
  value: 'Hello',
);

expect('hello'.t == 'Hello', true);

Adding custom translations

  • You can use lo.set() to add or update your own translations.

  • Below is an example of adding custom translations.

import 'package:easy_locale/easy_locale.dart';

final localeTexts = <String, Map<String, String>>{
  'todo': {
    'en': 'Todo',
    'ko': '할일',
  },
  'game': {
    'en': 'Games',
    'ko': '게임',
  },
  'Must login first': {
    'en': 'Must login first',
    'ko': '로그인이 필요합니다',
  },
  'you have reached the upload limit': {
    'en': 'You have reached the upload limit',
    'ko': '업로드 제한에 도달했습니다',
  },
};

void addLocaleTexts() async {
  final locale = await currentLocale;
  if (locale == null) return;

  for (var entry in localeTexts.entries) {
    lo.set(key: entry.key, locale: locale, value: entry.value[locale]);
  }
}

By doing as below, you can save it to the language key called name as shown below. Pay special attention to handling singular/plural forms.

final localeTexts = {
    'name': {
        'en': 'Name',
        'ko': '이름',
    },
    'there are {n} apple': {
        'en': {
            'none': 'There is no apple',
            'one': 'There is only {n} apple',
            'many': 'There are {n} apples',
        },
        'ko': '사과가 {n}개 있어요',
    }
}

Local Transation Texts #

Translation strings are stored in the localeTexts variable in ./lib/translation/translation.text.dart.

Simple translation - t #

.t is an extension method that simply displays text in multiple languages.

Translation.instance.setLocale('ko');
'name'.t // result: 이름

Translation with Replacement and Forms - tr #

Compared to .t, .tr allows for string substitution and can handle singular/plural forms.

The basic usage is: 'apple'.tr(args: {'name': 'J', 'n': n}, form: n).

In the args parameter, specify the key/value pairs you want to substitute in the translation string in the form args: { key: value, ... }.

For the form parameter, It can have 3 different values; a value of null or 0 means no items, 1 means singular, and 2 or more means plural.

When storing translation strings, they should be saved in the following format.

final localeTexts = {
    'apple': {
        'en': {
            'zero': '{name} has no apple.',
            'one': '{name} has one apple.',
            'many': '{name} has {n} apples.',
        }
    }
};

Example:

TranslationService.instance.set(
  key: 'apple',
  locale: 'en',
  value: {
    'zero': '{name} has no apple.',
    'one': '{name} has one apple.',
    'many': '{name} has {n} apples.',
  },
);

int n = 0;
expect('apple'.tr(args: {'name': 'J'}, form: n), 'J has no apple.');
n = 1;
expect('apple'.tr(args: {'name': 'J'}, form: n), 'J has one apple.');
n = 3;
expect('apple'.tr(args: {'name': 'J', 'n': n}, form: n), 'J has 3 apples.');

lo #

참고로 LocalService.instance 를 줄여서 lo 로 사용 할 수 있습니다.

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    super.initState();
    lo.init();
  }

  @override
  Widget build(BuildContext context) {
    lo.set(key: 'home title', locale: 'ko', value: '다국어 설정');
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text('home title'.t),
      ),
      // ...
    );
  }
}

유닛 테스트 #

test 폴더에 있는 테스트 코드를 보고, 사용법을 익히셔도 됩니다.

Trouble shooting #

  • If the translation is not working, then check if the easy_locale package has been initialized.