Чи можливо змінити мову програми програмно, використовуючи ресурси Android?
Якщо ні, чи можна запитувати ресурс певною мовою?
Я хотів би дозволити користувачеві змінювати мову програми з програми.
Чи можливо змінити мову програми програмно, використовуючи ресурси Android?
Якщо ні, чи можна запитувати ресурс певною мовою?
Я хотів би дозволити користувачеві змінювати мову програми з програми.
Відповіді:
Це можливо. Ви можете встановити локаль. Однак я б не рекомендував цього. Ми спробували це на ранніх стадіях, це в основному боротьба з системою.
У нас є однакові вимоги щодо зміни мови, але ми вирішили примиритися до того, що інтерфейс повинен бути таким же, як і інтерфейс телефону. Він працював за допомогою локального налаштування, але був занадто глючним. І ви повинні встановити це щоразу, коли ви входите в діяльність (кожну діяльність) з мого досвіду. ось код, якщо він вам все ще потрібен (знову ж, я не рекомендую цього)
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);
Якщо у вас є вміст, специфічний для мови - ви можете змінити цю базу в налаштуваннях.
оновлення 26 березня 2020 року
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()
, який можна використовувати для обгортання контексту за замовчуванням з конфігурацією, що залежить від локальності, а потім викликати getResources
це без необхідності оновлення конфігурації на самих об'єктах ресурсів.
conf.setLayoutDirection(locale)
, ви можете замінити conf.locale = new Locale(...))
з conf.setLocale(new Locale(...))
. Він внутрішньо зателефонує setLayoutDirection
.
Цей код справді працює:
fa = перська, en = англійська
Введіть свій код мови languageToLoad
змінною:
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
методу. Я відрізав код, щоб зробити його більш зрозумілим.
Я шукав спосіб змінити системну мову програмно. Хоча я повністю розумію, що звичайна програма ніколи не повинна цього робити, а натомість:
виникла потреба реально змінити мову системи програмно.
Це незадокументований API, і тому його не слід використовувати для додатків для ринку / кінцевих користувачів!
У будь-якому випадку є знайдене нами рішення:
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
надається лише програма, підписана ключем виконувати.
Якщо ви хочете, щоб мова, змінена у всіх ваших програмах, вам потрібно зробити дві речі.
По-перше, створіть базову діяльність та зробіть усі ваші дії продовженими від цього:
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);
}
}
Зауважте, що я зберігаю нову мову в спільнійПреференції.
По-друге, створіть розширення програми так:
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);
}
}
}
Зауважте, що getLocale () це те саме, що вище.
Це все! Я сподіваюся, що це може комусь допомогти.
Application
таке і як ними користуватися. mobomo.com/2011/05/how-to-use-application-object-of-android
configuration.locate
застаріло, setLocale вимагає API 17+ та оновленняConfiguration застаріле
Відповідно до цієї статті . Вам потрібно буде завантажити LocaleHelper.java
посилання в цій статті.
MyApplication
клас, який буде розширюватисяApplication
attachBaseContext()
мову, щоб оновити мову.Зареєструйте цей клас у маніфесті.
public class MyApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
}
}
<application
android:name="com.package.MyApplication"
.../>
Створіть BaseActivity
та замініть onAttach()
для оновлення мови. Потрібно для Android 6+
public class BaseActivity extends Activity {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base));
}
}
Зробіть все дії на ваше додаток поширюється від 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;
}
}
Просто додаю зайвий шматок, який мене збудив.
У той час як інші відповіді працюють нормально, наприклад, "де"
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());
Вищенаведене не працює, наприклад, з "fr_BE"
locale, тому воно використовує values-fr-rBE
папку чи подібні.
Для роботи потрібна наступна незначна зміна "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();
замість створення нового Configuration
екземпляра? Чи є якась користь від використання свіжої?
Я змінений на німецьку мову для самого запуску програми.
Ось мій правильний код. Хто хоче скористатися цим самим для мене .. (Як змінити мову в андроїд програмно)
мій код:
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);
}
Я знаю, що пізно відповісти, але я знайшов цю статтю тут . Це дуже добре пояснює весь процес і надає вам добре структурований код.
Місцевий помічник класу:
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;
}
}
Потрібно переосмислити attachBaseContext і зателефонувати LocaleHelper.onAttach (), щоб ініціалізувати параметри локалі у вашій програмі.
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"));
}
}
Все, що вам потрібно зробити - це додати
LocaleHelper.onCreate(this, "en");
де ви хочете змінити локаль.
createConfigurationContext
, що було корисно
Створення класу Extends Application
та створення статичного методу. Тоді ви можете викликати цей метод у всіх видах діяльності раніше 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);
}
}
Використання в діяльності:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApp.setLocaleFa(MainActivity.this);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
}
Змініть мову програматично в Android
Стара відповідь
Сюди входить підтримка 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());
}
Єдине рішення, яке повністю працює для мене, - це поєднання коду Алекса Волового з механізмом перезавантаження програми:
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()
Я стикався з тим же питанням. На GitHub я знайшов бібліотеку Android-LocalizationActivity .
Ця бібліотека дозволяє дуже просто змінювати мову вашого додатка під час виконання, як ви бачите в прикладі коду нижче. Зразок проекту, що включає зразок коду нижче та додаткову інформацію, можна знайти на сторінці github.
LocalizationActivity розширює AppCompatActivity, тому ви також можете використовувати його під час використання фрагментів.
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");
}
}
}
Час для належного оновлення.
По-перше, застарілий список з API, в якому він був застарілим:
configuration.locale
(API 17)updateConfiguration(configuration, displaymetrics)
(API 17)Те, на що нещодавно не отримали жодного питання, - це використання нового методу .
createConfigurationContext - це новий метод updateConfiguration.
Деякі використовували його окремо так:
Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
createConfigurationContext(overrideConfiguration);
... але це не працює. Чому? Метод повертає контекст, який потім використовується для обробки перекладів Strings.xml та інших локалізованих ресурсів (зображень, макетів і т. Д.).
Правильне використання виглядає так:
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();
Якщо ви просто скопіювали це в свій IDE, ви побачите попередження, що API вимагає націлювання на API 17 або вище. Це можна вирішити, ввівши його в метод і додавши анотацію@TargetApi(17)
Але чекай. А як щодо старих API?
Потрібно створити інший метод, використовуючи updateConfiguration без анотації 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);
Тут не потрібно повертати контекст.
Тепер, управління ними може бути важким. В API 17+ вам потрібен створений контекст (або ресурси з створеного контексту), щоб отримати відповідні ресурси на основі локалізації. Як ви справляєтеся з цим?
Ну ось так я це роблю:
/**
* 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;
}
Цей код працює за допомогою одного методу, який здійснює виклики до відповідного методу на основі API. Це те, що я робив із багатьма застарілими дзвінками (включаючи Html.fromHtml). У вас є один метод, який бере необхідні аргументи, який потім розбиває його на один з двох (або трьох або більше) методів і повертає відповідний результат на основі рівня API. Це гнучко, оскільки вам не доведеться перевіряти кілька разів, метод "введення" робить це за вас. Метод введення тут єsetLanguage
Вам потрібно використовувати контекст, який повертається, коли ви отримуєте ресурси. Чому? Тут я бачив інші відповіді, які використовують createConfigurationContext і не використовують контекст, який він повертає. Щоб він працював так, потрібно викликати updateConfiguration. Що застаріло. Використовуйте контекст, повернений методом, щоб отримати ресурси.
Приклад використання :
Конструктор або десь подібне:
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)
І тоді, де б ви хотіли отримати ресурси, якими ви користуєтеся:
String fromResources = ctx.getString(R.string.helloworld);
Використання будь-якого іншого контексту це (теоретично) це порушить.
AFAIK, ви все ще повинні використовувати контекст діяльності для показу діалогів або тостів. для цього ви можете використовувати примірник дії (якщо ви знаходитесь поза)
І, нарешті, скористайтеся recreate()
діяльністю, щоб оновити вміст. Ярлик не потрібно створювати наміру оновити.
Якщо ти пишеш
android:configChanges="locale"
У кожній діяльності (у файлі маніфесту) тоді не потрібно встановлювати її щоразу, коли ви вводите Activity
.
configChanges
використовувався лише для злому, щоб зберегти стан активності при обертаннях / тощо.
Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration config = context.getResources().getConfiguration();
config.setLocale(locale);
context.createConfigurationContext(config);
Важливе оновлення:
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
Зауважте, що на SDK> = 21 вам потрібно зателефонувати "Resources.updateConfiguration ()" , інакше ресурси не оновлюються.
Context ctx = createConfigurationContext(args);
і отримуєте з цього ресурси
/*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
activity
перед налаштуванням вмісту слід встановити в кожному -this.setContentView(R.layout.main);
activity.recreate()
Спочатку створіть multi string.xml для різних мов; потім використовуйте цей блок коду в onCreate()
методі:
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);
Ось код, який працює для мене:
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);
}
}
Джерело: тут
Жодне з перерахованих тут рішень мені не допомогло.
Мова не вмикається на android> = 7.0, якщо AppCompatDelegate.setDefaultNightMode (AppCompatDelegate.MODE_NIGHT_YES)
Цей LocaleUtils працює чудово: 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());
}
}
}
Додано цей код до програми
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);
}
}
Код у діяльності
public class BaseActivity extends AppCompatActivity {
public BaseActivity() {
LocaleUtils.updateConfig(this);
}
}
Відповідь Олексія Волового працює для мене лише в тому випадку, якщо вона використовується в методі onCreate в процесі діяльності.
Відповідь, яка працює у всіх методах, знаходиться в іншій темі
Програмно змінюйте мову в Android
Ось адаптація коду
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);
Сподіваюся, що це допомагає.
Зауважте, що це рішення з використанням updateConfiguration
більше не працюватиме з випуском Android M через кілька тижнів. Новий спосіб зробити це зараз за допомогою applyOverrideConfiguration
методу ContextThemeWrapper
див. API API
Ви можете знайти моє повне рішення тут, оскільки я зіткнувся з проблемою сам: https://stackoverflow.com/a/31787201/2776572
Є кілька кроків, які слід здійснити
Спочатку потрібно змінити локальну конфігурацію
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = new Locale(language);
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
По-друге, якщо ви хочете, щоб ваші зміни застосовувалися безпосередньо до видимого макета, ви можете або оновити представлення даних безпосередньо, або ви можете просто зателефонувати за Activity.recreate (), щоб відновити поточну активність.
А також вам доведеться зберегти свої зміни, оскільки після закриття програми користувач втратить мову.
Я пояснив більш детальне рішення у своєму дописі в блозі Програма зміни програмно в Android
В основному, ви просто викликаєте LocaleHelper.onCreate () у вашому класі додатків, і якщо ви хочете змінити локаль на ходу, ви можете зателефонувати LocaleHelper.setLocale ()
Це працює, коли я натискаю кнопку, щоб змінити мову тексту мого TextView. (Strings.xml у папці значень-de)
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();
Додати клас 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;
}
}
У діяльності або фрагменті
Context context = LocaleHelper.setLocale(this, App.getSharedPre().getLanguage());
Resource resources = context.getResources();
Тепер SetText для кожного тексту
TextView tv = findViewById(R.id.tv);
tv.setText(resources.getString(R.string.tv));
подібний до прийнятої відповіді, але версія 2017 та доданий перезапуск (без перезавантаження, іноді наступна активність все ще надає англійську мову):
// 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) повернутий контекст. Я думаю, що він повинен бути використаний для отримання ресурсів
Спочатку ви створюєте значення імені каталогів - "ім'я мови", як хінді, ніж пишете "привіт", і копіювати те саме ім'я файлу рядка в цей каталог і змінювати значення не змінювати параметр після встановленого нижче коду у вашій дії, як кнопка тощо ....
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
застаріло
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());
}
У прикладі ми встановлюємо англійську мову:
Configuration config = GetBaseContext().getResources().getConfiguration();
Locale locale = new Locale("en");
Locale.setDefault(locale);
config.locale = locale;
GetBaseContext().getResources().updateConfiguration(config,
GetBaseContext().getResources().getDisplayMetrics());
Пам'ятайте, що це працює лише в тому випадку, якщо мова знайдена і в системі пристроїв, а не лише в додатку
Для підтримки арабською / 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;
}