Почему локализация — это не просто перевод

Многие думают: отдал файлы переводчику, вставил строки — и готово. На практике это работает примерно так же, как «выучить английский за 30 дней по приложению».

Локализация (l10n) — это адаптация продукта под конкретный рынок: язык, форматы дат и чисел, направление текста, культурные особенности, иногда даже цвета. Перевод — лишь часть этой работы.

По данным App Annie, 70% загрузок в App Store приходится на страны, где английский не является основным языком. Конверсия в загрузку растёт на 26% после добавления описания на родном языке пользователя. Это не абстрактная статистика — это деньги, которые утекают мимо.

Как устроена локализация в Xcode

iOS предоставляет удобную инфраструктуру из коробки. Базовый механизм — файлы .strings и .stringsdict.

Файлы .strings

Каждая строка в приложении получает уникальный ключ:

let title = NSLocalizedString("onboarding.welcome.title", comment: "Заголовок экрана онбординга")

В директории en.lproj лежит Localizable.strings:

"onboarding.welcome.title" = "Welcome to the App";

В ru.lproj — его русский аналог:

"onboarding.welcome.title" = "Добро пожаловать";

iOS сам выбирает нужный файл по языку устройства.

String Catalogs — новый подход с Xcode 15

В Xcode 15 появился String Catalog — формат .xcstrings. Это JSON-файл, который хранит все языки сразу и показывает состояние перевода прямо в редакторе: зелёная галочка — переведено, жёлтый значок — устарело, красный — не переведено.

Мигрировать со старого формата легко: Edit → Convert → To String Catalog, и Xcode сделает всё сам.

Множественные числа — самое неприятное место

В английском два варианта: «1 item» и «2 items». В русском — четыре: «1 элемент», «2 элемента», «5 элементов», «21 элемент». В арабском — шесть форм. В китайском — одна.

Для этого существует .stringsdict — XML-файл, описывающий правила для каждого языка:

<key>items.count</key>
<dict>
    <key>NSStringLocalizedFormatKey</key>
    <string>%#@items@</string>
    <key>items</key>
    <dict>
        <key>NSStringFormatSpecTypeKey</key>
        <string>NSStringPluralRuleType</string>
        <key>NSStringFormatValueTypeKey</key>
        <string>d</string>
        <key>one</key>
        <string>%d элемент</string>
        <key>few</key>
        <string>%d элемента</string>
        <key>many</key>
        <string>%d элементов</string>
        <key>other</key>
        <string>%d элемента</string>
    </dict>
</dict>

Ошибка, которую делают почти все — пишут в коде что-то вроде:

// Так делать нельзя
let text = count == 1 ? "1 товар" : "\(count) товаров"

Это работает только для русского и только если разработчик помнит про 21, 22, 11, 12. Обычно не помнит — и появляется «21 товаров».

Форматирование дат, чисел и валюты

В США дата выглядит так: 06/10/2026. В России — 10.06.2026. В Японии — 2026年6月10日. Если захардкодить формат — кто-то обязательно увидит что-то странное.

Используй DateFormatter с локалью:

let formatter = DateFormatter()
formatter.dateStyle = .long
formatter.locale = Locale.current
let dateString = formatter.string(from: date)

То же самое с числами и валютой:

let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.locale = Locale.current
let price = formatter.string(from: 9.99)

В США получим $9.99, в России — 9,99 ₽, в Германии — 9,99 €. Никакого хардкода, никаких проблем.

RTL — языки справа налево

Арабский и иврит читаются справа налево. Если думаешь, что это просто «текст в другую сторону» — нет. Весь интерфейс зеркалируется: кнопка «назад» переходит направо, иконки меняют положение, вся вёрстка переворачивается.

Хорошая новость: iOS делает большую часть работы автоматически, если используешь Auto Layout с Leading/Trailing вместо Left/Right. Это правило номер один при вёрстке под RTL.

// Правильно
view.leadingAnchor.constraint(equalTo: container.leadingAnchor)

// Неправильно — сломается в RTL
view.leftAnchor.constraint(equalTo: container.leftAnchor)

Для кастомных иконок с направленностью (стрелки, кнопки «вперёд/назад») добавь флаг зеркального отображения:

image.imageFlipsForRightToLeftLayoutDirection = true

Проверяй RTL прямо в симуляторе: Settings → General → Language & Region → установи Arabic.

Культурные нюансы: когда перевод не спасает

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

Несколько примеров:

  • Цвет белый в азиатских культурах ассоциируется с трауром, а не чистотой.
  • Имена в США: имя + фамилия. В Японии: фамилия + имя. Форма с полями «First Name» / «Last Name» ставит японского пользователя в тупик.
  • Жест «большой палец вверх» — нейтральный в США, оскорбительный в ряде стран Ближнего Востока.
  • Номер телефона в разных странах имеет разную длину и формат — валидация «10 цифр» сломает регистрацию для половины мира.

Это мелочи, но именно они создают ощущение «своего» продукта.

Локализация в App Store

Люди находят приложение ещё до того, как его скачают. Страница в App Store — тоже часть локализации.

Что нужно перевести:

  • Название приложения
  • Подзаголовок
  • Описание
  • Ключевые слова (по 100 символов на язык, каждое слово работает независимо)
  • Скриншоты — текст на них тоже должен быть на нужном языке

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

Ключевые слова в App Store индексируются по каждому рынку независимо. То, что работает для США, может не работать для Германии. Для анализа ключевых слов по странам используй AppFollow или Sensor Tower.

Инструменты и автоматизация

Экспорт и импорт переводов

Xcode умеет экспортировать все строки в формат XLIFF — его понимают большинство бюро переводов и CAT-инструментов (SDL Trados, memoQ):

xcodebuild -exportLocalizations -localizationPath ./Localizations -project App.xcodeproj

После перевода импортируй обратно:

xcodebuild -importLocalizations -localizationPath ./Localizations/ru.xcloc -project App.xcodeproj

Сервисы для управления переводами

  • Lokalise — удобная интеграция с Xcode, GitHub и GitLab. Переводчики работают в браузере, разработчики получают файлы через API или GitHub Actions.
  • Phrase — популярен в корпоративном сегменте.
  • POEditor — бюджетный вариант для небольших приложений.
  • Crowdin — удобен для open-source проектов, есть бесплатный план.

Для приложения с одним-двумя языками хватит ручного XLIFF-экспорта. Для продукта с постоянными обновлениями Lokalise окупается быстро.

Pseudo-localization для тестирования вёрстки

Все строки заменяются похожими символами, которые занимают больше места: «Hello» превращается в «[Héllö Wörld!!!]». Смысл — найти проблемы с вёрсткой до прихода реальных переводов.

Немецкий в среднем на 30% длиннее английского. Финский — иногда вдвое. Если кнопка рассчитана ровно под английский текст — в немецком она сломается.

Включается через схему запуска: Edit Scheme → Options → App Language → Accented Pseudo-Language.

Типичные ошибки

Конкатенация строк. Никогда не склеивай переведённые части:

// Плохо — в других языках порядок слов будет другим
let text = "У вас " + count + " " + NSLocalizedString("messages", ...)

// Хорошо — format specifiers
let format = NSLocalizedString("messages.count", comment: "")
let text = String(format: format, count)
// messages.count = "У вас %d сообщений"

Картинки с текстом. Если в дизайне есть изображение с надписью — её нужно либо убрать, либо делать отдельную версию для каждой локали.

Предположения о длине строки. «Username» — 8 символов. «Benutzername» — 12. «Käyttäjänimi» (финский) — 12. Делай поля и кнопки гибкими.

Перевод без контекста. Переводчик получает ключи вроде button.ok, title.main, label.empty. Без контекста непонятно: это кнопка подтверждения платежа или удаления данных. Используй поле comment в NSLocalizedString — оно именно для этого.

Хардкод локали. Иногда разработчик явно пишет Locale(identifier: "en_US") для форматирования. Это ломает всё для всех остальных.

Когда и как выходить на новый рынок

Минимальный старт. Локализовать только самые важные экраны — онбординг, платёжный флоу, настройки. Остальное оставить на английском. Лучше, чем ничего, и позволяет проверить спрос.

A/B тест перед вложениями. Выпусти приложение в новой стране на английском, посмотри органику за месяц. Если есть загрузки — локализуй и сравни конверсию.

Приоритет по объёму рынка. Топ рынков по загрузкам в App Store: США, Китай, Япония, Германия, Великобритания, Франция, Бразилия. Китай требует отдельного внимания — там свои правила дистрибуции и нужен местный партнёр.

Машинный перевод как черновик. DeepL даёт хорошее качество для европейских языков. Используй его как черновик, который потом правит носитель языка — экономия в 3-5 раз по сравнению с переводом с нуля.

Ориентир по стоимости: профессиональный перевод 1000 слов стоит 50-150 долларов в зависимости от языка. Японский и арабский дороже европейских.

Как организовать процесс

Хорошая локализация — не разовый спринт, а постоянный процесс. Несколько правил, которые работают:

  1. Каждая новая строка сразу получает ключ и комментарий — не «потом добавим», а сейчас.
  2. Переводы обновляются вместе с релизом, не после.
  3. Есть ответственный — разработчик или PM, который следит за полнотой.
  4. CI/CD проверяет отсутствие непереведённых строк перед сборкой. Инструмент swiftgen или простой скрипт с проверкой .xcstrings справится с задачей.

Если нужна помощь с организацией переводного процесса или автоматизацией рутины — в REEXY занимаются интеграцией подобных решений в рамках разработки и поддержки мобильных проектов.

Главное

Технически iOS даёт всё необходимое: String Catalogs, .stringsdict для множественных чисел, автоматическое RTL, форматтеры с локалью. Нужно только правильно использовать это с самого начала.

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