🌍 Locale

Zarządzanie językiem aplikacji z dynamiczną zmianą bez restartu.

Przegląd

Moduł Locale umożliwia:

Podstawowe użycie

Pobieranie aktualnego języka

// Aktualny Locale
val locale = ADict.Locale.getCurrentLocale()

// Kod języka (np. "pl", "en")
val language = ADict.Locale.getCurrentLanguage()

// Kod kraju (np. "PL", "US")
val country = ADict.Locale.getCurrentCountry()

Zmiana języka

// Zmień język
ADict.Locale.setLocale("pl")     // Polski
ADict.Locale.setLocale("en")     // Angielski
ADict.Locale.setLocale("de")     // Niemiecki
ADict.Locale.setLocale("pl-PL")  // Polski (Polska) - pełny tag

// Reset do systemowego
ADict.Locale.resetToSystemDefault()

Integracja z Activity

Aby zmiana języka działała poprawnie, użyj wrap() w każdej Activity:

BaseActivity

abstract class BaseActivity : AppCompatActivity() {

    override fun attachBaseContext(newBase: Context) {
        // Wrap context z wybranym locale
        super.attachBaseContext(ADict.Locale.wrap(newBase))
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Opcjonalnie: aplikuj do resources
        ADict.Locale.applyToResources(resources)
    }
}

Callback na zmianę języka

// Nasłuchuj na zmiany
ADict.Locale.onLocaleChanged { locale ->
    // Odśwież UI lub recreate activity
    recreate()
}

// Lub z Flow w ViewModel
class SettingsViewModel : ViewModel() {
    fun changeLanguage(code: String) {
        ADict.Locale.setLocale(code)
        // UI automatycznie się odświeży przez callback
    }
}

Lista dostępnych języków

Konfiguracja

// Zdefiniuj dostępne języki w aplikacji
ADict.Locale.setAvailableLocales(listOf(
    "pl", "en", "de", "fr", "es"
))

Pobieranie listy

// Pobierz listę z informacjami
val locales = ADict.Locale.getAvailableLocales()

locales.forEach { info ->
    Log.d("Locale", """
        Kod: ${info.code}
        Nazwa: ${info.displayName}     // np. "Polski" (w aktualnym języku)
        Natywna: ${info.nativeName}    // np. "Polski" (w tym języku)
    """)
}

// Sprawdź czy język jest dostępny
val isAvailable = ADict.Locale.isAvailable("pl")

Budowanie UI wyboru języka

class LanguagePickerActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val recyclerView = findViewById(R.id.languageList)
        val languages = ADict.Locale.getAvailableLocales()
        val currentCode = ADict.Locale.getCurrentLanguage()

        recyclerView.adapter = LanguageAdapter(languages, currentCode) { selected ->
            ADict.Locale.setLocale(selected.code)
            recreate()
        }
    }
}

class LanguageAdapter(
    private val languages: List,
    private val currentCode: String,
    private val onSelect: (Locale.LocaleInfo) -> Unit
) : RecyclerView.Adapter<...>() {

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val lang = languages[position]

        // Pokaż flagę emoji
        val flag = ADict.Locale.getFlagEmoji(lang.code.uppercase())

        holder.flagText.text = flag
        holder.nameText.text = lang.nativeName
        holder.checkIcon.isVisible = lang.code == currentCode

        holder.itemView.setOnClickListener {
            onSelect(lang)
        }
    }
}

Remote Config

// Synchronizuj z Firebase Remote Config
// Jeśli klucz "forced_locale" ma wartość np. "en",
// aplikacja przełączy się na angielski
ADict.Locale.syncWithRemoteConfig("forced_locale")

// Użyj w Application.onCreate po pobraniu Remote Config
ADict.Config.remoteConfig?.fetchAndActivate()?.addOnCompleteListener {
    ADict.Locale.syncWithRemoteConfig()
}

Stałe kodów języków

// Użyj gotowych stałych
ADict.Locale.setLocale(Locale.Codes.POLISH)    // "pl"
ADict.Locale.setLocale(Locale.Codes.ENGLISH)   // "en"
ADict.Locale.setLocale(Locale.Codes.GERMAN)    // "de"
ADict.Locale.setLocale(Locale.Codes.FRENCH)    // "fr"
ADict.Locale.setLocale(Locale.Codes.SPANISH)   // "es"
ADict.Locale.setLocale(Locale.Codes.ITALIAN)   // "it"
ADict.Locale.setLocale(Locale.Codes.RUSSIAN)   // "ru"
ADict.Locale.setLocale(Locale.Codes.CHINESE)   // "zh"
ADict.Locale.setLocale(Locale.Codes.JAPANESE)  // "ja"
ADict.Locale.setLocale(Locale.Codes.UKRAINIAN) // "uk"
// ... i więcej

Narzędzia pomocnicze

// Pobierz nazwę wyświetlaną dla kodu
val displayName = ADict.Locale.getDisplayName("de") // "Niemiecki" (w aktualnym języku)

// Pobierz natywną nazwę
val nativeName = ADict.Locale.getNativeName("de") // "Deutsch"

// Pobierz flagę emoji dla kraju
val flag = ADict.Locale.getFlagEmoji("PL") // "🇵🇱"
val usFlag = ADict.Locale.getFlagEmoji("US") // "🇺🇸"

Przykład: Kompletna implementacja

// Application.kt
class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()

        ADict.init(this, BuildConfig.DEBUG)

        // Skonfiguruj dostępne języki
        ADict.Locale.setAvailableLocales(listOf(
            "pl", "en", "de", "es", "fr"
        ))
    }
}

// BaseActivity.kt
abstract class BaseActivity : AppCompatActivity() {
    override fun attachBaseContext(newBase: Context) {
        super.attachBaseContext(ADict.Locale.wrap(newBase))
    }
}

// SettingsFragment.kt
class SettingsFragment : Fragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val currentLang = ADict.Locale.getCurrentLanguage()
        val languages = ADict.Locale.getAvailableLocales()

        // Pokaż aktualny język
        binding.currentLanguage.text = languages
            .find { it.code == currentLang }
            ?.nativeName ?: currentLang

        // Obsłuż kliknięcie
        binding.languageRow.setOnClickListener {
            showLanguagePicker(languages)
        }

        // Nasłuchuj na zmiany
        ADict.Locale.onLocaleChanged { locale ->
            // Odśwież aktywność
            requireActivity().recreate()
        }
    }

    private fun showLanguagePicker(languages: List) {
        val items = languages.map { "${ADict.Locale.getFlagEmoji(it.code.uppercase())} ${it.nativeName}" }

        AlertDialog.Builder(requireContext())
            .setTitle("Wybierz język")
            .setItems(items.toTypedArray()) { _, which ->
                ADict.Locale.setLocale(languages[which].code)
            }
            .show()
    }
}