Мультиязичність мобільної програми (i18n)
Додати одну мову та додати підтримку N мов — різні архітектурні завдання. Коли мов дві — можна сійти з рук з прямолінійним підходом. Коли їх п'ять та більше — без правильно вистроєної i18n інфраструктури кожна нова мова додає біль: пропущені строки, сломані plurals, форматування дат під неправильну локаль, та неможливість віддати переклад команді без доступу до коду.
Архітектура i18n: від простого до правильного
iOS
Стандарт — Localizable.strings + .stringsdict для plurals + XLIFF для обміну з перекладачами. String(localized:) API (Swift 5.5+) — переважний спосіб, тому що підтримує interpolation, plural rules та коментар для перекладача в одному викликі:
let message = String(localized: "notifications.count \(count)",
comment: "Number of unread notifications in tab bar")
Для великих проектів з 1000+ строками та кількома командами — String Catalog (.xcstrings, Xcode 15+). Замінює розсипані .strings файли єдиним JSON з вбудованим diff та попередженнями про неперекладені строки прямо в IDE.
Android
strings.xml у res/values/ (базовий) + res/values-{lang}/ для кожної мови. plurals у тому ж файлі. Для параметричних строк — іменовані аргументи:
<string name="welcome_user">Ласкаво просимо, %1$s!</string>
%1$s замість %s — обов'язково при множинних аргументах, тому що порядок слів у різних мовах різний.
React Native
react-i18next — де факто стандарт. Namespace-и для розбивки по модулям (auth, profile, feed), lazy loading namespace-ів щоб не грузити всі переводи відразу. Plural forms через i18next-icu плагін з ICU Message Format — він коректно обробляє російські, українські, польські plural rules без написання користувацьких resolver-ів.
Flutter
flutter_localizations + intl пакет. ARB-файли (Application Resource Bundle) — стандарт для Flutter i18n. flutter gen-l10n генерує type-safe Dart-класи з ARB-файлів, що виключає опечатки в ключах строк:
Text(AppLocalizations.of(context)!.notificationCount(count))
Замість строкових ключів — методи з параметрами. Plural forms описуються прямо в ARB через ICU syntax.
Динамічна смена мови
Системна локаль — не завжди те, що потребує користувач. Частина програм надає вибір мови у налаштуваннях. На iOS це офіційно підтримується через CFBundleLocalizations у Info.plist + зберігання виборі користувача. На Android — через AppCompatDelegate.setApplicationLocales() (AndroidX API, Android 13+) або ручну заміну Resources.updateConfiguration() на старих версіях.
При зміні мови в рантаймі важливо: всі форматтери (дат, чисел, валют) пересоздати з новою locale. Закешовані DateFormatter з hardcoded locale залишаться на старій мові.
Plural forms: зведена таблиця
| Мова | Кількість форм | Складність |
|---|---|---|
| Англійська | 2 (one/other) | Низька |
| Українська | 3 (one/few/many) | Середня |
| Російська | 3 (one/few/many) | Середня |
| Польська | 4 (one/few/many/other) | Висока |
| Арабська | 6 форм | Дуже висока |
| Китайська | 1 форма | Немає |
ICU Message Format + i18next-icu або Flutter intl обробляють всі ці варіанти автоматично. Ручне ветвлення у коді по кількості форм — антипаттерн, який ломається при додаванні кожної нової мови.
CI/CD та якість перекладів
Інтегруємо перевірки у пайплайн:
-
Lint для строк:
twine(iOS),android-strings-lint— знаходять пропущені переводи, невикористані ключі, неекрановані спецсимволи -
Screenshot тести:
fastlane snapshot(iOS) абоscreengrab(Android) — автоматично роблять скриншоти на всіх мовах, регресію UI видно відразу - Translation Management System: Phrase, Lokalise, Crowdin — синхронізують строки між кодом та командою перекладачів через API, без ручного експорту/імпорту XLIFF
Часові рамки: від трьох до десяти робочих днів залежно від платформи, кількості мов та наявності готової інфраструктури.







