Як змінити мову програми, коли користувач вибирає мову?


106

Я хочу, щоб моя програма підтримувала три мови іспанську, португальську та англійську мови. І дайте можливість вибрати мову в додатку. Я зробив

1) 3 папки, що витягуються, Dravable-es, Dravable-pt, Dravable.

2) 3 значень папки-значення, значення-pt, величини. Змінити значення String.xml у відповідності з мовами.

У мене є imageView для вибору мови. Коли клацніть на ньому, відкрийте меню, яке складається з англійської, іспанської, португальської.

Я встановив Locale всередині програми на вибір опції за цим кодом

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.en:
             Locale locale = new Locale("en"); 
             Locale.setDefault(locale);
             Configuration config = new Configuration();
             config.locale = locale;
             getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
             Toast.makeText(this, "Locale in English !", Toast.LENGTH_LONG).show();
             break;

        case R.id.pt:
             Locale locale2 = new Locale("pt"); 
             Locale.setDefault(locale2);
             Configuration config2 = new Configuration();
             config2.locale = locale2;
             getBaseContext().getResources().updateConfiguration(config2, getBaseContext().getResources().getDisplayMetrics());

             Toast.makeText(this, "Locale in Portugal !", Toast.LENGTH_LONG).show();
             break;

        case R.id.es:
             Locale locale3 = new Locale("es"); 
             Locale.setDefault(locale3);
             Configuration config3 = new Configuration();
             config3.locale = locale3;
             getBaseContext().getResources().updateConfiguration(config3, getBaseContext().getResources().getDisplayMetrics());

             Toast.makeText(this, "Locale in Spain !", Toast.LENGTH_LONG).show();
             break;     
    }
    return super.onOptionsItemSelected(item);
}

Я декларую в Manifest- android: configChanges = "locale"

Це працює, але у нього є певне питання.

Проблема: -

1) Коли мова вибрана, екран, що складається із зображення вибору мови, не змінюється, а інші екрани змінюються.

2) Після зміни орієнтації додаток відновить мову відповідно до мови телефону.


1
Для другої проблеми спробуйте додати: android:configChanges="locale"для вашої активності всередині AndroidManifest.xml
Parth Doshi

я вже додав до кожної діяльності в своєму маніфесті.
мукеш

Ви можете використовувати таку бібліотеку, яка містить список мов, уподобання екрана налаштувань та замінює мову у вашій програмі: переорієнтовує github.com/delight-im/Android-Languages
caw

Відповіді:


172

Це витяг для веб-сторінки: http://android.programmerguru.com/android-localization-at-runtime/

Змінити мову вашого додатка просто, коли користувач вибере його зі списку мов. Створіть такий спосіб, як нижче, який приймає локальну мову як String (наприклад, "en" для англійської мови, "привіт" для хінді), налаштуйте локаль для вашої програми та оновіть поточну активність, щоб відобразити зміни мови. Локальний додаток, який ви застосували, не буде змінено, доки ви вручну не зміните його знову.

public void setLocale(String lang) { 
    Locale 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); 
    finish();
    startActivity(refresh); 
} 

Переконайтеся, що ви імпортували такі пакунки:

import java.util.Locale; 
import android.os.Bundle; 
import android.app.Activity; 
import android.content.Intent; 
import android.content.res.Configuration; 
import android.content.res.Resources; 
import android.util.DisplayMetrics; 

додати маніфест до діяльності Android: configChanges = "locale | орієнтація"


2
Так, звісно. Я можу надати витяг веб-сторінки. Де мені потрібно надати, будь ласка, повідомте мене. Дякую.
Удхай

3
Обов’язково додайте закінчення (), щоб у навігаційному стеку не було двох примірників вашої діяльності.
Джоель Теплі

6
finish()потрібно викликати раніше startActivity(refresh). Інакше додаток може вийти замість того, щоб активність перезапускалася.
Мохаммед Алі

10
Привіт, я це зробив, він працює, але коли я перезавантажую програму, він повертається до мови за замовчуванням ..
Sofiane Hassaini

5
Configuration config = нова конфігурація (newConfig); config.locale = locale; У моєму випадку отримання цього повідомлення. застаріле місце локалізації в рівні API 25
Мілон

9

Хороші рішення тут пояснено досить добре. Але ось ще один.

Створіть власний CustomContextWrapperрозширення класу ContextWrapperта скористайтеся ним, щоб змінити налаштування локальної програми для повної програми. Ось ГІСТ із використанням.

А потім зателефонуйте CustomContextWrapperіз збереженим ідентифікатором локалі, наприклад, 'hi'для мови хінді у методі життєвого циклу діяльності attachBaseContext. Використання тут:

@Override
protected void attachBaseContext(Context newBase) {
    // fetch from shared preference also save the same when applying. Default here is en = English
    String language = MyPreferenceUtil.getInstance().getString("saved_locale", "en");
    super.attachBaseContext(MyContextWrapper.wrap(newBase, language));
}

Дякую за посилання, воно працює, але я не зрозумів декілька речей, я просто зателефонував MyContextWrapper.warpу onAttachлише один фрагмент мого додатка, але мова була змінена для всього додатка, але заголовки діяльності не були змінені, я думаю, це це тому, що заголовки маніфесту мають перевагу, але якщо я називаю той самий метод у onAttachBaseContexсвоєму підкласі програми, заголовки активності також змінюються на вибраній мові, але тоді зміни застосовуються лише до фрагмента, який я викликав у методі warp, чому це ?
Абхінав Чахан

@AbhinavChauhan Я не впевнений, що це правда. Мені потрібно це перевірити. Я ніколи не стикався з цим питанням, коли реалізував це рішення. Однак минуло давно, і для нових версій можуть бути деякі зміни в реалізації Android. Крім того, спробуйте кілька останніх відповідей на це повідомлення.
sud007

Я спробував багато рішень, але не з них працював або, можливо, я реалізував їх неправильно, можливо, ваш клас добре працює з діяльністю, я використовую його warpметод у onAttachфрагменті, раніше я сказав, що мені просто потрібно це зробити з фрагментом манактивності, і мова змінилася в У всьому додатку це правда, але для всіх інших фрагментів мова змінюється на англійську при зміні конфігурації, тому мені потрібно вставити onattachвсі фрагменти і замість маніфесту я встановити заголовки панелі дій у коді, тепер додаток працює як очікувалося. дякую
Абхінав Чаухан

Добре! Я впевнений, що вам не доведеться робити це для кожного екрану, а лише першу діяльність, яка запускається і всередині attachBaseContextфункції. І це робиться для всіх екранів. Чи створили ви «BaseActivity» для всіх дій у вашому додатку?
sud007

Ні, я намагався зробити це в своєму підкласі програми, думаючи, що він буде застосований до всієї програми, потім у всіх фрагментах, але виявляється, що wrap()код потрібно виконувати при кожному зміні конфігурації, тому я помістив його в Абстрактна діяльність, від якої поширюються всі інші види діяльності, зараз вона працює
Абхінав Чаухан

6

Вам слід або видалити android:configChanges="locale"з маніфесту, який спричинить перезавантаження активності, або onConfigurationChangedметод заміни :

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
    // your code here, you can use newConfig.locale if you need to check the language
    // or just re-set all the labels to desired string resource
}

Видалення андроїда: configChanges = "locale" з маніфесту не заважає додатку перезапускатися. Він перезапуститься незалежно від того, додано це в маніфест чи ні.
портфоліобудівник

Я не кажу, що видалення android: configChanges = "locale" з маніфесту заважає додатку перезапускатися, я кажу саме навпаки. Тепер, для випадку, коли у маніфесті є android: configChanges = "locale", він використовував для запобігання завантаженню програми у той час, коли я писав цю відповідь, я не можу точно сказати, що так зараз.
Frane Poljak

6

все вищесказане @ код Uday ідеально, але відсутнє лише одне (конфігурація за замовчуванням у build.gradle)

public void setLocale(String lang) { 
Locale 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); 
finish();
startActivity(refresh); 

}

Шахта не працює лише тому, що мови не згадуються у файлі config (build.gradle)

 defaultConfig {
    resConfigs "en", "hi", "kn"
}

після цього всі мови почали працювати


3
НЕ ПРАЦЮЄ
Крунал Шах

Це справді потрібно?
JCarlosR

1
@JCarlosR так. коли я додав мови в конфігураційний файл код Udhay, почав працювати
Lokesh Tiwari

3

Ті, хто отримує проблему з версією, спробують цей код ..

public static void switchLocal(Context context, String lcode, Activity activity) {
        if (lcode.equalsIgnoreCase(""))
            return;
        Resources resources = context.getResources();
        Locale locale = new Locale(lcode);
        Locale.setDefault(locale);
        android.content.res.Configuration config = new 
        android.content.res.Configuration();
        config.locale = locale;
        resources.updateConfiguration(config, resources.getDisplayMetrics());
        //restart base activity 
        activity.finish();
        activity.startActivity(activity.getIntent());
    }

2

Зразок коду Удхая працює добре. За винятком питання Софії Хассейні та Чирага Соланкі, щодо повторного входу воно не працює. Я намагаюся викликати код Udhay без перезапуску активності в onCreate (), перш ніж super.onCreate (збереженийInstanceState) ;. Тоді все гаразд! Лише невелика проблема, рядки меню все ще не змінені на встановленому Locale.

    public void setLocale(String lang) { //call this in onCreate()
      Locale 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); 
      //finish();
    } 

така ж проблема з рядками меню. Ви вирішуєте проблему?
AlexS

@AlexS, я не знайшов способів вирішити проблему в рядку меню. Але, виявивши, що виходить із програми та знову вводиться, рядки меню можуть бути звичайно змінені на новий Locale.
Фішер

ти маєш на увазі Intent refresh = new Intent(this, ThisActivity.class); startActivity(refresh); ?
AlexS

2
@AlexS, ні! додавання нового Intent () та startActivity () може змусити його повернутися до мови за замовчуванням при перезапуску програми. Що я маю на увазі, якщо користувачі вийдуть із програми та перезавантажать програму, рядки меню можуть бути змінені на новий Locale.
Фішер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.