Какие способы добавления локализации в Flutter-приложение вы знаете?

«Какие способы добавления локализации в Flutter-приложение вы знаете?» — вопрос из категории UI и вёрстка, который задают на 29% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В своих Flutter-проектах я использовал несколько подходов к локализации:

1. Стандартный подход с flutter_localizations и intl (рекомендуемый):

# pubspec.yaml
dependencies:
  flutter_localizations:
    sdk: flutter
  intl: ^0.18.0

flutter:
  generate: true
// main.dart
return MaterialApp(
  localizationsDelegates: [
    AppLocalizations.delegate, // Сгенерированный делегат
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
  supportedLocales: AppLocalizations.supportedLocales,
  locale: Locale('ru', 'RU'), // Текущая локаль
  home: HomePage(),
);

Структура файлов .arb:

// lib/l10n/app_en.arb
{
  "@hello": {
    "description": "Приветствие"
  },
  "hello": "Hello {name}",
  "@itemsCount": {
    "description": "Количество элементов",
    "placeholders": {
      "count": {}
    }
  },
  "itemsCount": "{count, plural, =0{No items} =1{1 item} other{{count} items}}"
}

// lib/l10n/app_ru.arb
{
  "hello": "Привет, {name}",
  "itemsCount": "{count, plural, =0{Нет элементов} =1{1 элемент} few{{count} элемента} other{{count} элементов}}"
}

Использование в коде:

Text(AppLocalizations.of(context)!.hello('Анна')),
Text(AppLocalizations.of(context)!.itemsCount(5)),

2. Динамическое переключение локали через State Management:

// С использованием Provider/Riverpod
class LocaleController {
  Locale _locale = Locale('en');

  Future<void> setLocale(Locale locale) async {
    _locale = locale;
    await _saveToPrefs(locale);
    notifyListeners();
  }

  Locale get locale => _locale;
}

// В MaterialApp
locale: context.watch<LocaleController>().locale,

3. Для более простых проектов — кастомное решение:

class AppLocalizations {
  final Map<String, Map<String, String>> _localizedValues = {
    'en': {
      'welcome': 'Welcome',
      'settings': 'Settings',
    },
    'ru': {
      'welcome': 'Добро пожаловать',
      'settings': 'Настройки',
    },
  };

  String translate(String key, BuildContext context) {
    final locale = Localizations.localeOf(context).languageCode;
    return _localizedValues[locale]?[key] ?? _localizedValues['en']![key]!;
  }
}

4. Пакеты для специфических нужд:

  • easy_localization — для быстрого старта с JSON/YAML файлами
  • flutter_i18n — поддержка вложенных ключей и плюрализации
  • intl_utils — дополнительные утилиты для работы с intl

В production-проектах я предпочитаю стандартный подход с intl, так как он обеспечивает типобезопасность, поддержку плюрализации, гендера и форматирования дат/чисел из коробки. Для динамической смены языка без перезапуска приложения комбинирую его с провайдером для управления состоянием локали.