Про локализацию (интернационализацию) приложений Flutter написано уже достаточно много.
Официальная документация довольно подробно останавливается на этом вопросе, кроме этого ряд энтузиастов описывает самые различные подходы.


Эта статья не претендует на полноту охвата вопроса, а является описанием практики, на мой взгляд, очень эффективно уменьшающей ручной ввод.


Речь идет о локализации при помощи flutter_i18n — плагина Android Studio, используя который удается избавиться от рутинной работы и шаблонного кода.


Подготовка


Сперва установите плагин flutter-i18n


image


После перезагрузки в структуру проекта автоматически добавятся файлы generated/i18n.dart и res/values/strings_en.arb


image


(файл strings_ru.arb добавлен мною вручную для русского языка)


Обратите внимание, что Android Studio 3.3.1 — 3.4 содержит какой-то косяк, из-за которого файлы локализации не генерятся. Я описывал эту проблему на stackoverflow, и получил решение. Еще одним решением является временно остаться на AS 3.2, но это на любителя.


Еще потребуется установить пакет flutter_localizations для локализации внутренних виджетов Flutter (это будет делаться за вас на системном уровне).


dev_dependencies:
  flutter_localizations:
    sdk: flutter

После этого вам достаточно будет внести в конструктор параметры локализации:


    return MaterialApp(
      localizationsDelegates: [
        S.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        DefaultCupertinoLocalizations.delegate,
      ],
      supportedLocales: S.delegate.supportedLocales,

и не забыть импортировать пакет


import 'package:f_latte/generated/i18n.dart';

Локализация


Просто начинайте добавлять необходимые строки, соблюдая нотацию JSON, вот так:


strings_en.arb:


{
  "title": "F-Latte",
  "greeting": "Hi, $name!",
  "pushingZero": "You pressed NONE (",
  "pushingOne": "You pressed once",
  "pushingTwo": "You pressed twice",
  "pushingOther": "You pressed $cnt times",
}

Кстати, плагин реализует логику работы с plurals (множественными числами), для этого следует определенным образом называть ключи в arb-файлах. Как это работает вам станет понятно из кода примера.


Для добавления языков просто добавьте необходимые файлы в этот же пакет, и внесите туда локализованные строки с теми же самыми ключами, вот так:


strings_ru.arb:


{
  "title": "F-Латте",
  "greeting": "Привет, ${name}!",
  "pushingZero": "Ничего не нажималось",
  "pushingOne": "Нажато разок",
  "pushingTwo": "Нажато дважды",
  "pushingOther": "Нажато $cnt раз(а)"
}

При любых изменениях в этих файлах плагин будет перестраивать файл i18n.dart. Кстати, рекомендую его хотя бы просмотреть, многое станет понятнее.


Вот и все. В любом месте, где требуется доступ к локализованным строкам следует просто вызывать статический метод локализатора:


/// так
title: Text(S.of(context).title),
...
/// или так
Text(S.of(context).greeting('User'), ),
...
/// или вот так
Text(
    S.of(context).pushing(_counter),
    style: Theme.of(context).textTheme.display1,
,

Вот как это выглядит


Код с примером находится здесь (ветка iter_0001_localiz).


Источник иллюстрации.

Комментарии (3)


  1. delletenebre
    16.05.2019 16:27

    Спасибо. А у plural есть формы few и many?


    1. rookie_cruekie Автор
      17.05.2019 09:55

      Да, просто добавьте строки


       "pushingFew": "You pressed few times",
        "pushingMany": "You pressed many times",

      В i18n.dart появится


          switch (cnt.toString()) {
            case "0":
              return "You pressed NONE (";
            case "1":
              return "You pressed once";
            case "2":
              return "You pressed twice";
            case "few":
              return "You pressed few times";
            case "many":
              return "You pressed many times";
            default:
              return "You pressed $cnt times";
          }

      и можно использовать


      S.of(context).pushing('many'),
      S.of(context).pushing('few'),


  1. rstrelba
    17.05.2019 08:33
    +1

    В 3.4.1 исправили.