Реалізація динамічного перемикання мови у мобільному додатку

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1735 послуг
Реалізація динамічного перемикання мови у мобільному додатку
Середній
від 1 дня до 3 днів
Часті запитання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

Реалізація динамічного переключення мови у мобільній програмі

Переключення мови без перезапуску програми — завдання, яке виглядає тривіально, поки не натиснешся на те, що половина строк поменялась, а Fragment з ViewPager2 залишився на старій мові, тому що пережив смену конфігурації через setRetainInstance(true). Або DateTimeFormatter закешував Locale при першому виклику та тепер форматує дати на російській, хоча користувач вибрав англійську три екрани назад.

Чому це складніше, ніж кажеться

Android

Стандартний спосіб — AppCompatDelegate.setApplicationLocales(LocaleListCompat) з AndroidX (API 33+ нативно, AndroidX-бэкпорт працює до API 21). До AndroidX приходилось вручну пересоздавати Configuration та перезапускати Activity.

Проблема з setApplicationLocales: він зберігає вибір користувача у системних налаштуваннях програми. Це добре для інтеграції з системними Language Settings, але ломає сценарій, коли locale керується з бэкенда (мультитенантні програми, де мова задається профілем). Тоді потрібен власний ContextWrapper з перегрузкою attachBaseContext, який обгортає Context з потрібною Locale до того, як Activity почне інфлейтити layout.

ViewModel не пересоздається при зміні locale через setApplicationLocales — вона переживає зміну конфігурації. Строки всередину ViewModel (якщо вони туди попали — помилка архітектури) залишаться на старій мові. Строки у LiveData<String> або StateFlow<String> потрібно або зберігати як @StringRes Int та форматувати у View, або перевипускати після зміни locale.

RecyclerView.Adapter з закешованими строками потрібно явно дёрнути через notifyDataSetChanged() або краще через DiffUtil, інакше вже відрисовані елементи не перерисуються.

iOS

Bundle.main.localizedString(forKey:value:table:) читає строки з завантаженого бандла — то есть з бандла тієї локалі, що була активна при запуску. UserDefaults.standard.set(["ru"], forKey: "AppleLanguages") змінює мову лише після наступного запуску. Це обмеження iOS до версії 13.

Для iOS 13+ правильний шлях — Bundle swizzling: створюємо користувацький Bundle, який переопределяє localizedString(forKey:) та читає з бандла потрібної локалі. Типова реалізація — через розширення Bundle з збереженням поточної languageBundle у статичній змінній:

private var bundleKey: UInt8 = 0

class LanguageBundle: Bundle {
    override func localizedString(forKey key: String,
                                   value: String?,
                                   table tableName: String?) -> String {
        guard let bundle = objc_getAssociatedObject(self, &bundleKey) as? Bundle else {
            return super.localizedString(forKey: key, value: value, table: tableName)
        }
        return bundle.localizedString(forKey: key, value: value, table: tableName)
    }
}

extension Bundle {
    static func setLanguage(_ language: String) {
        object_setClass(Bundle.main, LanguageBundle.self)
        let path = Bundle.main.path(forResource: language, ofType: "lproj")
        let bundle = path.flatMap { Bundle(path: $0) } ?? Bundle.main
        objc_setAssociatedObject(Bundle.main, &bundleKey, bundle, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        NotificationCenter.default.post(name: .languageDidChange, object: nil)
    }
}

SwiftUI спрощує: environment(\.locale, Locale(identifier: "ar")) на кореневому View — та всі дочірні вью перерисуються з новою locale. Строки через LocalizedStringKey підхоплюються автоматично.

Але UIViewController-based екрани у SwiftUI-обёртці через UIViewControllerRepresentable потребують явного тригеру — NotificationCenter або @Published флаг перестройки.

Flutter

MaterialApp(locale: _currentLocale) + setState — стандартний підхід. Пакет flutter_localizations + intl для форматування. Смена locale через Provider або Riverpod (Notifier з Locale-стейтом) — UI перебудовується реактивно.

Кейс з практики: програма з cached_network_image — при зміні мови кеш зображень з alt-текстами скидався (тому що ключ кеша включав locale-залежний URL). Рішення — locale-agnostic ключі кеша.

Що робимо

  • Виибираємо механізм зберігання: SharedPreferences/UserDefaults або серверний профіль
  • Реалізуємо locale-провайдер з реактивним стейтом (Riverpod / Room + Flow / Combine)
  • Аудит всіх місць форматування дат, чисел, валют — NumberFormat, DateFormat не можна кешувати з locale
  • Тестуємо переключення на всіх ключових екранах включаючи deep link та push-notification landing pages

Часові рамки: 1-3 дні залежно від архітектури. Стоимість розраховується після аналізу кодової бази.