Тестирование локализации мобильного приложения
Кнопка «Зарегистрироваться» на немецком стала «Registrieren» и вышла за границы UIButton — дизайнер не учёл, что немецкий в среднем длиннее русского на 35%. Или арабский RTL-текст перемешался с LTR-числами и выглядит как мусор. Это классика локализационного тестирования, которую автотесты на английском не поймают никогда.
Самые частые проблемы
Хардкод строк. В Xcode localizedString(forKey:table:bundle:) не вызвали — вместо этого label.text = "Welcome" прямо в коде. Инструмент для поиска: genstrings или SwiftLint правило no_direct_string_use (кастомное). На Android аналогично — строки в strings.xml vs inline в XML-лэйаутах vs конкатенация в Kotlin.
Форматирование дат, чисел, валюты. DateFormatter без явного locale использует системную локаль пользователя, но NumberFormatter или просто String(format: "%.2f", price) — нет. Американский формат 1,234.56 в немецкой локали должен быть 1.234,56. Ошибки такого рода не ломают UI, но выглядят непрофессионально.
Направление текста (BiDi). В арабской и иврит-локали layoutDirection = RTL. Иконки «назад/вперёд» меняются местами, padding и margin должны быть зеркальными. На iOS semanticContentAttribute = .forceRightToLeft на уровне view hierarchy. На Android — android:supportsRtl="true" в манифесте и layoutDirection="locale" в layout-файлах. Если хоть одна кастомная view рисует текст через Canvas.drawText без учёта RTL — будет баг.
Инструменты и подход
Pseudolocalization — первый и самый дешёвый тест. Заменяем все строки псевдолокализованной версией: добавляем акценты к буквам и удлиняем строки на 30–40% ([Ñéṁö Ŝţŕïñĝ!!!!!]). Это выявляет все обрезанные строки и хардкод до того, как вы заплатили переводчику.
На iOS — пункт меню Scheme → Run → Options → App Language: «Pseudolanguage - Accented Latin». На Android — LocaleList.setDefault(Locale("ar")) в Application.onCreate для тестирования RTL, или псевдолокаль en-XA через adb:
adb shell settings put global locale_overlay en-XA
Скриншот-тестирование по локалям. Paparazzi (Android) или SnapshotTesting (iOS) позволяют прогнать один тест с набором локалей:
@Test fun allLocales() {
for (locale in listOf("en", "de", "ar", "ja", "ru")) {
paparazzi.snapshot(locale = locale) {
RegistrationScreen()
}
}
}
Каждый прогон CI генерирует скриншоты — рецензент видит разницу визуально. Это ловит обрезанные кнопки автоматически.
Ручное тестирование с нативным носителем. Для семантики нет замены. Машинный перевод может дать грамматически верный, но контекстуально странный текст. «Нажмите сюда» в японском звучит грубо — нужно «お進みください». Это не автоматизируется.
| Проверка | Инструмент | Когда |
|---|---|---|
| Хардкод строк | SwiftLint / Android Lint | В CI на каждый PR |
| Обрезка UI | Pseudolocalization | При разработке |
| Скриншоты по локалям | Paparazzi / SnapshotTesting | В CI |
| RTL layout | Device/emulator с арабской локалью | Перед релизом |
| Форматирование чисел и дат | Unit-тесты с конкретными локалями | При разработке |
| Семантика перевода | Нативный носитель | Перед релизом |
Процесс работы
Аудит текущих локалей — сколько поддерживается, есть ли RTL. Настройка pseudolocalization в Scheme/build config. Добавление скриншот-тестов по ключевым экранам с набором локалей. Ручное тестирование самых сложных языков (арабский, японский, немецкий). Список найденных дефектов с воспроизведением.
Сроки — 2–4 дня на проект с 3–5 локалями. RTL-локали добавляют 1–2 дня, если layout не готовился к RTL с нуля.







