Czy można programowo zmienić język aplikacji, nadal korzystając z zasobów Androida?
Jeśli nie, to czy można poprosić o zasób w określonym języku?
Chciałbym umożliwić użytkownikowi zmianę języka aplikacji z aplikacji.
Czy można programowo zmienić język aplikacji, nadal korzystając z zasobów Androida?
Jeśli nie, to czy można poprosić o zasób w określonym języku?
Chciałbym umożliwić użytkownikowi zmianę języka aplikacji z aplikacji.
Odpowiedzi:
To jest możliwe. Możesz ustawić ustawienia regionalne. Jednak nie poleciłbym tego. Wypróbowaliśmy to na wczesnych etapach, w zasadzie walczy z systemem.
Mamy ten sam wymóg zmiany języka, ale postanowiliśmy zgodzić się na fakt, że interfejs użytkownika powinien być taki sam jak interfejs telefonu. Działało przez ustawienie regionalne, ale było zbyt błędne. I musisz to ustawić za każdym razem, gdy wprowadzasz aktywność (każdą aktywność) z mojego doświadczenia. oto kod, jeśli nadal go potrzebujesz (ponownie, nie polecam tego)
Resources res = context.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.setLocale(new Locale(language_code.toLowerCase())); // API 17+ only.
// Use conf.locale = new Locale(...) if targeting lower versions
res.updateConfiguration(conf, dm);
Jeśli masz treści specyficzne dla języka - możesz zmienić tę bazę w zależności od ustawienia.
aktualizacja 26 marca 2020 r
public static void setLocale(Activitycontext) {
Locale locale;
Sessions session = new Sessions(context);
//Log.e("Lan",session.getLanguage());
locale = new Locale(langCode);
Configuration config = new Configuration(context.getResources().getConfiguration());
Locale.setDefault(locale);
config.setLocale(locale);
context.getBaseContext().getResources().updateConfiguration(config,
context.getBaseContext().getResources().getDisplayMetrics());
}
Context.createConfigurationContext()
, którego można użyć do zawinięcia domyślnego kontekstu konfiguracją specyficzną dla ustawień regionalnych, a następnie wywołania getResources
go bez konieczności aktualizacji konfiguracji samych obiektów zasobów.
conf.setLayoutDirection(locale)
, można zastąpić conf.locale = new Locale(...))
z conf.setLocale(new Locale(...))
. Zadzwoni wewnętrznie setLayoutDirection
.
Ten kod naprawdę działa:
fa = perski, en = angielski
Wpisz swój kod języka w languageToLoad
zmiennej:
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
public class Main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String languageToLoad = "fa"; // your language
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
this.setContentView(R.layout.main);
}
}
Resources.updateConfiguration
metody. Wciłem kod, aby był bardziej przejrzysty.
Szukałem sposobu programowej zmiany języka systemu. Chociaż w pełni rozumiem, że normalna aplikacja nigdy nie powinna tego robić i zamiast tego albo:
istniała potrzeba naprawdę programowej zmiany języka systemu.
Jest to nieudokumentowane API i dlatego nie powinno się go stosować w aplikacjach rynkowych / końcowych!
W każdym razie oto rozwiązanie, które znalazłem:
Locale locale = new Locale(targetLocaleAsString);
Class amnClass = Class.forName("android.app.ActivityManagerNative");
Object amn = null;
Configuration config = null;
// amn = ActivityManagerNative.getDefault();
Method methodGetDefault = amnClass.getMethod("getDefault");
methodGetDefault.setAccessible(true);
amn = methodGetDefault.invoke(amnClass);
// config = amn.getConfiguration();
Method methodGetConfiguration = amnClass.getMethod("getConfiguration");
methodGetConfiguration.setAccessible(true);
config = (Configuration) methodGetConfiguration.invoke(amn);
// config.userSetLocale = true;
Class configClass = config.getClass();
Field f = configClass.getField("userSetLocale");
f.setBoolean(config, true);
// set the locale to the new value
config.locale = locale;
// amn.updateConfiguration(config);
Method methodUpdateConfiguration = amnClass.getMethod("updateConfiguration", Configuration.class);
methodUpdateConfiguration.setAccessible(true);
methodUpdateConfiguration.invoke(amn, config);
android.permission.CHANGE_CONFIGURATION
może być przyznany tylko przez aplikację podpisaną kluczem perform.
Jeśli chcesz zachować zmieniony język w całej aplikacji, musisz zrobić dwie rzeczy.
Najpierw utwórz podstawową aktywność i spraw, aby wszystkie Twoje działania obejmowały:
public class BaseActivity extends AppCompatActivity {
private Locale mCurrentLocale;
@Override
protected void onStart() {
super.onStart();
mCurrentLocale = getResources().getConfiguration().locale;
}
@Override
protected void onRestart() {
super.onRestart();
Locale locale = getLocale(this);
if (!locale.equals(mCurrentLocale)) {
mCurrentLocale = locale;
recreate();
}
}
public static Locale getLocale(Context context){
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
String lang = sharedPreferences.getString("language", "en");
switch (lang) {
case "English":
lang = "en";
break;
case "Spanish":
lang = "es";
break;
}
return new Locale(lang);
}
}
Pamiętaj, że zapisuję nowy język we wspólnej preferencji.
Po drugie, utwórz rozszerzenie aplikacji w ten sposób:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
setLocale();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setLocale();
}
private void setLocale() {
final Resources resources = getResources();
final Configuration configuration = resources.getConfiguration();
final Locale locale = getLocale(this);
if (!configuration.locale.equals(locale)) {
configuration.setLocale(locale);
resources.updateConfiguration(configuration, null);
}
}
}
Zauważ, że getLocale () jest taki sam jak powyżej.
To wszystko! Mam nadzieję, że to może komuś pomóc.
Application
jest i jak korzystać. mobomo.com/2011/05/how-to-use-application-object-of-android
configuration.locate
jest przestarzałe, setLocale wymaga API 17+ i updateConfiguration jest przestarzałe
Zgodnie z tym artykułem . Będziesz musiał pobrać LocaleHelper.java
odnośniki w tym artykule.
MyApplication
klasę, która będzie rozszerzanaApplication
attachBaseContext()
aby zaktualizować język.Zarejestruj tę klasę w manifeście.
public class MyApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
}
}
<application
android:name="com.package.MyApplication"
.../>
Utwórz BaseActivity
i zastąp, onAttach()
aby zaktualizować język. Potrzebny do Androida 6+
public class BaseActivity extends Activity {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base));
}
}
Spraw, by wszystkie działania związane z Twoją aplikacją były rozszerzone BaseActivity
.
public class LocaleHelper {
private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
public static Context onAttach(Context context) {
String lang = getPersistedData(context, Locale.getDefault().getLanguage());
return setLocale(context, lang);
}
public static Context onAttach(Context context, String defaultLanguage) {
String lang = getPersistedData(context, defaultLanguage);
return setLocale(context, lang);
}
public static String getLanguage(Context context) {
return getPersistedData(context, Locale.getDefault().getLanguage());
}
public static Context setLocale(Context context, String language) {
persist(context, language);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
}
return updateResourcesLegacy(context, language);
}
private static String getPersistedData(Context context, String defaultLanguage) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
}
private static void persist(Context context, String language) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(SELECTED_LANGUAGE, language);
editor.apply();
}
@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
return context.createConfigurationContext(configuration);
}
@SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLayoutDirection(locale);
}
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
}
Właśnie dodałem dodatkowy kawałek, który mnie potknął.
Podczas gdy inne odpowiedzi działają na przykład dobrze z „de”
String lang = "de";
Locale locale = new Locale(lang);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
Powyższe nie będzie działać na przykład z "fr_BE"
ustawieniami regionalnymi, więc użyje values-fr-rBE
folderu lub podobnego.
Wymaga następującej niewielkiej zmiany do pracy "fr_BE"
String lang = "fr";
//create a string for country
String country = "BE";
//use constructor with country
Locale locale = new Locale(lang, country);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
activity.recreate()
android.content.res.Configuration conf = res.getConfiguration();
zamiast tworzenia nowej Configuration
instancji? Czy jest jakaś korzyść z używania nowej?
Zostałem zmieniony na język niemiecki, ponieważ moja aplikacja sama się uruchamia.
Oto mój poprawny kod. Każdy chce użyć tego samego dla mnie .. (Jak programowo zmienić język w Androidzie)
mój kod:
Configuration config ; // variable declaration in globally
// this part is given inside onCreate Method starting and before setContentView()
public void onCreate(Bundle icic)
{
super.onCreate(icic);
config = new Configuration(getResources().getConfiguration());
config.locale = Locale.GERMAN ;
getResources().updateConfiguration(config,getResources().getDisplayMetrics());
setContentView(R.layout.newdesign);
}
Wiem, że jest późno na odpowiedź, ale znalazłem ten artykuł tutaj . Co bardzo dobrze wyjaśnia cały proces i zapewnia dobrze ustrukturyzowany kod.
Klasa pomocnika ustawień regionalnych:
import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.preference.PreferenceManager;
import java.util.Locale;
/**
* This class is used to change your application locale and persist this change for the next time
* that your app is going to be used.
* <p/>
* You can also change the locale of your application on the fly by using the setLocale method.
* <p/>
* Created by gunhansancar on 07/10/15.
*/
public class LocaleHelper {
private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
public static Context onAttach(Context context) {
String lang = getPersistedData(context, Locale.getDefault().getLanguage());
return setLocale(context, lang);
}
public static Context onAttach(Context context, String defaultLanguage) {
String lang = getPersistedData(context, defaultLanguage);
return setLocale(context, lang);
}
public static String getLanguage(Context context) {
return getPersistedData(context, Locale.getDefault().getLanguage());
}
public static Context setLocale(Context context, String language) {
persist(context, language);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
}
return updateResourcesLegacy(context, language);
}
private static String getPersistedData(Context context, String defaultLanguage) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
}
private static void persist(Context context, String language) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(SELECTED_LANGUAGE, language);
editor.apply();
}
@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
return context.createConfigurationContext(configuration);
}
@SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLayoutDirection(locale);
}
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
}
Musisz przesłonić attachBaseContext i wywołać LocaleHelper.onAttach (), aby zainicjować ustawienia regionalne w aplikacji.
import android.app.Application;
import android.content.Context;
import com.gunhansancar.changelanguageexample.helper.LocaleHelper;
public class MainApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
}
}
Wszystko, co musisz zrobić, to dodać
LocaleHelper.onCreate(this, "en");
gdziekolwiek chcesz zmienić ustawienia regionalne.
createConfigurationContext
, który był pomocny
Utwórz klasę Rozszerza Application
i tworzy metodę statyczną. Następnie możesz wywołać tę metodę we wszystkich czynnościach wcześniej setContentView()
.
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
}
public static void setLocaleFa (Context context){
Locale locale = new Locale("fa");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
context.getApplicationContext().getResources().updateConfiguration(config, null);
}
public static void setLocaleEn (Context context){
Locale locale = new Locale("en_US");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
context.getApplicationContext().getResources().updateConfiguration(config, null);
}
}
Zastosowanie w działaniach:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApp.setLocaleFa(MainActivity.this);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
}
Programowo zmieniaj język w systemie Android
Stara odpowiedź
Obejmuje to obsługę RTL / LTR:
public static void changeLocale(Context context, Locale locale) {
Configuration conf = context.getResources().getConfiguration();
conf.locale = locale;
Locale.setDefault(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
conf.setLayoutDirection(conf.locale);
}
context.getResources().updateConfiguration(conf, context.getResources().getDisplayMetrics());
}
Jedynym rozwiązaniem, które w pełni działa dla mnie, jest połączenie kodu Alexa Volovoya z mechanizmem ponownego uruchamiania aplikacji:
void restartApplication() {
Intent i = new Intent(MainTabActivity.context, MagicAppRestart.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainTabActivity.context.startActivity(i);
}
/** This activity shows nothing; instead, it restarts the android process */
public class MagicAppRestart extends Activity {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
finish();
}
protected void onResume() {
super.onResume();
startActivityForResult(new Intent(this, MainTabActivity.class), 0);
}
}
activity.recreate()
Miałem do czynienia z tym samym problemem. Na GitHub znalazłem bibliotekę Android-LocalizationActivity .
Ta biblioteka ułatwia zmianę języka aplikacji w czasie wykonywania, co widać na poniższym przykładzie kodu. Przykładowy projekt zawierający poniższy przykładowy kod i więcej informacji można znaleźć na stronie github.
LocalizationActivity rozszerza AppCompatActivity, dzięki czemu można go również używać podczas korzystania z fragmentów.
public class MainActivity extends LocalizationActivity implements View.OnClickListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
findViewById(R.id.btn_th).setOnClickListener(this);
findViewById(R.id.btn_en).setOnClickListener(this);
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.btn_en) {
setLanguage("en");
} else if (id == R.id.btn_th) {
setLanguage("th");
}
}
}
Czas na odpowiednią aktualizację.
Po pierwsze, przestarzała lista z interfejsem API, w którym została wycofana:
configuration.locale
(API 17)updateConfiguration(configuration, displaymetrics)
(API 17)Rzeczą, na którą ostatnio nie udzielono odpowiedzi, jest zastosowanie nowej metody .
createConfigurationContext to nowa metoda updateConfiguration.
Niektórzy używali go jako samodzielnego:
Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
createConfigurationContext(overrideConfiguration);
... ale to nie działa. Dlaczego? Metoda zwraca kontekst, który jest następnie używany do obsługi tłumaczeń Strings.xml i innych zlokalizowanych zasobów (obrazów, układów, cokolwiek).
Prawidłowe użycie wygląda następująco:
Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
//the configuration can be used for other stuff as well
Context context = createConfigurationContext(overrideConfiguration);
Resources resources = context.getResources();
Jeśli właśnie skopiowałeś to do swojego IDE, możesz zobaczyć ostrzeżenie, że API wymaga kierowania na API 17 lub nowszy. Można to obejść, wprowadzając metodę i dodając adnotację@TargetApi(17)
Ale poczekaj. Co ze starszymi interfejsami API?
Musisz utworzyć inną metodę za pomocą updateConfiguration bez adnotacji TargetApi.
Resources res = YourApplication.getInstance().getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = new Locale("th");
res.updateConfiguration(conf, dm);
Nie musisz tutaj zwracać kontekstu.
Teraz zarządzanie nimi może być trudne. W API 17+ potrzebujesz utworzonego kontekstu (lub zasobów z utworzonego kontekstu), aby uzyskać odpowiednie zasoby w oparciu o lokalizację. Jak sobie z tym poradzisz?
Tak to robię:
/**
* Full locale list: /programming/7973023/what-is-the-list-of-supported-languages-locales-on-android
* @param lang language code (e.g. en_US)
* @return the context
* PLEASE READ: This method can be changed for usage outside an Activity. Simply add a COntext to the arguments
*/
public Context setLanguage(String lang/*, Context c*/){
Context c = AndroidLauncher.this;//remove if the context argument is passed. This is a utility line, can be removed totally by replacing calls to c with the activity (if argument Context isn't passed)
int API = Build.VERSION.SDK_INT;
if(API >= 17){
return setLanguage17(lang, c);
}else{
return setLanguageLegacy(lang, c);
}
}
/**
* Set language for API 17
* @param lang
* @param c
* @return
*/
@TargetApi(17)
public Context setLanguage17(String lang, Context c){
Configuration overrideConfiguration = c.getResources().getConfiguration();
Locale locale = new Locale(lang);
Locale.setDefault(locale);
overrideConfiguration.setLocale(locale);
//the configuration can be used for other stuff as well
Context context = createConfigurationContext(overrideConfiguration);//"local variable is redundant" if the below line is uncommented, it is needed
//Resources resources = context.getResources();//If you want to pass the resources instead of a Context, uncomment this line and put it somewhere useful
return context;
}
public Context setLanguageLegacy(String lang, Context c){
Resources res = c.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();//Utility line
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = new Locale(lang);//setLocale requires API 17+ - just like createConfigurationContext
Locale.setDefault(conf.locale);
res.updateConfiguration(conf, dm);
//Using this method you don't need to modify the Context itself. Setting it at the start of the app is enough. As you
//target both API's though, you want to return the context as you have no clue what is called. Now you can use the Context
//supplied for both things
return c;
}
Ten kod działa, ponieważ ma jedną metodę, która wywołuje odpowiednią metodę na podstawie interfejsu API. Zrobiłem to z wieloma przestarzałymi wywołaniami (w tym Html.fromHtml). Masz jedną metodę, która pobiera potrzebne argumenty, która następnie dzieli ją na jedną z dwóch (lub trzech lub więcej) metod i zwraca odpowiedni wynik na podstawie poziomu API. Jest elastyczny, ponieważ nie musisz sprawdzać wiele razy, metoda „wejścia” robi to za Ciebie. Oto metoda wprowadzaniasetLanguage
Musisz użyć kontekstu zwróconego po otrzymaniu zasobów. Dlaczego? Widziałem tutaj inne odpowiedzi, które używają createConfigurationContext i nie używają kontekstu, który zwraca. Aby to działało, należy wywołać updateConfiguration. Które jest przestarzałe. Użyj kontekstu zwróconego przez metodę, aby uzyskać zasoby.
Przykładowe użycie :
Konstruktor lub coś podobnego:
ctx = getLanguage(lang);//lang is loaded or generated. How you get the String lang is not something this answer handles (nor will handle in the future)
A potem, gdziekolwiek chcesz zdobyć zasoby, które robisz:
String fromResources = ctx.getString(R.string.helloworld);
Użycie dowolnego innego kontekstu (teoretycznie) to złamie.
AFAIK nadal musisz używać kontekstu aktywności do wyświetlania okien dialogowych lub Toastów. w tym celu możesz użyć instancji działania (jeśli jesteś na zewnątrz)
I na koniec użyj recreate()
tego działania, aby odświeżyć zawartość. Skrót, aby nie tworzyć zamiaru odświeżenia.
Jeśli napiszesz
android:configChanges="locale"
W każdej aktywności (w pliku manifestu) nie ma potrzeby ustawiania jej przy każdym wejściu Activity
.
configChanges
do hakowania, aby zachować stan Aktywności podczas rotacji / etc.
Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration config = context.getResources().getConfiguration();
config.setLocale(locale);
context.createConfigurationContext(config);
Ważna aktualizacja:
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
Zauważ, że w SDK> = 21 musisz wywołać „Resources.updateConfiguration ()” , w przeciwnym razie zasoby nie zostaną zaktualizowane.
Context ctx = createConfigurationContext(args);
i otrzymujesz z tego zasoby
/*change language at Run-time*/
//use method like that:
//setLocale("en");
public void setLocale(String lang) {
myLocale = new Locale(lang);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
Intent refresh = new Intent(this, AndroidLocalize.class);
startActivity(refresh);
}
activity.recreate()
Locale
configuration
należy ustawić w każdym activity
przed ustawieniem treści -this.setContentView(R.layout.main);
activity.recreate()
Najpierw utwórz plik multi string.xml dla różnych języków; następnie użyj tego bloku kodu w onCreate()
metodzie:
super.onCreate(savedInstanceState);
String languageToLoad = "fr"; // change your language here
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
this.setContentView(R.layout.main);
Oto kod, który działa dla mnie:
public class MainActivity extends AppCompatActivity {
public static String storeLang;
@Override
protected void onCreate(Bundle savedInstanceState) {
SharedPreferences shp = PreferenceManager.getDefaultSharedPreferences(this);
storeLang = shp.getString(getString(R.string.key_lang), "");
// Create a new Locale object
Locale locale = new Locale(storeLang);
// Create a new configuration object
Configuration config = new Configuration();
// Set the locale of the new configuration
config.locale = locale;
// Update the configuration of the Accplication context
getResources().updateConfiguration(
config,
getResources().getDisplayMetrics()
);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Źródło: tutaj
Żadne z wymienionych tutaj rozwiązań nie pomogło mi.
Język nie włącza się w Androidzie> = 7.0, jeśli AppCompatDelegate.setDefaultNightMode (AppCompatDelegate.MODE_NIGHT_YES)
To LocaleUtils działa dobrze: https://gist.github.com/GigigoGreenLabs/7d555c762ba2d3a810fe
LocaleUtils
public class LocaleUtils {
public static final String LAN_SPANISH = "es";
public static final String LAN_PORTUGUESE = "pt";
public static final String LAN_ENGLISH = "en";
private static Locale sLocale;
public static void setLocale(Locale locale) {
sLocale = locale;
if(sLocale != null) {
Locale.setDefault(sLocale);
}
}
public static void updateConfig(ContextThemeWrapper wrapper) {
if(sLocale != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
Configuration configuration = new Configuration();
configuration.setLocale(sLocale);
wrapper.applyOverrideConfiguration(configuration);
}
}
public static void updateConfig(Application app, Configuration configuration) {
if(sLocale != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
//Wrapping the configuration to avoid Activity endless loop
Configuration config = new Configuration(configuration);
config.locale = sLocale;
Resources res = app.getBaseContext().getResources();
res.updateConfiguration(config, res.getDisplayMetrics());
}
}
}
Dodano ten kod do aplikacji
public class App extends Application {
public void onCreate(){
super.onCreate();
LocaleUtils.setLocale(new Locale("iw"));
LocaleUtils.updateConfig(this, getBaseContext().getResources().getConfiguration());
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
LocaleUtils.updateConfig(this, newConfig);
}
}
Kod w działaniu
public class BaseActivity extends AppCompatActivity {
public BaseActivity() {
LocaleUtils.updateConfig(this);
}
}
Odpowiedź Alex Volovoy działa tylko dla mnie, jeśli jest w metodzie onCreate działania.
Odpowiedź, która działa we wszystkich metodach, znajduje się w innym wątku
Zmień język programowo w Androidzie
Oto adaptacja kodu
Resources standardResources = getBaseContext().getResources();
AssetManager assets = standardResources.getAssets();
DisplayMetrics metrics = standardResources.getDisplayMetrics();
Configuration config = new Configuration(standardResources.getConfiguration());
config.locale = new Locale(languageToLoad);
Resources defaultResources = new Resources(assets, metrics, config);
Mam nadzieję, że to pomaga.
Należy pamiętać, że korzystanie z tego rozwiązania updateConfiguration
nie będzie już działać z wydaniem Androida M za kilka tygodni. Nowym sposobem na to jest teraz użycie applyOverrideConfiguration
metody z ContextThemeWrapper
patrz dokumentacja API
Możesz znaleźć moje pełne rozwiązanie tutaj, ponieważ sam napotkałem problem: https://stackoverflow.com/a/31787201/2776572
Jest kilka kroków, które powinieneś wdrożyć
Najpierw musisz zmienić ustawienia regionalne swojej konfiguracji
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = new Locale(language);
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
Po drugie, jeśli chcesz, aby zmiany miały zastosowanie bezpośrednio do widocznego układu, możesz albo zaktualizować widoki bezpośrednio, albo po prostu wywołać activity.recreate (), aby zrestartować bieżącą aktywność.
Musisz także zachować zmiany, ponieważ po zamknięciu aplikacji przez użytkownika stracisz zmianę języka.
Bardziej szczegółowe rozwiązanie wyjaśniłem na moim blogu Zmień programowo język w systemie Android
Zasadniczo wystarczy wywołać funkcję LocaleHelper.onCreate () w klasie aplikacji, a jeśli chcesz zmienić ustawienia lokalne w locie, możesz wywołać funkcję LocaleHelper.setLocale ()
Działa to, gdy naciskam przycisk, aby zmienić język tekstu w TextView. (Strings.xml w folderze wartości)
String languageToLoad = "de"; // your language
Configuration config = getBaseContext().getResources().getConfiguration();
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
recreate();
Dodaj klasę LocaleHelper
public class LocaleHelper{
private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
public static Context onAttach(Context context) {
String lang = getPersistedData(context, Locale.getDefault().getLanguage());
return setLocale(context, lang);
}
public static Context onAttach(Context context, String defaultLanguage) {
String lang = getPersistedData(context, defaultLanguage);
return setLocale(context, lang);
}
public static String getLanguage(Context context) {
return getPersistedData(context, Locale.getDefault().getLanguage());
}
public static Context setLocale(Context context, String language) {
persist(context, language);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
}
return updateResourcesLegacy(context, language);
}
private static String getPersistedData(Context context, String defaultLanguage) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
}
private static void persist(Context context, String language) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(SELECTED_LANGUAGE, language);
editor.apply();
}
@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
return context.createConfigurationContext(configuration);
}
@SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLayoutDirection(locale);
}
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
}
W działaniu lub fragmencie
Context context = LocaleHelper.setLocale(this, App.getSharedPre().getLanguage());
Resource resources = context.getResources();
Teraz SetText na każdym tekście
TextView tv = findViewById(R.id.tv);
tv.setText(resources.getString(R.string.tv));
podobna do przyjętej wersji z odpowiedzią, ale z 2017 r. i dodanego restartu (bez restartu, czasami następna czynność nadal wyświetla angielski):
// Inside some activity...
private void changeDisplayLanguage(String langCode) {
// Step 1. Change the locale in the app's configuration
Resources res = getResources();
android.content.res.Configuration conf = res.getConfiguration();
conf.setLocale(currentLocale);
createConfigurationContext(conf);
// Step 2. IMPORTANT! you must restart the app to make sure it works 100%
restart();
}
private void restart() {
PackageManager packageManager = getPackageManager();
Intent intent = packageManager.getLaunchIntentForPackage(getPackageName());
ComponentName componentName = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(componentName);
mainIntent.putExtra("app_restarting", true);
PrefUtils.putBoolean("app_restarting", true);
startActivity(mainIntent);
System.exit(0);
}
activity.recreate()
3) zwrócony kontekst Myślę, że należy użyć, aby uzyskać zasoby
Najpierw tworzysz wartości nazw katalogów - „Nazwa języka” jak hindi niż piszesz „cześć” i kopiujesz w tym katalogu nazwę pliku z ciągiem, a wartość nie zmienia parametru po ustawieniu poniżej kodu w akcji, takiej jak przycisk itp.
Locale myLocale = new Locale("hi");
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
Intent refresh = new Intent(Home.this, Home.class);
startActivity(refresh);
finish();
conf.locale
jest przestarzałe
private void setLanguage(String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration config = new Configuration();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
config.setLocale(locale);
} else {
config.locale = locale;
}
getResources().updateConfiguration(config,
getResources().getDisplayMetrics());
}
W przykładzie ustawiamy język angielski:
Configuration config = GetBaseContext().getResources().getConfiguration();
Locale locale = new Locale("en");
Locale.setDefault(locale);
config.locale = locale;
GetBaseContext().getResources().updateConfiguration(config,
GetBaseContext().getResources().getDisplayMetrics());
Pamiętaj, że działa to tylko wtedy, gdy język znajduje się również w systemie urządzeń, nie tylko w aplikacji
Do obsługi języka arabskiego / RTL
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(updateBaseContextLocale(newBase));
}
public Context updateBaseContextLocale(Context context) {
String language = SharedPreference.getInstance().getValue(context, "lan");//it return "en", "ar" like this
if (language == null || language.isEmpty()) {
//when first time enter into app (get the device language and set it
language = Locale.getDefault().getLanguage();
if (language.equals("ar")) {
SharedPreference.getInstance().save(mContext, "lan", "ar");
}
}
Locale locale = new Locale(language);
Locale.setDefault(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
updateResourcesLocale(context, locale);
return updateResourcesLocaleLegacy(context, locale);
}
return updateResourcesLocaleLegacy(context, locale);
}
@TargetApi(Build.VERSION_CODES.N)
private Context updateResourcesLocale(Context context, Locale locale) {
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
return context.createConfigurationContext(configuration);
}
@SuppressWarnings("deprecation")
private Context updateResourcesLocaleLegacy(Context context, Locale locale) {
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}