เปลี่ยนภาษาของแอปโดยทางโปรแกรมใน Android


448

เป็นไปได้ไหมที่จะเปลี่ยนภาษาของแอปแบบเป็นโปรแกรมในขณะที่ยังใช้ทรัพยากร Android อยู่

ถ้าไม่เป็นไปได้หรือไม่ที่จะขอทรัพยากรในภาษาใดภาษาหนึ่ง?

ฉันต้องการให้ผู้ใช้เปลี่ยนภาษาของแอพจากแอพ


4
คุณสามารถใช้ไลบรารีต่อไปนี้ซึ่งมีรายการภาษาการตั้งค่าสำหรับหน้าจอการตั้งค่าของคุณและแทนที่ภาษาในแอปพลิเคชันของคุณ: github.com/delight-im/Android-Language
caw

@MarcoW คุณรู้หรือไม่ว่า Android-Languages ​​ทำงานกับ Android 5.0 Lollipop ได้หรือไม่?
neu242

1
@ neu242 ใช่มันทำงานบน Android 5.0 โดยไม่มีปัญหาใด ๆ
caw

1
คุณสามารถใช้ไลบรารีต่อไปนี้: github.com/zeugma-solutions/locale-helper-android
josue.0

1
@ josue.0 ห้องสมุดนั้นเป็นทางออกที่สะอาดที่สุดสำหรับเรื่องนี้
amitavk

คำตอบ:


376

มันเป็นไปได้. คุณสามารถกำหนดสถานที่ อย่างไรก็ตามฉันจะไม่แนะนำ เราได้ลองในช่วงแรก ๆ แล้วมันเป็นการต่อสู้กับระบบโดยทั่วไป

เรามีข้อกำหนดแบบเดียวกันสำหรับการเปลี่ยนภาษา แต่ตัดสินใจที่จะตัดสินว่า UI ควรเหมือนกับ UI ของโทรศัพท์ มันทำงานผ่านการตั้งค่าสถานที่เกิดเหตุ แต่ก็บั๊กซีเกินไป และคุณต้องตั้งค่าทุกครั้งที่คุณป้อนกิจกรรม (แต่ละกิจกรรม) จากประสบการณ์ของฉัน นี่คือรหัสถ้าคุณยังต้องการสิ่งนี้ (อีกครั้งฉันไม่แนะนำ)

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());
    }

329
ไม่อยากเชื่อเลยว่า Android จะทำให้สิ่งนี้ยากมาก ฉันไม่เห็นว่าทำไมจึงควรมีความสัมพันธ์ที่เข้มงวดระหว่างสถานที่ของโทรศัพท์และแอปพลิเคชัน ฉันมีโทรศัพท์ของฉันที่ใช้ภาษาอังกฤษเสมอแม้ว่าฉันจะไม่ได้พูดภาษาอังกฤษ เหตุผลก็คือคำศัพท์กึ่งเทคนิคที่แปลแล้วแปลกเกินไปในภาษาของฉันเองดังนั้นภาษาอังกฤษจึงง่ายกว่ามาก มันทำให้ฉันทำตามคำแนะนำจากเน็ตได้ง่ายขึ้น แต่นั่นไม่ได้หมายความว่าฉันต้องการแอปทุกคนในโทรศัพท์ของฉันที่จะใช้ภาษาอังกฤษ ฉันต้องการที่จะสามารถเลือก !!!
เตอร์

9
โอ้ดูเหมือนกับ API ระดับ 17 ที่แนะนำContext.createConfigurationContext()ซึ่งสามารถใช้เพื่อห่อบริบทเริ่มต้นด้วยการกำหนดค่าเฉพาะสถานที่แล้วเรียกgetResourcesใช้โดยไม่ต้องอัปเดตการกำหนดค่าบนวัตถุทรัพยากรด้วยตนเอง
JAB

8
คุณต้องใส่สิ่งนี้ใน onCreate () ของทุกกิจกรรม มิฉะนั้นอาจถูกแทนที่โดยระบบ - ตัวอย่างเช่นเมื่อคุณเปลี่ยนอุปกรณ์เป็นแนวนอนและกิจกรรมของคุณจะถูกสร้างขึ้นใหม่ด้วยการกำหนดค่าใหม่ (มีระบบให้)
Zsolt Safrany

14
ในกรณีที่คุณตั้งค่าโลแคล RTL เช่น "ar" และต้องการให้โฟลเดอร์รีซอร์ส -ldrtl ของคุณทำงานได้เช่นกันให้เรียก conf.setLayoutDirection (locale);
Zsolt Safrany

3
@ZsoltSafrany - มากกว่าการเพิ่มการเรียกไปยังconf.setLayoutDirection(locale)คุณสามารถแทนที่ด้วยconf.locale = new Locale(...)) มันภายในจะเรียกconf.setLocale(new Locale(...)) setLayoutDirection
Ted Hopp

180

รหัสนี้ใช้งานได้จริง:

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);
  }
}

2
ฉันต้องการเปลี่ยนสถานที่เกิดเหตุ ณ รันไทม์ในรหัสของคุณคุณใส่รหัสของคุณก่อนที่เมธอด setContentView () ดังนั้นรหัสของคุณไม่เป็นประโยชน์สำหรับฉันดังนั้นวิธีการเปลี่ยนภาษาในเวลาทำงานในใบสมัครของฉันมีปุ่มตัวเลือกสองปุ่มสำหรับภาษาอังกฤษและอีกหนึ่งสำหรับภาษาอาหรับ
Dwivedi Ji

2
@Buffalo มันเป็นเพียงอาร์กิวเมนต์ที่สองสำหรับResources.updateConfigurationวิธีการ ฉันได้เยื้องรหัสเพื่อให้ชัดเจนยิ่งขึ้น
Czechnology

5
สิ่งนี้ใช้ได้ดีสำหรับทุกกิจกรรมเมื่อตั้งค่าในกิจกรรมการเปิดตัว แต่ชื่อแถบการกระทำดูเหมือนจะไม่ได้รับผลกระทบและยังคงแสดงภาษาเริ่มต้นต่อไป ความคิดอะไรที่ฉันอาจจะพลาด?
AndroidMechanic - Viral Patel

8
Config.locale เลิกใช้แล้ว
Zoe

2
แทน "config.locale = locale;" ใช้ "if (Build.VERSION.SDK_INT> = 17) {config.setLocale (locale);} else {config.locale = locale;}
roghayeh hosseini

36

ฉันกำลังมองหาวิธีที่จะเปลี่ยนภาษาของระบบโดยทางโปรแกรม ในขณะที่ฉันเข้าใจอย่างถ่องแท้ว่าแอปพลิเคชันทั่วไปไม่ควรทำเช่นนั้นและแทน:

  • ผู้ใช้ควรชี้ (ผ่านเจตนา) ไปที่การตั้งค่าระบบเพื่อเปลี่ยนด้วยตนเอง
  • แอปพลิเคชั่นควรจัดการการแปลด้วยตนเองเช่นเดียวกับที่อธิบายไว้ในคำตอบของ Alex

ไม่จำเป็นต้องเปลี่ยนภาษาของระบบโดยทางโปรแกรม

นี่คือ 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);

2
ให้ข้อยกเว้นเรียกใช้เป้าหมายยกเว้น
Ravi

1
ขึ้นอยู่กับที่ invocationTargetException ถูกส่งออกไป จากนั้นคุณควรจะรู้ว่าชั้นที่มีการเปลี่ยนแปลง
icyerasor

1
@ Rat-a-tat-a-tat Ratatouille เริ่มต้นจาก Android 4.2 android.permission.CHANGE_CONFIGURATIONเท่านั้นที่จะได้รับอนุญาตจากแอปที่เซ็นชื่อด้วยปุ่มดำเนินการ
Yeung

3
ฉันใส่แอปของฉันใน / system / priv-app เพื่อแก้ไขปัญหา Android 6.0 รายละเอียดที่นี่
weiyin

1
@Ravi ฉันต้องย้ายแอปของฉันจาก / system / app ไปที่ / system / priv-app เพื่อให้ทำงานได้
alexislg

31

หากคุณต้องการเปลี่ยนภาษาของแอปทั้งหมดของคุณคุณต้องทำสองสิ่ง

ขั้นแรกสร้างกิจกรรมพื้นฐานและทำให้กิจกรรมทั้งหมดของคุณขยายจากนี้:

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);
    }
}

โปรดทราบว่าฉันบันทึกภาษาใหม่ใน sharedPreference

ประการที่สองสร้างส่วนขยายของแอปพลิเคชันเช่นนี้:

    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 () มันเหมือนกับข้างต้น

นั่นคือทั้งหมด! ฉันหวังว่านี่จะช่วยให้ใครบางคน


กิจกรรมแอปมันเป็นกิจกรรมหลักเช่นเดียวกับ MainActivity หรือไม่? เช่นฉันสามารถแก้ไขปัญหานี้ใน setLocale () ในวิธีการของฉัน onCreate ()?
Morozov

แอพเป็นส่วนเสริมของแอปพลิเคชันไม่ใช่กิจกรรม ฉันไม่เข้าใจสิ่งที่คุณต้องการขอโทษ บางทีคุณสามารถลองอธิบายฉันได้อีก :) :)
Daniel S.

1
สำหรับ noobs Android เช่นฉันมาที่นี่เพื่อเรียนรู้ว่าApplicationมันคืออะไรและใช้อย่างไร mobomo.com/2011/05/how-to-use-application-object-of-android
Siwei Shen 申思维

2
configuration.locateเลิกใช้แล้ว setLocale ต้องการ API 17+ และ updateConfiguration เลิกใช้แล้ว
Zoe

19

ตามที่ บทความนี้ คุณจะต้องดาวน์โหลดLocaleHelper.javaการอ้างอิงในบทความนั้น

  1. สร้าง MyApplicationคลาสที่จะขยายApplication
  2. แทนที่attachBaseContext()เพื่ออัปเดตภาษา
  3. ลงทะเบียนคลาสนี้โดยชัดแจ้ง

    public class MyApplication extends Application {
       @Override
       protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
       }
    }
    
    <application
         android:name="com.package.MyApplication"
         .../>
  4. สร้างBaseActivityและแทนที่onAttach()เพื่ออัปเดตภาษา จำเป็นสำหรับ Android 6+

    public class BaseActivity extends Activity {
      @Override
      protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base));
      }
    }
  5. ทำให้กิจกรรมทั้งหมดในแอพของคุณขยายออก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;
    }
    }

ไม่สามารถใช้ super.attachBaseContext (LocaleHelper.onAttach (newBase)) ทำให้ฉันใช้ super.attachBaseContext แล้ว (CalligraphyContextWrapper.wrap (newBase))
Rasel

1
คุณสามารถพันรวมกันได้ super.attachBaseContext (CalligraphyContextWrapper.wrap (LocaleHelper.onAttach (newBase)))
Yeahia2508

15

เพียงแค่เพิ่มชิ้นส่วนพิเศษที่ทำให้ฉันสะดุด

ในขณะที่คำตอบอื่น ๆ ทำงานได้ดีกับ "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());

ข้างต้นจะไม่ทำงานกับ"fr_BE"สถานที่ตัวอย่างเช่นดังนั้นมันจะใช้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());

1
ถ้าคุณต้องการใช้การเปลี่ยนแปลงสถานที่กับการโทรกิจกรรมที่เปิดอยู่ในปัจจุบันactivity.recreate()
ถึงกระ

ฉันรู้ว่าฉันมางานปาร์ตี้ช้า แต่ Locale ใหม่ (lang, country) เป็นสิ่งที่ฉันต้องการ!
Jacob Holloway

activity.recreate () วิธีการใช้งานหรือถ้าเราคิดสิ่งนี้แล้ว String lang = "fr"; String country = "BE"; จะไม่ลบล้างว่าจะใช้เวลาอย่างไร
Amitsharma

สิ่งที่เกี่ยวกับการใช้android.content.res.Configuration conf = res.getConfiguration();แทนที่จะสร้างConfigurationอินสแตนซ์ใหม่ มีประโยชน์สำหรับการใช้ใหม่หรือไม่
Bianca Daniciuc

14

ฉันเปลี่ยนเป็นภาษาเยอรมันสำหรับแอปของฉันเริ่มต้นเอง

นี่คือรหัสที่ถูกต้องของฉัน ทุกคนต้องการใช้สิ่งนี้เหมือนกันสำหรับฉัน .. (วิธีเปลี่ยนภาษาใน Android โดยทางโปรแกรม)

รหัสของฉัน:

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);
}

1
@harikrishnan มันใช้งานไม่ได้สำหรับฉันและแป้นพิมพ์ไม่เปลี่ยนเป็นภาษาที่ระบุ .. คุณประกาศกิจกรรมอย่างไรในรายการ?
Avadhani Y

13

ฉันรู้ว่ามันสายที่จะตอบ แต่ผมพบว่า บทความนี้ที่นี่ ซึ่งอธิบายกระบวนการทั้งหมดได้เป็นอย่างดีและให้รหัสที่มีโครงสร้างที่ดีแก่คุณ

คลาส Helper Helper:

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 () เพื่อเริ่มต้นการตั้งค่า locale ในแอปพลิเคชันของคุณ

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");

ทุกที่ที่คุณต้องการเปลี่ยนสถานที่


LocaleHelper เป็นคลาสจากบทความ ลิงก์ใด ๆ มีความเสี่ยงที่จะถูกถอดออก โปรดเพิ่มรหัสลงในคำตอบของคุณ
โซอี้

ฉันไม่ต้องการรีสตาร์ทแอพเพราะแอพกำลังทำงานบางอย่างเช่นหน้าจอบันทึก ดังนั้นโดยไม่ต้องรีสตาร์ทแอพจะมีวิธีแก้ปัญหาสำหรับ Android 7.0
PriyankaChauhan

1
@PriyankaChauhan ฉันคิดว่าบทความนี้ครอบคลุมกรณีนี้: คุณมีสองตัวเลือกในการอัปเดตเลย์เอาท์ที่มองเห็นได้ในตอนนี้: อันดับแรกคุณสามารถอัปเดตข้อความหรือทรัพยากรอื่น ๆ ที่เกี่ยวข้องกับภาษาทีละตัว
Maksim Turaev

ขอบคุณสำหรับการเพิ่มใหม่createConfigurationContextที่เป็นประโยชน์
jacoballenwood

1
onCreate หรือ onAttach โทร
vanste25

12

สร้างคลาสขยาย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);
}

10

สำหรับ Android 7.0 Nougat (และต่ำกว่า) ให้ทำตามบทความนี้:

เปลี่ยนภาษาอย่างเป็นระบบใน 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());
}

1
updateConfiguration เลิกใช้แล้ว ลิงค์มีประโยชน์โปรดเพิ่มเข้าไปในคำตอบของคุณ (เชื่อมโยงคำตอบเดียวที่ไม่ดีเช่นการเชื่อมโยงอาจจะนำมาลงถ้าเกิดว่าคำตอบนี้จะไม่ได้ผล.)
โซอี้

8

ทางออกเดียวที่ทำงานได้อย่างสมบูรณ์สำหรับฉันคือการรวมกันของรหัสของ Alex Volovoy กับกลไกการรีสตาร์ทแอพพลิเคชั่น:

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);         
    }
}

2
หลังจากเปลี่ยนสถานที่แล้วคุณยังสามารถโทรactivity.recreate()
ถึงกระ

1
ฉันไม่ต้องการรีสตาร์ทแอพเพราะแอพกำลังทำงานบางอย่างเช่นหน้าจอบันทึก ดังนั้นโดยไม่ต้องรีสตาร์ทแอพจะมีวิธีแก้ปัญหาสำหรับ Android 7.0
PriyankaChauhan

7

ฉันกำลังเผชิญกับปัญหาเดียวกัน บน GitHub ฉันพบห้องสมุด Android-LocalizationActivityห้องสมุดที่ใช้

ห้องสมุดนี้ทำให้การเปลี่ยนภาษาของแอพของคุณเป็นเรื่องง่ายอย่างที่คุณเห็นในตัวอย่างโค้ดด้านล่าง ตัวอย่างโครงการรวมถึงรหัสตัวอย่างด้านล่างและข้อมูลเพิ่มเติมสามารถดูได้ที่หน้า GitHub

LocalizationActivity ขยาย AppCompatActivity ดังนั้นคุณสามารถใช้เมื่อคุณใช้ Fragments

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");
        }
    }
}

7

เวลาสำหรับการอัปเดตเนื่องจาก

ก่อนอื่นรายการที่เลิกใช้แล้วกับ 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 และไม่ใช้บริบทที่ส่งคืน หากต้องการให้มันทำงานอย่างนั้นต้องเรียกการกำหนดค่าใหม่ ซึ่งเลิกใช้แล้ว ใช้บริบทที่ส่งกลับโดยวิธีการรับทรัพยากร

ตัวอย่างการใช้งาน :

ตัวสร้างหรือบางที่คล้ายกัน:

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 คุณยังต้องใช้บริบทของกิจกรรมเพื่อแสดงข้อความโต้ตอบหรือ Toasts เพื่อที่คุณสามารถใช้อินสแตนซ์ของกิจกรรม (ถ้าคุณอยู่นอก)


และสุดท้ายใช้recreate()กิจกรรมเพื่อรีเฟรชเนื้อหา ปุ่มลัดที่ไม่ต้องสร้างความตั้งใจในการรีเฟรช


1
บางคนอาจสงสัยว่าบริบทที่สร้างขึ้นจะทำให้หน่วยความจำของคุณมีค่าใช้จ่ายหรือไม่ อย่างไรก็ตามตามเอกสารประกอบอย่างเป็นทางการของ Android: "การเรียกแต่ละครั้งไปที่เมธอดนี้ส่งคืนอินสแตนซ์ใหม่ของวัตถุ Context แต่ไม่ได้แชร์วัตถุบริบทร่วมกัน แต่สถานะทั่วไป (ClassLoader ทรัพยากรอื่น ๆ สำหรับการกำหนดค่าเดียวกัน) อาจเป็นไปได้ ที่มีน้ำหนักเบา." ดังนั้นฉันคิดว่า Android คาดหวังให้คุณใช้วัตถุบริบทแยกต่างหากสำหรับสิ่งที่เกิดขึ้น
Sira Lam

7

ถ้าคุณเขียน

android:configChanges="locale"

ในทุกกิจกรรม (ในไฟล์ Manifest) Activityแล้วจะต้องตั้งมันทุกครั้งที่คุณป้อนไม่


11
ถ้ามันอยู่ในรายการแล้วสิ่งนี้ก่อให้เกิดการเปลี่ยนแปลงที่รันไทม์ซึ่งดูเหมือนจะเป็นสิ่งที่ OP ต้องการหรือไม่
user316117

1
@ user316117 เป็นการบ่งบอกถึง Android ว่าแอปจะจัดการทุกเรื่องเกี่ยวกับการกำหนดค่าภาษาภายในไม่ว่าจะเป็นสถานที่คงที่ ฉันไม่แน่ใจว่าจะป้องกันไม่ให้ Android ตั้งค่าสถานที่เมื่อมีการเปลี่ยนแปลงระหว่างกิจกรรมหรือไม่เพราะฉันเคยเห็นconfigChangesใช้แฮ็คเพื่อรักษาสถานะของกิจกรรมไว้ในการหมุน / etc
JAB

วิธีการตั้งค่าภาษาเฉพาะภาษาอังกฤษโดยเฉพาะ?
Kaveesh Kanwal

1
... จนกว่า Android จะฆ่ากิจกรรมของคุณเพราะต้องการ RAM มากกว่า
CAD แบบหลุยส์

@Brijesh หากเราเปลี่ยนภาษาของแอพแล้วถ้าเรามีตัวเลือกการค้นหาอยู่ภายในแอพและถ้าเราค้นหาในนั้นแอปจะแสดงข้อมูลอย่างไรเราควรพัฒนาฐานข้อมูลที่แตกต่างกันสำหรับแต่ละภาษาหรือการตั้งค่ารหัส android แอปนั้นสามารถแสดงข้อมูลตามการค้นหาได้หรือไม่
Vishwa Pratap

5
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 ()'มิฉะนั้นทรัพยากรจะไม่ได้รับการอัปเดต


updateConfiguration เลิกใช้แล้ว AFAIK คุณใช้ createConfigurationContext และใช้บริบทที่คุณมีกับมัน ( Context ctx = createConfigurationContext(args);และรับทรัพยากรจากนั้น
Zoe

ฉันรู้ว่ามันเลิกใช้แล้ว แต่อย่างไรก็ตามฉันไม่รู้วิธีแก้ปัญหาใด ๆ ที่สามารถใช้กับ Android 5 ขึ้นไป
МаксимПетлюк

จากนั้นคุณไม่ได้ตรวจสอบ javadoc อย่างชัดเจน คุณเรียกบริบทที่สร้างจาก createConfigurationContext
Zoe

ตกลง แต่เราควรเรียก updateConfiguration () ใช่ไหม
МаксимПетлюк

1
อย่าใช้สายที่ไม่สนับสนุน ความหมายที่ไม่มีการโทร updateConfiguration
Zoe

4
/*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); 
 }

5
ไม่จำเป็นต้องเริ่มกิจกรรมใหม่เพียงรีเฟรชจริงactivity.recreate()
ถึงกระ

4

Locale configurationควรตั้งค่าในแต่ละactivityก่อนการตั้งค่าเนื้อหา -this.setContentView(R.layout.main);


แต่ถ้าคุณต้องการเปิดใช้งานได้ทันทีหลังจาก setContentView () ถูกเรียกใช้แล้ว
IgorGanapolsky

2
หลังจากเปลี่ยนสถานที่แล้วคุณยังสามารถโทรactivity.recreate()
ถึงกระ

4

ตอนแรกสร้าง 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);

ขอบคุณรหัสนี้ใช้งานได้ดีฉันทดสอบบน Android 5.x และ 6.x โดยไม่มีปัญหาใด ๆ
innovaciones

4

นี่คือรหัสที่เหมาะกับฉัน:

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);
    }
}

ที่มา: ที่นี่


3

ไม่มีวิธีแก้ปัญหาที่ระบุไว้ที่นี่ช่วยฉันได้

ภาษาไม่ได้เปิดบน 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);
    }
}

2

คำตอบของ Alex Volovoy ใช้ได้กับฉันถ้ามันอยู่ในวิธีการสร้างกิจกรรม

คำตอบที่ใช้งานได้ในวิธีการทั้งหมดอยู่ในหัวข้ออื่น

เปลี่ยนภาษาโดยใช้โปรแกรมใน 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);

หวังว่ามันจะช่วย


19
คุณพูดว่า "คำตอบที่ใช้ได้กับวิธีการทั้งหมดอยู่ในหัวข้ออื่น" แต่ลิงก์ของคุณชี้ไปที่หัวข้อนี้! "
user316117

1
config.locale เลิกใช้แล้ว
Zoe

2
คำตอบแบบเรียกซ้ำ, เป็นไปได้ของ StackOverflow
Tamtom

2

โปรดทราบว่าการใช้โซลูชันนี้updateConfiguration จะไม่ทำงานอีกต่อไปเมื่อมีการเปิดตัวAndroid Mในอีกไม่กี่สัปดาห์ วิธีใหม่ในการทำเช่นนี้คือตอนนี้ใช้applyOverrideConfigurationวิธีจากContextThemeWrapper ดูเอกสาร API

คุณสามารถหาวิธีแก้ปัญหาทั้งหมดของฉันที่นี่ตั้งแต่ฉันประสบปัญหาด้วยตัวเอง: https://stackoverflow.com/a/31787201/2776572


ฉันลองอัปเดตรหัสกำหนดค่าบน Android 6.0.1 และใช้งานได้ดีฉันไม่รู้ว่า Google แก้ไขปัญหานี้หรือไม่ แต่ฉันสามารถใช้งานได้โดยไม่มีปัญหา
innovaciones

1
@innovaciones วิธีที่ไม่สนับสนุนมีอยู่พักหนึ่ง ในที่สุดมันจะถูกลบออก ใช้เวลานาน แต่เป็นการดีที่สุดที่จะย้ายไปที่ API ใหม่โดยเร็วที่สุดเพื่อป้องกันปัญหาที่อาจเกิดขึ้น
Zoe

1

มีขั้นตอนบางอย่างที่คุณควรใช้

ก่อนอื่นคุณต้องเปลี่ยนภาษาของการกำหนดค่าของคุณ

Resources resources = context.getResources();

Configuration configuration = resources.getConfiguration();
configuration.locale = new Locale(language);

resources.updateConfiguration(configuration, resources.getDisplayMetrics());

ประการที่สองหากคุณต้องการให้การเปลี่ยนแปลงของคุณนำไปใช้โดยตรงกับโครงร่างที่มองเห็นได้คุณสามารถอัปเดตมุมมองได้โดยตรงหรือคุณสามารถเรียกกิจกรรมได้เพียงสร้าง recreate () เพื่อเริ่มกิจกรรมปัจจุบันใหม่

และคุณต้องยืนยันการเปลี่ยนแปลงของคุณเพราะหลังจากผู้ใช้ปิดแอปพลิเคชันของคุณคุณจะสูญเสียการเปลี่ยนแปลงภาษา

ฉันอธิบายโซลูชันที่มีรายละเอียดเพิ่มเติมเกี่ยวกับโพสต์บล็อกของฉันเปลี่ยนภาษาโดยทางโปรแกรมใน Android

โดยทั่วไปคุณเพียงแค่เรียก LocaleHelper.onCreate () ในคลาสแอปพลิเคชันของคุณและหากคุณต้องการเปลี่ยนสถานที่เกิดเหตุได้ทันทีคุณสามารถโทรหา LocaleHelper.setLocale ()


@LunarWatcher ใช่ถ้าคุณตรวจสอบรหัสใน gitHub หรือ gist จริง ๆ มันได้รับการจัดการแล้ว
Gunhan

1

สิ่งนี้ทำงานเมื่อฉันกดปุ่มเพื่อเปลี่ยนภาษาข้อความของ TextView ของฉัน (strings.xml ในโฟลเดอร์ values-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();

1

เพิ่มคลาส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));

0

คล้ายกับคำตอบที่ยอมรับ แต่รุ่น 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);
}

1) ใช้ finish () แทน 2) เพื่อรีสตาร์ทแอปที่คุณสามารถใช้activity.recreate()3) บริบทที่ส่งคืนฉันคิดว่าจะต้องใช้เพื่อให้ได้ทรัพยากร
Zoe

ฉันไม่ต้องการรีสตาร์ทแอพเพราะแอพกำลังทำงานบางอย่างเช่นหน้าจอบันทึก ดังนั้นโดยไม่ต้องรีสตาร์ทแอพจะมีวิธีแก้ปัญหาสำหรับ Android 7.0
PriyankaChauhan

0

ก่อนอื่นคุณสร้างค่าชื่อไดเรกทอรี - "ชื่อภาษา" เช่นภาษาฮินดีกว่าเขียน "hi" และคัดลอกชื่อไฟล์สตริงเดียวกันในไดเรกทอรีนี้และค่าการเปลี่ยนแปลงไม่เปลี่ยนพารามิเตอร์หลังจากตั้งค่าด้านล่างรหัสในการกระทำของคุณเช่นปุ่ม ฯลฯ ...

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(); 

1
conf.localeเลิกใช้แล้ว
Zoe

0
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());

}

1
ฉันไม่ต้องการรีสตาร์ทแอพเพราะแอพกำลังทำงานบางอย่างเช่นหน้าจอบันทึก ดังนั้นโดยไม่ต้องรีสตาร์ทแอพจะมีวิธีแก้ปัญหาสำหรับ Android 7.0
PriyankaChauhan

ใช่ใน 6.0 มันทำงานได้ดีสำหรับฉันโดยไม่ต้องรีสตาร์ทแอปเปลี่ยนภาษา แต่ฉันไม่ได้ทดสอบใน 7.0
Adeeb karim

0

ในตัวอย่างเราตั้งค่าภาษาอังกฤษ:

 Configuration config = GetBaseContext().getResources().getConfiguration();
 Locale locale = new Locale("en");
 Locale.setDefault(locale);
 config.locale = locale;
 GetBaseContext().getResources().updateConfiguration(config, 
            GetBaseContext().getResources().getDisplayMetrics());

โปรดจำไว้ว่าใช้งานได้เฉพาะในกรณีที่พบภาษาในระบบอุปกรณ์เท่านั้นไม่เพียง แต่ในแอปพลิเคชัน


0

สำหรับการสนับสนุนภาษาอารบิก / RTL

  1. คุณต้องอัปเดตการตั้งค่าภาษาของคุณผ่าน - attachBaseContext ()
  2. สำหรับ Android เวอร์ชัน N ขึ้นไปคุณต้องใช้ createConfigurationContext () & updateConfiguration () - รูปแบบ 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;
    }

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.