🌍 Locale
Zarządzanie językiem aplikacji z dynamiczną zmianą bez restartu.
Przegląd
Moduł Locale umożliwia:
- Dynamiczną zmianę języka aplikacji
- Zapisywanie preferencji językowych
- Integrację z Remote Config (wymuszony język)
- Obsługę wielu języków z łatwym UI wyboru
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()
}
}