← Назад к вопросам

Как бы реализовал поддержку локализации языков в проекте

2.0 Middle🔥 192 комментариев
#UI и вёрстка#Архитектура и паттерны#Опыт и софт-скиллы

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Реализация локализации в Android-проекте

Для поддержки локализации языков в Android-проекте я использую многоуровневый подход, основанный на официальных рекомендациях и лучших практиках. Вот ключевые шаги и принципы:

1. Структура ресурсов с локализацией

Основной механизм — создание директорий ресурсов с суффиксами кодов локалей (values-ru/, values-es/ и т.д.). Внутри размещаются файлы strings.xml, arrays.xml, plurals.xml:

<!-- values/strings.xml (по умолчанию, обычно английский) -->
<string name="welcome_message">Welcome to our app!</string>

<!-- values-ru/strings.xml -->
<string name="welcome_message">Добро пожаловать в наше приложение!</string>

Для графических ресурсов создаются аналогичные папки (drawable-ru/, drawable-xxhdpi-ru/), но на практике иконки часто остаются универсальными, а локализуются только текстовые элементы.

2. Динамическое изменение языка

Для смены языка во время выполнения приложения требуется обновить конфигурацию Locale и перезагрузить активность. Ключевой класс — Resources:

fun setAppLocale(languageCode: String, context: Context) {
    val locale = Locale(languageCode)
    Locale.setDefault(locale)
    
    val resources = context.resources
    val configuration = Configuration(resources.configuration)
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        configuration.setLocale(locale)
        context.createConfigurationContext(configuration)
    } else {
        @Suppress("DEPRECATION")
        configuration.locale = locale
        @Suppress("DEPRECATION")
        resources.updateConfiguration(configuration, resources.displayMetrics)
    }
}

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

3. Сохранение выбранного языка

Предпочтения языка хранятся в SharedPreferences или DataStore. При запуске приложения проверяем сохраненный язык в Application классе:

class LocalizedApp : Application() {
    override fun onCreate() {
        super.onCreate()
        val prefs = getSharedPreferences("settings", MODE_PRIVATE)
        val lang = prefs.getString("language", "en") ?: "en"
        setAppLocale(lang, this)
    }
}

Важно объявить кастомный Application в AndroidManifest.xml.

4. Сложные случаи локализации

Множественные формы (plurals):

<plurals name="items_count">
    <item quantity="one">%d item</item>
    <item quantity="other">%d items</item>
</plurals>

Форматирование дат и чисел:

val dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault())
val formattedDate = dateFormat.format(Date())

Направление текста (RTL) — Android автоматически поддерживает для арабского, иврита и др., но необходимо протестировать разметки.

5. Организация и инструменты

Структура проекта:

  • Все строки выносятся в strings.xml, никогда не хардкодятся в код
  • Отдельные файлы для больших текстов (strings_help.xml, strings_errors.xml)
  • Константы для ключей строк в StringKeys.kt

Инструменты:

  • Android Studio Translations Editor для визуального управления
  • Плагины типа Localization Helper для массового экспорта/импорта
  • Сервисы вроде Crowdin или Lokalise для командной работы с переводчиками

6. Архитектурные соображения

ViewModels/UseCases должны возвращать ID ресурсов, а не готовые строки:

// Неправильно
class UserViewModel {
    fun getMessage(): String = context.getString(R.string.welcome)
}

// Правильно
class UserViewModel {
    fun getMessage(): Int = R.string.welcome
}

UI-слой (Activities/Fragments) занимается получением конечных строк через getString(), что обеспечивает корректное переключение языков без пересоздания бизнес-логики.

7. Тестирование локализации

  • Тесты на различные длины строк (немецкие слова длиннее английских)
  • Проверка отображения в RTL-режиме
  • Инструмент: adb shell "setprop persist.sys.locale ru-RU; restart" для быстрого переключения языка на устройстве
  • Скриншот-тесты с разными локалями через Facebook screenshot-tests-for-android

8. Продвинутые техники

Динамические ресурсы: Использование Resources.getIdentifier() для загрузки ресурсов по имени:

val resId = resources.getIdentifier("image_${type}", "drawable", packageName)

Локализация метаданных: Файлы play-store-listings/ для описаний в магазинах приложений.

Поддержка региональных вариантов: values-en-rUS/, values-en-rGB для различий американского и британского английского.

Основные вызовы:

  • Синхронизация переводов при частых обновлениях интерфейса
  • Поддержка редких языков с особыми правилами форматирования
  • Динамическое обновление без перезапуска приложения (требует кастомной реализации)

Локализация — это не разовая задача, а процесс, интегрированный в цикл разработки. Успешная реализация требует автоматизации, инструментов для переводчиков и тщательного тестирования на реальных устройствах.