Организация, соответствующая GDPR

Организация с сертификацией ISO 27001

Организация, соответствующая SOC II

Локализация Flutter: файлы ARB, intl и gen-l10n

Локализация Flutter адаптирует сообщения и интерфейс приложения для разных локалей. Во встроенном процессе flutter_localizations обеспечивает локализацию виджетов фреймворка, ресурсы ARB и gen-l10n формируют API AppLocalizations приложения, а intl отвечает за языкозависимые сообщения и форматирование.

Заказать демо

Заказать демо

Подготовьте небольшой пример ARB и проверки, которые требует ваша сборка

Проект локализации ПО в Smartcat: прогресс перевода по целевым языкам

Более 80 крупнейших компаний мира выбрали Smartcat

Настройка flutter_localizations и gen-l10n

В этом руководстве мы настроим небольшой пример на английском и испанском, разберём метаданные сообщений и сравним распространённые подходы на основе пакетов. Также покажем, что проверить, прежде чем подключать платформу перевода к проекту Flutter.

Используйте один генератор локализации и явно укажите расположение его входных и выходных файлов. В примере ниже предполагается существующее приложение Flutter со своими ограничениями SDK и обычной конфигурацией проекта.

Добавьте нужные записи в pubspec.yaml; не дублируйте разделы dependencies и flutter:

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: any

flutter:
  generate: true

Установите зависимости командой flutter pub get. Запись intl: any соответствует официальному шаблону настройки и позволяет механизму разрешения зависимостей выбрать версию, совместимую с Flutter SDK; сохраняйте lock-файл приложения и обычный процесс проверки зависимостей.

Создайте l10n.yaml в корне проекта:

arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart

Для настройки под конкретную версию SDK используйте актуальное руководство по интернационализации Flutter. В современном процессе сгенерированные файлы локализации хранятся в дереве исходного кода приложения. Пример импортирует из lib/l10n; не переносите старый синтетический импорт package:flutter_gen в новую конфигурацию. См. примечание о миграции сгенерированного кода.

Пишите файлы ARB с контекстом и типизированными плейсхолдерами

Файл ARB — это пакет ресурсов на основе JSON, содержащий сообщения и необязательные метаданные. Сохраняйте ключи сообщений стабильными, пишите сообщения целиком и используйте метаданные, чтобы объяснить, как применяется текст.

Создайте lib/l10n/app_en.arb:

{
  "@@locale": "en",
  "appTitle": "Reading room",
  "@appTitle": {
    "description": "Title of the sample reading application"
  },
  "welcomeName": "Welcome, {name}",
  "@welcomeName": {
    "description": "Greeting on the home screen",
    "placeholders": {
      "name": {"type": "String", "example": "Sam"}
    }
  },
  "savedBooks": "{count, plural, =0{No saved books} one{1 saved book} other{{count} saved books}}",
  "@savedBooks": {
    "description": "Number of books saved to the user's library",
    "placeholders": {
      "count": {"type": "int"}
    }
  },
  "readingState": "{state, select, active{Reading now} paused{Reading paused} other{Ready to read}}",
  "@readingState": {
    "description": "Reading status; state is active, paused or another value",
    "placeholders": {
      "state": {"type": "String"}
    }
  }
}

Создайте lib/l10n/app_es.arb:

{
  "@@locale": "es",
  "appTitle": "Sala de lectura",
  "welcomeName": "Te damos la bienvenida, {name}",
  "savedBooks": "{count, plural, =0{No hay libros guardados} one{1 libro guardado} other{{count} libros guardados}}",
  "readingState": "{state, select, active{Leyendo ahora} paused{Lectura en pausa} other{Todo listo para leer}}"
}

Шаблон содержит метаданные плейсхолдеров, которые использует генератор. Локализованный файл сохраняет ключи сообщений, имена плейсхолдеров и идентификаторы select, меняя только текст для пользователя. Эти испанские примеры иллюстрируют механику; текст для продакшена должен проверить носитель языка в реальном контексте продукта.

Запускайте flutter gen-l10n после добавления или изменения ресурсов. Считайте ошибки генератора проблемами в ресурсах, требующими исправления, и устраняйте их до включения файлов в релиз.

Подключите сгенерированные сообщения к MaterialApp

Зарегистрируйте сгенерированные делегаты и поддерживаемые локали, а затем получайте локализованные сообщения из контекста ниже виджета приложения.

После генерации добавьте следующий пример в lib/main.dart:

import 'package:flutter/material.dart';
import 'l10n/app_localizations.dart';

void main() => runApp(const ReadingApp());

class ReadingApp extends StatelessWidget {
  const ReadingApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: AppLocalizations.localizationsDelegates,
      supportedLocales: AppLocalizations.supportedLocales,
      home: const ReadingHome(),
    );
  }
}

class ReadingHome extends StatelessWidget {
  const ReadingHome({super.key});

  @override
  Widget build(BuildContext context) {
    final messages = AppLocalizations.of(context)!;
    return Scaffold(
      appBar: AppBar(title: Text(messages.appTitle)),
      body: Padding(
        padding: const EdgeInsetsDirectional.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(messages.welcomeName('Sam')),
            Text(messages.savedBooks(3)),
            Text(messages.readingState('active')),
          ],
        ),
      ),
    );
  }
}
ReadingHome имеет доступ к локализациям, которые предоставляет MaterialApp. Запрос AppLocalizations из контекста внешнего виджета будет искать выше провайдера, созданного этим виджетом. В документации по API Localizations объясняется, как локализованные ресурсы становятся доступны дочерним виджетам.

Сгенерированный API делает различие между простым сообщением и сообщением с аргументами видимым в коде. appTitle вызывается как значение; welcomeName, savedBooks и readingState получают значения, необходимые для построения сообщений.

Продуманно работайте с сообщениями plural и select

Сообщения plural выбирают формулировку в зависимости от количества и грамматики целевой локали. Сообщения select выбирают ветку по идентификатору, который передаёт приложение. Сохраняйте синтаксис и идентификаторы, переводя только текст каждой ветки.

Множественные формы

В примере =0 задаёт отдельное предложение для пустого состояния. Ветки one и other покрывают формы, используемые в языках примера; это не универсальный шаблон для любой целевой локали. Дайте проверяющему достаточно контекста, чтобы он указал формы, которых требует язык, и значения, которые может выдать ваше приложение.

Сообщения select

Значения вроде active и paused — это программные идентификаторы. Если их перевести, ресурс потеряет связь с кодом, который их передаёт. Ветка other служит запасным вариантом для значения, не совпадающего ни с одной именованной веткой.

Сообщения целиком

Не склеивайте фрагменты вроде переведённого глагола, числа и переведённого существительного. Цельное сообщение позволяет целевому языку управлять порядком слов. Опишите в брифе значения, ожидаемые диапазоны и контекст экрана, чтобы проверяющие оценивали предложение так, как его увидят пользователи.

Сравнение пакетов локализации Flutter

Выбирайте пакет с учётом формата ресурсов, архитектуры приложения и требований к поддержке. Пакеты ниже следуют разным соглашениям; использование нескольких генераторов для одних и тех же сообщений создаёт лишнюю путаницу.

ПодходТипичные ресурсыГенерация кодаРабота с множественными формамиКогда подходит
Встроенный gen-l10nARBГенерирует типизированные методы доступа DartСинтаксис сообщений в стиле ICUНужен официальный процесс работы с ресурсами Flutter
easy_localizationПо умолчанию JSON, доступны дополнительные загрузчикиНеобязательные инструменты генерацииAPI пакета для множественных форм и правила с учётом локалиВам подходят его соглашения о загрузке ресурсов и управлении локалями
Переводы GetXСловари с ключами по локалям в базовом документированном процессеНе требуется для базового API на словаряхtrPlural использует ключи для единственного и множественного числа; более сложную грамматику оценивайте отдельноПриложение уже использует GetX, и его модель переводов отвечает требованиям

Перед выбором изучите актуальную документацию easy_localization и документацию GetX. Протестируйте запасные варианты, параметры, категории множественных форм и процессы извлечения на своих реальных сообщениях. Удобный API для английских строк ещё не доказывает поддержку всех языков, которые вы планируете выпустить.

intl — не конкурирующая платформа управления переводами. Это набор утилит интернационализации, которые используются в процессах локализации. gen-l10n генерирует методы доступа приложения из ресурсов ARB. Отдельный пакет intl_utils тоже генерирует код локализации, но на момент проверки 30 октября 2026 года его страница была помечена как прекращённая. Проверьте статус поддержки, прежде чем использовать его в новом проекте.

Тестируйте переключение локалей, RTL и увеличение длины текста

Проверяйте и корректность ресурсов, и поведение переведённого текста в интерфейсе. Успешный разбор JSON или генерация кода не гарантируют, что экран понятен и удобен.

Переключение локалей

Для точечной проверки при разработке задайте MaterialApp.locale поддерживаемое значение, например const Locale('es'). Для выбора языка в продакшене храните выбранную локаль в состоянии приложения, сохраняйте предпочтение в соответствии с требованиями продукта и дайте возможность следовать языку системы. Проверяйте сохранённое предпочтение по списку локалей, которые действительно поддерживает текущая версия приложения.

Макеты с письмом справа налево

Используйте API направленной вёрстки для элементов, которые должны следовать направлению чтения. Проверяйте отступы, выравнивание, элементы навигации и контент со смешанным направлением в реальной локали с письмом справа налево. Не думайте, что зеркально отражать нужно каждую иконку: у стрелки навигации и символа бренда разная семантика.

Увеличение длины текста

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

Используйте практичную матрицу тестирования:

ПроверкаПример
Покрытие ресурсовУ каждого обязательного ключа шаблона есть осознанно заданное локализованное значение или запасной вариант
Аргументы сообщенийИмена и типы плейсхолдеров остаются совместимыми со сгенерированными методами
Поведение при разном количествеНоль, один и значения, задействующие дополнительные формы целевого языка
Поведение selectИзвестные состояния плюс неожиданное значение, которое попадает в other
Поведение локалиЯзык системы, явный выбор, перезапуск и неподдерживаемое предпочтение
ВёрсткаУдлинённый текст, крупный шрифт и контент с письмом справа налево
СмыслПроверка важных пользовательских сценариев носителями языка

Для языковой стороны процесса используйте процесс тестирования локализации. Показывайте лингвистическое утверждение и результаты функционального тестирования как отдельные подтверждения готовности релиза.

Планируйте локализацию Flutter web и видимость в поиске отдельно

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

В FAQ по веб-версии Flutter указано, что он ориентирован на приложения, и для статического веб-контента с большим объёмом текста рекомендуется документно-ориентированный подход. Рассмотрите отдельные HTML-страницы для маркетинга, справки и редакционного контента, если им важно органическое продвижение в поиске.

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

Проверьте процесс перевода ARB, прежде чем масштабировать его

Рассматривайте ARB как структурированный ресурс приложения, а не просто файл с текстовыми значениями. При передаче на перевод нужно сохранить ключи, метаданные, плейсхолдеры и синтаксис сообщений, а затем вернуть файлы, которые проходят генерацию и тесты приложения.

Среди документированных форматов программных проектов Smartcat — импорт JSON, YAML, Android XML, iOS .strings и LocJSON. Документация, изученная для этого руководства, не подтверждает встроенную поддержку ARB или проверенный процесс конвертации ARB в JSON. Не считайте, что смена расширения файла доказывает совместимость. См. документацию по программным проектам.

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

  1. Выберите показательный пример

    Выберите небольшой пример ARB с простыми строками, метаданными, типизированными плейсхолдерами, plural и select.

  2. Подтвердите импорт и экспорт

    Уточните у продуктовой команды поддерживаемый способ импорта и экспорта, включая обработку метаданных @ и сообщений ICU.

  3. Предоставьте языковые ресурсы и контекст

    Предоставьте глоссарий, при необходимости память переводов и понятный контекст для каждого сообщения.

  4. Переведите, сохранив структуру

    Переведите и проверьте пользовательский текст, сохранив программные идентификаторы и структуру.

  5. Сравните и восстановите

    Сравните полученные ресурсы с исходным контрактом и верните их по ожидаемым путям проекта.

  6. Сгенерируйте и протестируйте

    Запустите flutter gen-l10n, статический анализ и нужные тесты в окружении проекта с зафиксированной версией SDK.

  7. Проверьте и зафиксируйте

    Проверьте локализованный интерфейс и зафиксируйте утверждённую версию исходника.

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

Обсудить ваш процесс перевода Flutter

Частые сбои и что проверить в первую очередь

СимптомЧто проверить сначала
Не удаётся найти сгенерированный импортГенерация прошла успешно, и импорт совпадает с настроенным путём вывода
AppLocalizations.of(context) недоступенКонтекст находится ниже провайдера локализации приложения
У метода сообщения неожиданные аргументыМетаданные плейсхолдеров в шаблоне и сгенерированный API
select всегда показывает запасной вариантИдентификатор приложения точно совпадает с веткой ресурса
Отсутствует локальФайлы ресурсов, поддерживаемые локали и настройка выбора локали
Перевод ломается после экспортаКлючи, корректность JSON, метаданные и синтаксис ICU сохранились после полного цикла

Исправляйте самое раннее нарушение контракта, а не правьте сгенерированный Dart вручную. Сгенерированный код можно пересоздать; ручное исправление в нём, скорее всего, исчезнет при следующем изменении ресурсов.

Часто задаваемые вопросы

Что такое файл ARB во Flutter?

Application Resource Bundle — это файл на основе JSON с локализованными сообщениями и необязательными метаданными. Процесс gen-l10n во Flutter использует ресурсы ARB для генерации API локализации на Dart. Метаданные могут описывать сообщение и его плейсхолдеры, давая разработчикам и переводчикам более понятный контракт для каждого ключа.

Чем gen-l10n отличается от intl_utils?

Оба генерируют код локализации из ресурсов ARB, но это отдельные инструменты с разной конфигурацией и соглашениями о выходных данных. gen-l10n входит во встроенный процесс Flutter. Страница пакета intl_utils на момент подготовки руководства была помечена как прекращённая, поэтому проверьте статус поддержки, прежде чем выбирать его для новой реализации.

Как переводить файлы ARB?

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

Поддерживает ли Smartcat плейсхолдеры и множественные формы в ARB?

Изученная документация по программным проектам не подтверждает встроенную поддержку ARB или проверенный способ конвертации с сохранением всех возможностей ARB. Уточните способ импорта и экспорта у продуктовой команды и проверьте показательный полный цикл до внедрения. Общая поддержка JSON сама по себе не доказывает совместимость с ARB.

Работает ли локализация Flutter в вебе?

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

Передача на перевод должна быть такой же надёжной, как контракт ваших ресурсов

Подготовьте небольшой пример ARB и проверки, которые требует ваша сборка. Обсудим процесс до масштабирования на все языки и релизы.