Wielu użytkowników wielojęzycznych ustawia język systemu na jeden język, np. angielski, ale w przypadku konkretnych aplikacji chcą wybrać inne języki, np. holenderski, chiński lub hindi. Aby ułatwić aplikacjom zapewnianie lepszych wrażeń użytkownikom, Android 13 wprowadza te funkcje dla aplikacji obsługujących wiele języków:
Ustawienia systemu: centralne miejsce, w którym użytkownicy mogą wybrać preferowany język dla każdej aplikacji.
Możesz skonfigurować aplikację tak, aby automatycznie generowała pliki potrzebne do obsługi wyboru języka według aplikacji i wyświetlania się w ustawieniach systemu. Więcej informacji znajdziesz w instrukcji włączania automatycznego obsługi języka w poszczególnych aplikacjach.
Dodatkowe interfejsy API: te publiczne interfejsy API, takie jak metody
setApplicationLocalesigetApplicationLocaleswLocaleManager, umożliwiają aplikacjom ustawienie w czasie działania języka innego niż język systemu.Te interfejsy API automatycznie synchronizują się z ustawieniami systemu, dlatego aplikacje, które używają ich do tworzenia niestandardowych selektorów języka w aplikacji, zapewniają użytkownikom spójne wrażenia niezależnie od tego, gdzie wybierają oni preferencje językowe. Publiczne interfejsy API pomagają też zmniejszyć ilość powtarzalnego kodu, obsługują dzielone pakiety APK i automatyczne tworzenie kopii zapasowych aplikacji, które służy do przechowywania ustawień języka użytkownika na poziomie aplikacji.
Aby zapewnić zgodność wsteczną z poprzednimi wersjami Androida, równoważne interfejsy API są też dostępne w AndroidX. Interfejsy API zgodne wstecznie działają jednak w kontekście AppCompatActivity, a nie w kontekście aplikacji, w przypadku Androida 12 (poziom interfejsu API 32) i starszych wersji. Dostęp do interfejsów API zgodnych wstecznie uzyskasz za pomocą biblioteki AppCompat w wersji 1.6.0 lub nowszej.
Omówienie wdrażania tej funkcji
W tabeli poniżej znajdziesz zalecane implementacje w zależności od różnych przypadków użycia.
| Przypadek użycia | Zalecana implementacja |
|---|---|
| W aplikacji nie ma selektora języka |
|
| Twoja aplikacja ma już selektor języka |
|
Ustawienia systemowe użytkowników
Od Androida 13 system zawiera centralną lokalizację w ustawieniach systemu, w której można ustawiać wybór języka według aplikacji. Aby mieć pewność, że języki aplikacji można skonfigurować w ustawieniach systemu na urządzeniach z Androidem 13 lub nowszym, włącz automatyczną obsługę języków w poszczególnych aplikacjach (zalecane) lub skonfiguruj obsługę ręcznie.
Włącz automatyczną obsługę języka w poszczególnych aplikacjach
Jest to zalecany sposób dodawania obsługi języka w poszczególnych aplikacjach, ponieważ nie wymaga modyfikacji plików XML.
Od Androida Studio Giraffe i AGP 8.1 możesz skonfigurować aplikację tak, aby automatycznie obsługiwała wybór języka według aplikacji. Na podstawie zasobów projektu AGP generuje plik LocaleConfig i dodaje do niego odwołanie w finalnym pliku manifestu, więc nie musisz już tego robić ręcznie. AGP korzysta z zasobów w folderach res modułów aplikacji i wszelkich zależności modułów biblioteki, aby określić, które ustawienia regionalne mają być uwzględnione w pliku LocaleConfig.
Oznacza to, że jeśli dodasz do aplikacji zasoby dla nowego języka, nie musisz aktualizować pliku LocaleConfig.
Pamiętaj, że funkcja automatycznego ustawiania języka dla poszczególnych aplikacji obsługuje aplikacje działające na Androidzie 13 (poziom API 33) lub nowszym. Aby korzystać z tej funkcji, musisz ustawić wartość
compileSdkVersion na 33 lub wyższą. Aby skonfigurować wybór języka według aplikacji w starszych wersjach Androida, nadal musisz używać interfejsów API i selektorów języka w aplikacji.
Aby włączyć automatyczne obsługiwanie języka w poszczególnych aplikacjach:
- Aby włączyć tę funkcję, użyj ustawienia
generateLocaleConfigw blokuandroidResources {}pliku na poziomie modułubuild.gradle.kts(plikubuild.gradle, jeśli używasz Groovy). Ta funkcja jest domyślnie wyłączona.
Kotlin
android {
androidResources {
generateLocaleConfig = true
}
}
Dynamiczny
android {
androidResources {
generateLocaleConfig true
}
}
- Określ domyślne ustawienia regionalne:
- W folderze
resmodułu aplikacji utwórz nowy plik o nazwieresources.properties. - W pliku
resources.propertiesustaw domyślny język za pomocą etykietyunqualifiedResLocale. Informacje o formatowaniu nazw regionów znajdziesz w artykule Jak tworzyć nazwy regionów.
- W folderze
AGP dodaje ten domyślny region i wszystkie określone przez Ciebie regiony alternatywne, korzystając z values-* katalogów w folderze res, do automatycznie wygenerowanego pliku LocaleConfig.
Jak tworzyć nazwy ustawień regionalnych
Aby utworzyć nazwy języków, połącz kod języka z opcjonalnymi kodami skryptu i regionu, rozdzielając je myślnikiem:
- Język: użyj 2- lub 3-literowego kodu ISO 639-2.
- Alfabet (opcjonalnie): użyj kodu ISO 15924.
- Region (opcjonalnie): użyj dwuliterowego kodu ISO 3166-1-alpha-2 lub trzycyfrowego kodu UN_M.49.
Jeśli na przykład domyślnym językiem jest angielski amerykański:
unqualifiedResLocale=en-US
Dodawanie obsługiwanych języków do ustawień systemu za pomocą aplikacji android:localeConfig
Możesz ręcznie skonfigurować aplikację, aby jej języki można było ustawiać w ustawieniach systemowych na urządzeniach z Androidem 13 lub nowszym. Aby to zrobić, utwórz plik XML locale_config i dodaj go do manifestu aplikacji za pomocą atrybutu android:localeConfig. Pominięcie wpisu android:localeConfig w pliku manifestu oznacza, że użytkownicy nie powinni mieć możliwości ustawienia języka aplikacji niezależnie od języka systemu w ustawieniach systemu.
Aby ręcznie dodać obsługiwane przez aplikację języki do ustawień systemowych użytkownika:
Utwórz plik o nazwie
res/xml/locale_config.xmli określ języki aplikacji, w tym ostateczny region rezerwowy, czyli region określony w plikures/values/strings.xml.Wymagania dotyczące formatu znajdziesz w artykule Jak tworzyć nazwy ustawień regionalnych. Listę najczęściej używanych ustawień regionalnych znajdziesz też w przykładzie
locale_config.xmlpliku.Na przykład w przypadku aplikacji obsługującej te języki plik
locale_config.xmlpowinien mieć taki format:- angielski (USA) jako ostateczny język zastępczy.
- angielski (Wielka Brytania)
- francuski
- japoński
- chiński (uproszczony, Makau)
- chiński (tradycyjny, Makau)
<?xml version="1.0" encoding="utf-8"?> <locale-config xmlns:android="http://schemas.android.com/apk/res/android"> <locale android:name="en-US"/> <locale android:name="en-GB"/> <locale android:name="fr"/> <locale android:name="ja"/> <locale android:name="zh-Hans-MO"/> <locale android:name="zh-Hant-MO"/> </locale-config>W pliku manifestu dodaj wiersz wskazujący ten nowy plik:
<manifest> ... <application ... android:localeConfig="@xml/locale_config"> </application> </manifest>
Możesz dynamicznie aktualizować localeConfig w aplikacji za pomocą LocaleManager.setOverrideLocaleConfig, aby dostosować zestaw języków wyświetlanych na liście języków poszczególnych aplikacji w Ustawieniach Androida. Dzięki temu możesz dostosowywać listę języków w poszczególnych regionach, przeprowadzać eksperymenty A/B i udostępniać zaktualizowane ustawienia regionalne, jeśli Twoja aplikacja korzysta z lokalizacji przesyłanych po stronie serwera, jak pokazano w tym przykładzie:
//For setOverrideLocaleConfig
val localeManager = applicationContext
.getSystemService(LocaleManager::class.java)
localeManager.overrideLocaleConfig = LocaleConfig(
LocaleList.forLanguageTags("en-US,ja-JP,zh-Hans-SG")
)
//For getOverrideLocaleConfig
// The app calls the API to get the override LocaleConfig
val overrideLocaleConfig = localeManager.overrideLocaleConfig
// If the returned overrideLocaleConfig isn't equal to NULL, then the app calls the API to get the supported Locales
val supportedLocales = overrideLocaleConfig.supportedLocales()
Dodatkowo edytory IME mogą teraz używać LocaleManager.getApplicationLocales, aby poznać język interfejsu bieżącej aplikacji i zaktualizować język klawiatury, jak pokazano poniżej:
val currentAppLocales: LocaleList = applicationContext.getSystemService(LocaleManager::class.java).getApplicationLocales(appPackageName)
Określanie obsługiwanych języków w Gradle
Jeśli nie ma ich jeszcze w pliku build.gradle na poziomie modułu aplikacji, określ te same języki za pomocą właściwości resourceConfigurations:
android {
...
defaultConfig {
resourceConfigurations += ["en", "en-rGB", "fr", "ja", "b+zh+Hans+MO", "b+zh+Hant+MO"]
}
}
Gdy występuje właściwość resourceConfigurations, system kompilacji uwzględnia w pliku APK tylko zasoby językowe dla tych określonych języków, co zapobiega uwzględnianiu przetłumaczonych ciągów tekstowych z innych bibliotek, które mogą obsługiwać języki, których Twoja aplikacja nie obsługuje. Więcej informacji znajdziesz w artykule Określanie języków obsługiwanych przez aplikację.
Jak użytkownicy wybierają język aplikacji w ustawieniach systemowych
Użytkownicy mogą wybrać preferowany język poszczególnych aplikacji w ustawieniach systemu. Mogą to zrobić na 2 sposoby:
Dostęp przez ustawienia System
Ustawienia > System > Języki i metody wprowadzania > Języki aplikacji > (wybierz aplikację)
Dostęp z ustawień Aplikacje
Ustawienia > Aplikacje > (wybierz aplikację) > Język
Obsługa selektorów języka w aplikacjach
W przypadku aplikacji, które mają selektor języka lub chcą go używać, do ustawiania i pobierania preferowanego języka użytkownika w aplikacji używaj publicznych interfejsów API zamiast niestandardowej logiki aplikacji. Jeśli używasz publicznych interfejsów API w selektorze języka w aplikacji, ustawienia systemowe urządzenia są automatycznie aktualizowane, aby pasowały do języka wybranego przez użytkownika w aplikacji.
Implementacja za pomocą Jetpack Compose
W przypadku aplikacji utworzonych w całości za pomocą Jetpack Compose system automatycznie obsługuje aktualizacje interfejsu, gdy zmienia się język aplikacji. Wywołanie interfejsu API w celu ustawienia nowego języka powoduje zmianę konfiguracji. Compose reaguje przez ponowne komponowanie interfejsu i automatyczne rozwiązywanie wywołań stringResource za pomocą nowych ustawień regionalnych.
Aby zapewnić zgodność wsteczną z Androidem 12 (interfejs API na poziomie 32) i starszymi wersjami, zdecydowanie zalecamy używanie biblioteki pomocy AndroidX (AppCompatDelegate) podczas implementowania selektora języka w aplikacji. Jeśli używasz tego podejścia, aktywność
hostująca interfejs Compose musi rozszerzać klasę AppCompatActivity. W razie potrzeby możesz jednak wdrożyć interfejsy API platformy bezpośrednio.
Poniższy fragment kodu pokazuje, jak odczytać bieżący język aplikacji i ustawić nowy w funkcji typu „composable”:
import androidx.appcompat.app.AppCompatDelegate
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.core.os.LocaleListCompat
@Composable
fun LanguageSelector() {
// Retrieve the currently configured app locale.
// If no app-specific locale is set, LocaleListCompat.get(0) returns null,
// so we safely fall back to a default (e.g., "en").
val appLocales = AppCompatDelegate.getApplicationLocales()
val currentLocaleTag = appLocales.get(0)?.toLanguageTag() ?: "en"
// Example UI: A button to toggle between English and Spanish
Button(
onClick = {
val newLanguageTag = if (currentLocaleTag == "en") "es" else "en"
val localeList = LocaleListCompat.forLanguageTags(newLanguageTag)
// Setting the locale re-creates the Activity by default,
// which automatically applies the new configuration to Compose.
AppCompatDelegate.setApplicationLocales(localeList)
}
) {
Text(
text = if (currentLocaleTag == "en") "Switch to Spanish" else "Switch to English"
)
}
}
Aby ustawić preferowany język użytkownika, poproś go o wybranie ustawień regionalnych w selektorze języka, a następnie ustaw tę wartość w systemie:
val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags("xx-YY")
// Call this on the main thread as it may require Activity.restart()
AppCompatDelegate.setApplicationLocales(appLocale)
Pamiętaj, że wywołanie setApplicationLocales ponownie tworzy Activity, chyba że Twoja aplikacja samodzielnie obsługuje zmiany konfiguracji regionalnej.
Użyj AppCompatDelegate.getApplicationLocales, aby pobrać preferowany język użytkownika. Użytkownik mógł wybrać język aplikacji w ustawieniach systemu lub w selektorze języka w aplikacji.
Obsługa Androida 12 i starszych wersji
Aby obsługiwać urządzenia z Androidem 12 (poziom interfejsu API 32) i starszym, poinformuj AndroidaX o obsłudze przechowywania ustawień regionalnych, ustawiając w pozycji manifestu usługi autoStoreLocales aplikacji wartość true i wartość android:enabled na false, jak pokazano w tym fragmencie kodu:AppLocalesMetadataHolderService
<application
...
<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
android:exported="false">
<meta-data
android:name="autoStoreLocales"
android:value="true" />
</service>
...
</application>
Pamiętaj, że ustawienie wartości autoStoreLocales na true powoduje odczyt blokujący w głównym wątku i może spowodować naruszenie zasad StrictMode diskRead i diskWrite, jeśli rejestrujesz naruszenia wątków. Więcej informacji znajdziesz w sekcji AppCompatDelegate.setApplicationLocales.
Niestandardowa obsługa pamięci
Pominięcie wpisu w pliku manifestu lub ustawienie wartości autoStoreLocales na false oznacza, że samodzielnie zarządzasz pamięcią. W takim przypadku musisz podać zapisane ustawienia regionalne przed onCreate w cyklu życia działania i ograniczyć wywołania AppCompatDelegate.setApplicationLocales w Androidzie 12 (poziom interfejsu API 32) lub starszym.
Jeśli aplikacja ma niestandardową lokalizację przechowywania ustawień regionalnych, zalecamy jednorazowe przekazanie danych między niestandardowym rozwiązaniem do przechowywania ustawień regionalnych a autoStoreLocales, aby użytkownicy mogli nadal korzystać z aplikacji w wybranym przez siebie języku. Jest to szczególnie istotne w przypadku pierwszego uruchomienia aplikacji po uaktualnieniu urządzenia do Androida 13. W takim przypadku możesz udostępnić istniejące już ustawienia regionalne, o które poprosił użytkownik, pobierając je z pamięci niestandardowej i przekazując do funkcji AppCompatDelegate.setApplicationLocales.
Wdrażanie za pomocą interfejsów API platformy Android
Zdecydowanie zalecamy używanie biblioteki AndroidX do implementowania selektorów języka w aplikacji, ale możesz też używać metod setApplicationLocales i getApplicationLocales w ramach Androida na urządzeniach z Androidem 13.
Poniższy fragment kodu pokazuje, jak ustawić i pobrać preferowany język użytkownika za pomocą usługi systemowej LocaleManager:
import android.app.LocaleManager
import android.content.Context
import android.os.Build
import android.os.LocaleList
import androidx.annotation.RequiresApi
import java.util.Locale
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
fun setAppLanguage(context: Context, languageTag: String) {
// 1. Retrieve the system service
val localeManager = context.getSystemService(LocaleManager::class.java)
// 2. Create a LocaleList from the language tag (e.g., "es-ES" or "ja")
val localeList = LocaleList(Locale.forLanguageTag(languageTag))
// 3. Set the locale. The system automatically updates the locale and
// restarts the app, including any necessary configuration updates.
localeManager.applicationLocales = localeList
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
fun getAppLanguage(context: Context): String {
val localeManager = context.getSystemService(LocaleManager::class.java)
val currentLocales = localeManager.applicationLocales
// Return the primary app locale, or fall back to the system default
return if (!currentLocales.isEmpty) {
currentLocales.get(0).toLanguageTag()
} else {
Locale.getDefault().toLanguageTag()
}
}
Dodatkowe sprawdzone metody
Zapoznaj się z tymi sprawdzonymi metodami.
Podczas wywoływania intencji w innej aplikacji weź pod uwagę język
Intencje związane z językiem mogą umożliwiać określenie języka, w którym ma działać wywoływana aplikacja. Przykładem jest funkcja EXTRA_LANGUAGE interfejsu Speech Recognizer API.
Uwzględnianie nagłówka Accept-Language na niestandardowej karcie Chrome
Rozważ dodanie nagłówka Accept-Language za pomocą
Browser.EXTRA_HEADERS, aby otwierać stronę internetową w języku aplikacji podczas wywoływania karty niestandardowej Chrome.
Jeśli usuniesz wybór języka według aplikacji w ustawieniach systemu, zresetuj ustawienia regionalne aplikacji do ustawień regionalnych systemu.
Jeśli usuniesz preferencje językowe aplikacji z ustawień systemu (usuwając android:localeConfig z AndroidManifest.xml aplikacji), użytkownicy nie będą mogli łatwo przywrócić domyślnego języka aplikacji.
Dlatego jeśli usuniesz android:localeConfig, rozważ zresetowanie ustawień regionalnych aplikacji do ustawień regionalnych systemu za pomocą LocaleListCompat.getEmptyLocaleList lub LocaleList.getEmptyLocaleList, jak pokazano w tym fragmencie kodu:
// Use the AndroidX APIs to reset to the system locale for backward and forward compatibility
AppCompatDelegate.setApplicationLocales(
LocaleListCompat.getEmptyLocaleList()
)
// Or use the Framework APIs for Android 13 and above to reset to the system locale
val context = LocalContext.current
context.getSystemService(LocaleManager::class.java)
.applicationLocales = LocaleList.getEmptyLocaleList()
Przykładowy plik locale_config.xml
Domyślnie Android zawiera tłumaczenia na poziomie systemu w ramach Projektu Android Open Source (AOSP) dla standardowego zestawu najczęściej używanych ustawień regionalnych.
Przykładowy plik locale_config.xml w tej sekcji pokazuje sugerowany format dla każdego z tych ustawień regionalnych. Skorzystaj z tego przykładowego pliku, aby utworzyć własny locale_config.xml plik dla zestawu języków, które obsługuje Twoja aplikacja.
<?xml version="1.0" encoding="utf-8"?>
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
<locale android:name="af"/> <!-- Afrikaans -->
<locale android:name="am"/> <!-- Amharic -->
<locale android:name="ar"/> <!-- Arabic -->
<locale android:name="as"/> <!-- Assamese -->
<locale android:name="az"/> <!-- Azerbaijani -->
<locale android:name="be"/> <!-- Belarusian -->
<locale android:name="bg"/> <!-- Bulgarian -->
<locale android:name="bn"/> <!-- Bengali -->
<locale android:name="bs"/> <!-- Bosnian -->
<locale android:name="ca"/> <!-- Catalan -->
<locale android:name="cs"/> <!-- Czech -->
<locale android:name="da"/> <!-- Danish -->
<locale android:name="de"/> <!-- German -->
<locale android:name="el"/> <!-- Greek -->
<locale android:name="en-AU"/> <!-- English (Australia) -->
<locale android:name="en-CA"/> <!-- English (Canada) -->
<locale android:name="en-GB"/> <!-- English (United Kingdom) -->
<locale android:name="en-IN"/> <!-- English (India) -->
<locale android:name="en-US"/> <!-- English (United States) -->
<locale android:name="es"/> <!-- Spanish (Spain) -->
<locale android:name="es-US"/> <!-- Spanish (United States) -->
<locale android:name="et"/> <!-- Estonian -->
<locale android:name="eu"/> <!-- Basque -->
<locale android:name="fa"/> <!-- Farsi -->
<locale android:name="fi"/> <!-- Finnish -->
<locale android:name="fil"/> <!-- Filipino -->
<locale android:name="fr"/> <!-- French (France) -->
<locale android:name="fr-CA"/> <!-- French (Canada) -->
<locale android:name="gl"/> <!-- Galician -->
<locale android:name="gu"/> <!-- Gujarati -->
<locale android:name="hi"/> <!-- Hindi -->
<locale android:name="hr"/> <!-- Croatian -->
<locale android:name="hu"/> <!-- Hungarian -->
<locale android:name="hy"/> <!-- Armenian -->
<locale android:name="in"/> <!-- Indonesian -->
<locale android:name="is"/> <!-- Icelandic -->
<locale android:name="it"/> <!-- Italian -->
<locale android:name="iw"/> <!-- Hebrew -->
<locale android:name="ja"/> <!-- Japanese -->
<locale android:name="ka"/> <!-- Georgian -->
<locale android:name="kk"/> <!-- Kazakh -->
<locale android:name="km"/> <!-- Khmer -->
<locale android:name="kn"/> <!-- Kannada -->
<locale android:name="ko"/> <!-- Korean -->
<locale android:name="ky"/> <!-- Kyrgyz -->
<locale android:name="lo"/> <!-- Lao -->
<locale android:name="lt"/> <!-- Lithuanian -->
<locale android:name="lv"/> <!-- Latvian -->
<locale android:name="mk"/> <!-- Macedonian -->
<locale android:name="ml"/> <!-- Malayalam -->
<locale android:name="mn"/> <!-- Mongolian -->
<locale android:name="mr"/> <!-- Marathi -->
<locale android:name="ms"/> <!-- Malay -->
<locale android:name="my"/> <!-- Burmese -->
<locale android:name="nb"/> <!-- Norwegian -->
<locale android:name="ne"/> <!-- Nepali -->
<locale android:name="nl"/> <!-- Dutch -->
<locale android:name="or"/> <!-- Odia -->
<locale android:name="pa"/> <!-- Punjabi -->
<locale android:name="pl"/> <!-- Polish -->
<locale android:name="pt-BR"/> <!-- Portuguese (Brazil) -->
<locale android:name="pt-PT"/> <!-- Portuguese (Portugal) -->
<locale android:name="ro"/> <!-- Romanian -->
<locale android:name="ru"/> <!-- Russian -->
<locale android:name="si"/> <!-- Sinhala -->
<locale android:name="sk"/> <!-- Slovak -->
<locale android:name="sl"/> <!-- Slovenian -->
<locale android:name="sq"/> <!-- Albanian -->
<locale android:name="sr"/> <!-- Serbian (Cyrillic) -->
<locale android:name="sr-Latn"/> <!-- Serbian (Latin) -->
<locale android:name="sv"/> <!-- Swedish -->
<locale android:name="sw"/> <!-- Swahili -->
<locale android:name="ta"/> <!-- Tamil -->
<locale android:name="te"/> <!-- Telugu -->
<locale android:name="th"/> <!-- Thai -->
<locale android:name="tr"/> <!-- Turkish -->
<locale android:name="uk"/> <!-- Ukrainian -->
<locale android:name="ur"/> <!-- Urdu -->
<locale android:name="uz"/> <!-- Uzbek -->
<locale android:name="vi"/> <!-- Vietnamese -->
<locale android:name="zh-Hans"/> <!-- Chinese (Simplified) -->
<locale android:name="zh-Hant"/> <!-- Chinese (Traditional) -->
<locale android:name="zu"/> <!-- Zulu -->
</locale-config>
Dodatkowe materiały
Więcej informacji znajdziesz w naszych przykładowych kodach, artykułach na blogu i filmach.
- Wybór języka według aplikacji – część 1 (blog)
- Wybór języka według aplikacji – część 2 (blog)
- Film Tworzenie z myślą o wielojęzycznym świecie
- Zasoby w funkcji Compose