2012-02-28 12 views
41

Więc chcę uzyskać wartość String w kilku lokalizacjach, bez względu na bieżące ustawienia regionalne urządzenia/aplikacji. Jak mam to zrobić?jak uzyskać ciąg znaków z różnych ustawień regionalnych w systemie Android?

Zasadniczo co potrzebne jest funkcją getString(int id, String locale) zamiast getString(int id)

Jak mogę to zrobić?

Dzięki

+1

jak to właściwie wdrożyłeś? Proszę o odpowiedź :) –

+0

jako zaakceptowana odpowiedź –

+0

to "ResourceBundle", które ma odnosić się do aktywów? lub czy mogą uzyskać dostęp do naszego folderu res? –

Odpowiedz

80

UWAGA Jeśli minimalna API jest 17+, idź prosto do dołu tej odpowiedzi. W przeciwnym razie, czytaj dalej ...

Jeśli masz różne res foldery dla różnych lokalizacjach, można zrobić coś takiego:

Configuration conf = getResources().getConfiguration(); 
conf.locale = new Locale("pl"); 
DisplayMetrics metrics = new DisplayMetrics(); 
getWindowManager().getDefaultDisplay().getMetrics(metrics); 
Resources resources = new Resources(getAssets(), metrics, conf); 
String str = resources.getString(id); 

Alternatywnie, można po prostu ponownie uruchomić działalność stosując metodę wskazywanego przez @ jyotiprakash.

UWAGA Wywołanie konstruktora takiego, jak to, zmienia coś wewnętrznie w systemie Android. Będziesz musiał wywołać konstruktora z oryginalnymi ustawieniami narodowymi, aby odzyskać dane z powrotem.

EDIT nieznacznie różnić (i nieco czystsze) przepis na pobieranie zasobów z określonej lokalizacji jest:

Resources res = getResources(); 
Configuration conf = res.getConfiguration(); 
Locale savedLocale = conf.locale; 
conf.locale = desiredLocale; // whatever you want here 
res.updateConfiguration(conf, null); // second arg null means don't change 

// retrieve resources from desired locale 
String str = res.getString(id); 

// restore original locale 
conf.locale = savedLocale; 
res.updateConfiguration(conf, null); 

Jak z poziomu API 17, należy użyć conf.setLocale() zamiast bezpośredniego ustawiania conf.locale. Spowoduje to prawidłową aktualizację kierunku układu konfiguracji, jeśli przełączasz się między ustawieniami od prawej do lewej i od lewej do prawej. (Kierunek Układ został wprowadzony w 17.)

Nie ma sensu w tworzeniu nowej Configuration przedmiot (jak sugeruje @Nulano w komentarzu), ponieważ wywołanie updateConfiguration zamierza zmienić pierwotną konfigurację uzyskać dzwoniąc res.getConfiguration().

Chciałbym zawęzić to do metody getString(int id, String locale), jeśli zamierzasz ładować kilka zasobów ciągów dla lokalizacji. Zmiana ustawień narodowych (przy użyciu dowolnego przepisu) wymaga, aby struktura wykonała wiele pracy, ponownie wiążąc wszystkie zasoby. Znacznie lepiej jest raz zaktualizować ustawienia lokalne, pobrać wszystko, czego potrzebujesz, a następnie przywrócić ustawienia regionalne.

EDIT (Dzięki @Mygod):

Jeżeli minimalny poziom API jest 17+, jest znacznie lepszym rozwiązaniem, jak pokazano na this answer w innym wątku. Na przykład, można utworzyć wiele Resource przedmiotów, po jednym dla każdego ustawienia trzeba, wraz z:

@NonNull Resources getLocalizedResources(Context context, Locale desiredLocale) { 
    Configuration conf = context.getResources().getConfiguration(); 
    conf = new Configuration(conf); 
    conf.setLocale(desiredLocale); 
    Context localizedContext = context.createConfigurationContext(conf); 
    return localizedContext.getResources(); 
} 

Następnie wystarczy pobrać zasoby chcesz z miejscowego Resource obiektu zwróconego przez tą metodą. Po odzyskaniu zasobów nie trzeba resetować niczego.

+1

Nie powinieneś dokonać nowej konfiguracji od tej zwróconej przez 'getResources(). GetConfiguration()'? Według kodu GrepCode zwraca lokalną instancję przechowywaną w zasobach. Zmiana pola lokalizacji to prawdopodobnie prawdziwy powód, dla którego Android jest zdezorientowany. Powinieneś prawdopodobnie wykonać 'conf = new Configuration (conf);' (aby sklonować zwróconą konfigurację) pomiędzy pierwszą a drugą linią. – Nulano

+0

@Nulano - Warto spróbować, ale nie sądzę, że to jest źródło tego, dlaczego Android jest "zdezorientowany" (jak to określasz). Spójrz na źródło dla konstruktora 'Resources', a zobaczysz, że tworzenie nowego obiektu' Resources' w ten sposób zmienia rzeczy na głębokości w zasobach procesu (najwyraźniej jeden singleton). Kiedy zdałem sobie sprawę, że rzeczy trzeba zresetować, nie zawracałem sobie głowy poszukiwaniem przyczyny. Alternatywnym (być może czystszym) podejściem do budowy nowego obiektu 'Resources' jest wywołanie' resources.updateConfiguration (conf, null) 'po zmianie ustawień regionalnych. –

+0

@TedHopp: Hello Sir, proszę spojrzeć na moje [pytanie] (http://stackoverflow.com/q/40398528). Byłbym wdzięczny, gdybyś pomógł. Dzięki ... :) –

-9

Co szukasz nazywa klasa ResourceBundle. Oto link:

Google Docs for ResourceBundle

+6

-1, bez wyjaśnienia –

+0

Ta odpowiedź nie ma sensu, ponieważ miesza jabłka i pomarańcze. Kiedy wstawisz ciąg do 'res/values ​​/ strings.xml', jak sugeruje ta odpowiedź, wartość ** ** nie jest dostępna za pośrednictwem' ResourceBundle'. Zamiast tego uzyskuje się do niego dostęp za pośrednictwem specyficznego dla Androida obiektu 'Resources' uzyskanego z' Kontekstu'. 'ResourceBundle' nie ma znaczenia dla tej operacji. Ponadto pole 'R.string.my_message' jest wartością' int', a metoda 'ResourceBundle.getString()' pobiera argument 'String', więc przykład kodu jest w najlepszym przypadku mylący. Wreszcie, w tej odpowiedzi nie ma roli "Locale" (kluczowy problem). –

+0

@TedHopp - masz rację, to był pierdnięcie mózgu. Usunięto sprzeczne informacje. – BitBank

8

Oto połączona wersja metod opisanych przez Ted Hopp. W ten sposób kod działa dla każdej wersji Androida: przykład

public static String getLocaleStringResource(Locale requestedLocale, int resourceId, Context context) { 
    String result; 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // use latest api 
     Configuration config = new Configuration(context.getResources().getConfiguration()); 
     config.setLocale(requestedLocale); 
     result = context.createConfigurationContext(config).getText(resourceId).toString(); 
    } 
    else { // support older android versions 
     Resources resources = context.getResources(); 
     Configuration conf = resources.getConfiguration(); 
     Locale savedLocale = conf.locale; 
     conf.locale = requestedLocale; 
     resources.updateConfiguration(conf, null); 

     // retrieve resources from desired locale 
     result = resources.getString(resourceId); 

     // restore original locale 
     conf.locale = savedLocale; 
     resources.updateConfiguration(conf, null); 
    } 

    return result; 
} 

Zastosowanie:

String englishName = getLocaleStringResource(new Locale("en"), id, R.string.name); 

Uwaga

Jak już wspomniano w oryginalnym odpowiedzi, to może być bardziej wydajne, aby zastąpić wielokrotne wywołanie powyższego kodu z pojedynczą zmianą konfiguracji i wieloma wywołaniami resources.getString().

Powiązane problemy