Шеринг файлов локализации между несколькими пакетами в Flutter

e1de23b1b472a8d2aaacf43a48773403.png

Когда вы разрабатываете большое приложение, вы волей-неволей дробите его на пакеты, однако если использовать стандартный механизм, который предлагают разработчики Flutter в официальной документации, прямого способа пошерить файлы локализации между проектами нет.

Есть вариант заново настроить flutter_localizations в новом пакете и заполнять там новые переводы и переносить старые. Но это сложно и кажется неправильным.

Тогда я предлагаю второй вариант. Поделиться переводами из одного пакета в другой. В этой статье я расскажу, как это сделать.

Идея

Пакет flutter_localizations по умолчанию генерирует файлы в папку /.dart_tool/flutter_gen/gen_l10n, но это директорию нельзя пошерить другим пакетам.
Наша задача создать пакет локализации и с помощью файла экспорта экспортировать файл app_localizations.dart из /.dart_tool/flutter_gen/gen_l10n/, чтобы его могли заиспользовать другие пакеты, в том числе наш основной.

Реализация

Создам пакет под названием sputnik_localization и добавлю туда плагины intl и app_localizations:

flutter pub add flutter_localizations --sdk=flutter
flutter pub add intl:any

В проекте:

MaterialApp(  
  ... 
  localizationsDelegates: const [  
    AppLocalizations.delegate,  
    GlobalMaterialLocalizations.delegate,  
    GlobalWidgetsLocalizations.delegate,  
    GlobalCupertinoLocalizations.delegate,  
  ],  
  supportedLocales: const [  
    Locale('en'),
  ],  
  ...
)

Затем создам папку lib/l10n/generated. В папке lib/l10n создам сам файл для локализации app_en.arb. Заполню его информацией:

{  
  "helloWorld": "Hello World!",
  "@helloWorld": {
      "description": "The conventional newborn programmer greeting"  
  }, 
  "alreadyHaveAccount": "Already have account?",  
  "signIn": "Sign in",  
  "signUp": "Sign up",  
  "invalidEmail": "Incorrect e-mail format",  
  "invalidPassword": "The password must contain no less than 6 and no more than 64 characters",  
  "passwordDontMatch": "The passwords don't match",  
  "unknownSignUpError": "Unknown error when creating an account", 
  "unknownSignInError": "Unknown error when logging in to the account"
}

Дальше необходимо в корне проекта создать файл l10n.yaml со следующим содержимым:

arb-dir: lib/l10n  
template-arb-file: app_en.arb  
output-localization-file: app_localizations.dart  
output-dir: lib/l10n/generated  
synthetic-package: false  
nullable-getter: false

arb-dir — расположение файлов локализации (в нашем случае app_en.arb)
template-arb-file — основной arb-файл
output-localization-file — файл, куда будет сгенерирована локализация
output-dir — папка, в которую будет идти генерация.
synthetic-package — флаг, который отвечает за выбор по умолчанию директории локализации (если false, то значение будет браться из arb-dir)
nullable-getter — позволяет не проверять на null значение перевода каждый раз при использовании, например, если значение true — AppLocalizations.of(context).alreadyHaveAccount ?? "Значение если перевода нет".

Дальше переходим в файл экспорта, в моем случае он называется lib/sputnik_localization.dart, в вашем случае это lib/<название_пакета>.dart. Там у меня лежит такой код:

library sputnik_localization;  
  
export 'package:flutter_localizations/flutter_localizations.dart'; // пакет
export 'l10n/generated/app_localizations.dart'; // переводы
export 'src/utils.dart'; // мои дополнительные приколюхи

Все! Теперь можно использовать в вашем проекте:

В pubspec.yaml подключаете:

sputnik_localization:  
  path: packages/sputnik_localization

В проекте:

import 'package:sputnik_localization/sputnik_localization.dart';

...

AppLocalizations.of(context).helloWorld

Готово!

Дополнение

Чтобы проще было пользоваться плагином локализации, вы можете написать дополнение в пакет локализации, как у меня файл utils.dart.

import 'package:flutter/material.dart';  
import 'package:sputnik_localization/l10n/generated/app_localizations.dart';  
  
extension BuildContextLocalizationEx on BuildContext {  
  AppLocalizations get tr =>; AppLocalizations.of(this);  
}

Заключение

Таким образом вы можете дробить свой проект на множество пакетов и не терять файлы локализации, не запариваться над синхронизацией нескольких файлов. Применяйте на здоровье!

Хорошего настроения и добра <3!

© Habrahabr.ru