W wielu przypadkach użytkownicy wielojęzyczni ustawiają w swoim systemie język na jeden język, np. angielski, ale chcą wybrać inne języki dla poszczególnych aplikacji, np. niderlandzki, chiński czy hindi. Aby zapewnić użytkownikom lepsze wrażenia podczas korzystania z aplikacji, Android 13 wprowadza te funkcje w aplikacjach, które obsługują 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 ustawień języka poszczególnych aplikacji i pojawiały się w ustawieniach systemu. Aby dowiedzieć się więcej, zapoznaj się z instrukcjami włączania automatycznej obsługi języków dla poszczególnych aplikacji.
Dodatkowe interfejsy API: te publiczne interfejsy API, takie jak metody
setApplicationLocales()
igetApplicationLocales()
wLocaleManager
, pozwalają aplikacjom na ustawienie innego języka niż język systemu w czasie działania.Te interfejsy API automatycznie synchronizują się z ustawieniami systemu. Dlatego aplikacje korzystające z tych interfejsów API do tworzenia niestandardowych selektora języka zapewniają użytkownikom spójne wrażenia niezależnie od tego, gdzie wybiorą ustawienia językowe. Publiczne interfejsy API pomagają też zmniejszyć ilość powtarzającego się kodu. Obsługują dzielone pakiety APK i obsługują Automatyczną kopię zapasową aplikacji, która pozwala na przechowywanie ustawień języka na poziomie użytkownika.
Aby zapewnić zgodność wsteczną z poprzednimi wersjami Androida, odpowiedniki interfejsów API są też dostępne w AndroidzieX. Jednak w przypadku Androida 12 (poziom interfejsu API 32) i starszych interfejsów API zgodne wstecznie działają z kontekstem AppCompatActivity, a nie z kontekstem aplikacji. Uzyskaj dostęp do zgodnych wstecznie interfejsów API w wersji Appcompat 1.6.0 lub nowszej.
Omówienie wdrażania tej funkcji
W tabeli poniżej znajdziesz zalecane implementacje z uwzględnieniem różnych przypadków użycia.
Przypadek użycia | Zalecana implementacja |
---|---|
Twoja aplikacja nie ma selektora języka |
|
Twoja aplikacja ma już selektor języka |
|
Ustawienia systemu dla użytkowników
Począwszy od Androida 13, Android obejmuje scentralizowaną lokalizację w ustawieniach systemowych, w której można określić język według aplikacji. Aby mieć pewność, że języki aplikacji można konfigurować w ustawieniach systemu na urządzeniach z Androidem 13 lub nowszym, włącz automatyczną obsługę języków według aplikacji (zalecane) lub skonfiguruj obsługę ręcznie.
Włącz automatyczną obsługę języków dla poszczególnych aplikacji
Począwszy od Androida Studio Giraffe i AGP 8.1 możesz skonfigurować aplikację tak, aby automatycznie obsługiwała ustawienia języka według aplikacji. Na podstawie zasobów projektu AGP generuje plik LocaleConfig
i dodaje do niego odwołanie w końcowym pliku manifestu, dzięki czemu nie musisz już tego robić ręcznie. Aby określić języki do uwzględnienia w pliku LocaleConfig
, AGP korzysta z zasobów z folderów res
modułów aplikacji i wszystkich zależności tych modułów. Oznacza to, że gdy dodasz do aplikacji zasoby dla nowego języka, nie musisz się martwić o aktualizowanie pliku LocaleConfig
.
Pamiętaj, że funkcja automatycznego określania języka według aplikacji obsługuje aplikacje na Androidzie 13 (poziom API 33) lub nowszym. Aby korzystać z tej funkcji, musisz ustawić compileSdkVersion
na wartość 33 lub większą. Aby w poprzednich wersjach Androida skonfigurować preferencje językowe poszczególnych aplikacji, nadal musisz użyć interfejsów API i selektorów języka w aplikacji.
Aby włączyć automatyczną obsługę języków dla poszczególnych aplikacji, wykonaj te czynności:
- Aby włączyć tę funkcję, użyj ustawienia
generateLocaleConfig
w blokuandroidResources {}
plikubuild.gradle.kts
na poziomie modułu (plikbuild.gradle
, jeśli używasz Groovy). Ta funkcja jest domyślnie wyłączona.Kotlin
android { androidResources { generateLocaleConfig = true } }
Odlotowy
android { androidResources { generateLocaleConfig true } }
- Określ domyślny język:
- W folderze
res
modułu aplikacji utwórz nowy plik o nazwieresources.properties
. W pliku
resources.properties
ustaw domyślny język za pomocą etykietyunqualifiedResLocale
. Aby sformatować nazwy języków, przeczytaj sekcję Jak tworzyć nazwy języków.
- W folderze
AGP dodaje to domyślne ustawienie regionalne i wszelkie określone przez Ciebie alternatywne języki w katalogach values-*
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 opcjonalnym skryptem i kodami regionów, oddzielając je łącznikiem:
- Język: użyj dwu- lub trzyliterowego kodu ISO 639-1.
- Skrypt (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 Twoim domyślnym językiem jest angielski (USA):
unqualifiedResLocale=en-US
Użyj android:localeConfig
, aby dodać obsługiwane języki do ustawień systemu
Możesz ręcznie skonfigurować aplikację, aby mieć pewność, że jej języki można określić w ustawieniach systemu na urządzeniach z Androidem 13 lub nowszym. W tym celu utwórz plik XML locales_config
i dodaj go do pliku manifestu aplikacji za pomocą atrybutu android:localeConfig
. Pominięto parametr android:localeConfig
w pliku manifestu, ż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 języki aplikacji do ustawień systemowych użytkownika:
Utwórz plik o nazwie
res/xml/locales_config.xml
i określ języki aplikacji, w tym jej maksymalny zastępcze ustawienie regionalne, czyli język określony wres/values/strings.xml
.Wymagania związane z formatem znajdziesz w artykule Jak tworzyć nazwy języków. Listę najczęściej używanych języków znajdziesz w przykładowym pliku
locale_config.xml
.Na przykład plik
locales_config.xml
sformatuj w ten sposób dla aplikacji, która obsługuje te języki:- Angielski (Stany Zjednoczone) jako najbardziej uniwersalny 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/locales_config"> </application> </manifest>
Możesz dynamicznie aktualizować localeConfig
swojej aplikacji za pomocą LocaleManager.setOverrideLocaleConfig
, aby dostosować zestaw języków wyświetlanych na liście języków dla poszczególnych aplikacji w Ustawieniach Androida. Dzięki temu możesz dostosować listę języków w zależności od regionu, uruchomić eksperymenty A/B i podać zaktualizowane ustawienia regionalne, jeśli aplikacja korzysta z lokalizowania po stronie serwera, jak pokazano w tym przykładzie:
Kotlin
//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()
Java
//For setOverrideLocaleConfig mContext.getSystemService(LocaleManager.class).setOverrideLocaleConfig(new LocaleConfig(LocaleList.forLanguageTags("en-US,ja-JP,zh-Hans-SG"))); //For getOverrideLocaleConfig // The app calls the API to get the override LocaleConfig LocaleConfig overrideLocaleConfig = mContext.getSystemService(LocaleManager.class).getOverrideLocaleConfig(); // If the returned overrideLocaleConfig isn't equal to NULL, then the app calls the API to get the supported Locales LocaleList supportedLocales = overrideLocaleConfig.getSupportedLocales();
Ponadto edytorzy IME mogą teraz używać języka LocaleManager.getApplicationLocales
, aby poznać język interfejsu bieżącej aplikacji i zaktualizować go tak, jak w przykładzie:
Kotlin
val currentAppLocales: LocaleList = applicationContext.getSystemService(LocaleManager::class.java).getApplicationLocales(appPackageName)
Java
LocaleList currentAppLocales = mContext.getSystemService(LocaleManager.class).getApplicationLocales(appPackageName);
Określanie obsługiwanych języków w Gradle
Jeśli jeszcze go nie masz, podaj te same języki za pomocą właściwości resourceConfigurations
w pliku build.gradle
na poziomie modułu aplikacji:
android {
...
defaultConfig {
resourceConfigurations += ["en", "en-rGB", "fr", "ja", "b+zh+Hans+MO", "b+zh+Hant+MO"]
}
}
Gdy jest określona właściwość resourceConfigurations
, system kompilacji uwzględni w pliku APK tylko zasoby językowe tylko dla tych języków. Uniemożliwia to uwzględnianie przetłumaczonych ciągów znaków z innych bibliotek, które mogą obsługiwać języki nieobsługiwanych przez Twoją aplikację. Więcej informacji znajdziesz w sekcji poświęconej określaniu języków obsługiwanych przez aplikację.
Jak użytkownicy wybierają język aplikacji w ustawieniach systemu
Użytkownicy mogą wybrać preferowany język dla każdej aplikacji w ustawieniach systemowych. Dostęp do tych ustawień można uzyskać na 2 sposoby:
Dostęp za pomocą ustawień Systemu
Ustawienia > System > Języki i metody wprowadzania > Języki aplikacji > (wybierz aplikację)
Dostęp za pomocą ustawień aplikacji
Ustawienia > Aplikacje > (wybierz aplikację) > Język
Obsługa selektorów języka w aplikacji
W przypadku aplikacji, które mają już selektor języka w aplikacji lub chcesz go używać, do obsługi ustawień i pobierania preferowanego przez użytkownika języka używaj publicznych interfejsów API zamiast niestandardowych logiki aplikacji. Jeśli używasz publicznych interfejsów API w selektorze języka w aplikacji, ustawienia systemowe urządzenia są automatycznie aktualizowane tak, aby odpowiadały językowi wybranemu przez użytkownika w aplikacji.
Aby zapewnić wsteczną zgodność z poprzednimi wersjami Androida, przy implementowaniu selektora języka w aplikacji zalecamy skorzystanie z biblioteki pomocy AndroidaX. W razie potrzeby możesz też bezpośrednio wdrożyć interfejsy API platformy.
Implementacja z użyciem biblioteki pomocy AndroidX
Użyj metod setApplicationLocales()
i getApplicationLocales()
w Appcompat w wersji 1.6.0 lub nowszej. Zwróć uwagę, że zgodne wstecznie interfejsy API działają z kontekstem AppCompatActivity, a nie z kontekstem aplikacji na Androidzie 12 (poziom interfejsu API 32) i starszych.
Aby na przykład ustawić preferowany język użytkownika, poproś go o wybranie języka w selektorze języka, a następnie ustawienie tej wartości w systemie:
Kotlin
val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags("xx-YY") // Call this on the main thread as it may require Activity.restart() AppCompatDelegate.setApplicationLocales(appLocale)
Java
LocaleListCompat appLocale = 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()
odtwarza Activity
, chyba że aplikacja samodzielnie obsługuje zmiany konfiguracji języka.
Użyj AppCompatDelegate.getApplicationLocales()
, aby pobrać język preferowany przez użytkownika. Użytkownik mógł wybrać język aplikacji z ustawień systemu lub z selektora języka w aplikacji.
Obsługa Androida 12 i starszych
Aby zapewnić obsługę urządzeń z Androidem 12 (poziom interfejsu API 32) lub starszym, skonfiguruj AndroidX tak, aby obsługiwał pamięć lokalną, ustawiając wartość autoStoreLocales
na true
i android:enabled
na false
we wpisie manifestu aplikacji AppLocalesMetadataHolderService
, jak pokazano w tym fragmencie kodu:
<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 zablokowanie odczytu w wątku głównym i może spowodować naruszenie zasad StrictMode
diskRead
oraz diskWrite
, jeśli rejestrujesz naruszenia w wątkach. Więcej informacji znajdziesz w sekcji AppCompatDelegate.setApplicationLocales()
.
Niestandardowa obsługa pamięci masowej
Pominięcie wpisu w pliku manifestu lub ustawienie autoStoreLocales
na false
oznacza, że zarządzasz własnym miejscem na dane. W takim przypadku musisz podać zapisane języki przed onCreate
w cyklu życia aktywności i wywołaniami bramki AppCompatDelegate.setApplicationLocales()
na Androidzie 12 (poziom API 32) lub niższym.
Jeśli Twoja aplikacja ma niestandardową lokalizację przechowywania danych regionalnych, zalecamy jednorazowe połączenie między niestandardowym rozwiązaniem do przechowywania danych dla języka a usługą autoStoreLocales
, aby użytkownicy mogli nadal korzystać z aplikacji w preferowanym przez nich języku. Dotyczy to zwłaszcza sytuacji, gdy aplikacja jest uruchamiana po raz pierwszy na urządzeniu z Androidem 13. W takim przypadku możesz udostępnić istniejące języki żądane przez użytkownika, pobierając je z pamięci niestandardowej i przekazując je do AppCompatDelegate.setApplicationLocales()
.
Wdróż za pomocą interfejsów API platformy Android
Chociaż do wdrożenia selektora języka w aplikacji zdecydowanie zalecamy korzystanie z biblioteki pomocy AndroidaX, w przypadku urządzeń z Androidem 13 możesz też używać metod setApplicationLocales()
i getApplicationLocales()
w ramach platformy Androida.
Aby na przykład ustawić preferowany język użytkownika, poproś go o wybranie języka w selektorze języka, a następnie ustawienie tej wartości w systemie:
// 1. Inside an activity, in-app language picker gets an input locale "xx-YY"
// 2. App calls the API to set its locale
mContext.getSystemService(LocaleManager.class
).setApplicationLocales(new LocaleList(Locale.forLanguageTag("xx-YY")));
// 3. The system updates the locale and restarts the app, including any configuration updates
// 4. The app is now displayed in "xx-YY" language
Aby bieżący preferowany język użytkownika wyświetlał się w selektorze języka, aplikacja może odzyskać wartość z systemu:
// 1. App calls the API to get the preferred locale
LocaleList currentAppLocales =
mContext.getSystemService(LocaleManager.class).getApplicationLocales();
// 2. App uses the returned LocaleList to display languages to the user
Dodatkowe sprawdzone metody
Zapoznaj się z tymi sprawdzonymi metodami.
Podczas wywoływania intencji w innej aplikacji weź pod uwagę sformułowania
Intencje związane z językiem mogą umożliwiać określenie języka, w którym ma być wywoływana aplikacja. Jednym z przykładów jest funkcja EXTRA_LANGUAGE
z interfejsu Speech Recognizer API.
Rozważ nagłówek Accept-Language na karcie niestandardowej w Chrome
Rozważ dodanie nagłówka Accept-Language w Browser.EXTRA_HEADERS
, aby podczas wywoływania karty niestandardowej w Chrome strona internetowa otwierała się w języku Twojej aplikacji.
Jeśli usuniesz preferencje językowe poszczególnych aplikacji w ustawieniach systemu, zresetuj ustawienia regionalne aplikacji do ustawień regionalnych systemu.
Jeśli usuniesz preferencje językowe aplikacji z ustawień systemowych (przez usunięcie języka android:localeConfig
z sekcji AndroidManifest.xml
aplikacji), użytkownicy nie będą mogli łatwo przywrócić języka domyślnego systemu.
Dlatego, jeśli usuniesz android:localeConfig
, rozważ zresetowanie języka aplikacji do ustawień regionalnych systemu za pomocą LocaleListCompat.getEmptyLocaleList()
lub LocaleList.getEmptyLocaleList()
, tak jak w tym fragmencie kodu:
Kotlin
// 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()
Java
// 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 mContext.getSystemService(LocaleManager.class) .setApplicationLocales(LocaleList.getEmptyLocaleList());
Dodatkowe materiały
Więcej informacji znajdziesz w naszych przykładach kodu, artykułach na blogu i filmach.
- Ustawienia języka według aplikacji – część 1 – post na blogu
- Ustawienia języka według aplikacji – część 2 – post na blogu
- Przykładowe aplikacje
- Film na temat tworzenia treści z myślą o wielojęzycznym świecie
Przykładowy plik locale_config.xml
Android domyślnie włącza tłumaczenia na poziomie systemu w ramach projektu Android Open Source Project (AOSP) w ramach standardowego zestawu najczęściej używanych języków.
Przykładowy plik locale_config.xml
zawarty w tej sekcji zawiera zalecany format dla każdego z tych języków. Zapoznaj się z tym przykładowym plikiem, aby utworzyć własny plik locale_config.xml
dla zbioru języków obsługiwanych przez Twoją aplikację.
<?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>