Androidでアプリの言語をプログラムで変更する


448

Androidリソースを使用しながら、プログラムでアプリの言語を変更することはできますか?

そうでない場合、特定の言語でリソースをリクエストすることは可能ですか?

ユーザーにアプリの言語をアプリから変更させたい。


4
言語リスト、設定画面の設定を提供し、アプリケーションの言語をオーバーライドする次のライブラリを使用できます:github.com/delight-im/Android-Languages
caw

@MarcoW。Android-LanguagesがAndroid 5.0 Lollipopで動作するかどうか知っていますか?
neu242 2015年

1
@ neu242はい、Android 5.0で問題なく動作します。
2015年

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

言語固有のコンテンツがある場合-設定に基づいてその内容を変更できます。


2020年3月26日更新

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

328
Androidがこれを難しくしているとは信じられません。電話のロケールとアプリケーションのロケールの間に厳密な関連付けが必要な理由は本当にわかりません。私は英語を母国語とする人ではありませんが、常に英語の電話を使用しています。その理由は、翻訳されたセミテクニカルワードが私の母国語では奇妙すぎて、英語がとても簡単になるからです。また、ネットからのアドバイスに簡単に対応できるようになります。しかし、それは私が私の電話のすべてのアプリが英語を使うことを望んでいることを意味しません(それは完全に大丈夫ですがデフォルトです)選べるようになりたい!!!
peterh 2013

9
ああ、APIレベル17が導入されたようですContext.createConfigurationContext()。これを使用して、デフォルトのコンテキストをロケール固有の構成でラップgetResourcesし、リソースオブジェクト自体の構成を更新する必要なくそれを呼び出すことができます。
JAB 2014

8
これをすべてのアクティビティのonCreate()に配置する必要があります。そうしないと、システムによって上書きされる可能性があります。たとえば、デバイスを横向きにして、アクティビティが新しい(システム提供の)構成で再作成された場合などです。
Zsolt Safrany 2014年

13
「ar」のようなRTLロケールを設定し、-ldrtlリソースフォルダーも機能させる場合は、conf.setLayoutDirection(locale);も呼び出します。
Zsolt Safrany 2014年

3
@ZsoltSafrany-への呼び出しを追加するconf.setLayoutDirection(locale)代わりにconf.locale = new Locale(...))、で置き換えることができますconf.setLocale(new Locale(...))。内部的にを呼び出しますsetLayoutDirection
テッドホップ、2015

179

このコードは本当に機能します:

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()メソッドの前にコードを配置します。だからあなたのコードは私には役に立たないので、実行時に言語を変更する方法、私のアプリケーションには、英語用とアラビア語用の2つのラジオボタンがあります
Dwivedi Ji

2
@バッファロー、それはResources.updateConfigurationメソッドの2番目の引数にすぎません。コードをインデントして、わかりやすくしました。
チェコ語2013

5
これは、起動アクティビティで設定すると、すべてのアクティビティでうまく機能します。ただし、アクションバーのタイトルは影響を受けないようで、引き続きデフォルトの言語が表示されます。私が見逃したかもしれないアイデアはありますか?
AndroidMechanic-Viral Patel、2015年

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
例外invocationtarget例外を与える
Ravi

1
invocationTargetExceptionがスローされる場所によって異なります。次に、変更されたクラスを知る必要があります。
icyerasor 2013年

1
@ Rat-a-tat-a-tat Ratatouilleは、Android 4.2以降、android.permission.CHANGE_CONFIGURATIONperformキーで署名されたアプリでのみ付与できます。
Yeung

3
アプリを/ system / priv-appに配置して、Android 6.0の問題を回避します。詳細はこちら
weiyin 2015

1
@Raviアプリを/ system / appから/ system / priv-appに移動して動作させる必要がありました
alexislg

31

アプリ全体で言語を変更したい場合は、2つのことを行う必要があります。

まず、ベースアクティビティを作成し、すべてのアクティビティをこれから拡張します。

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などの主要なアクティビティですか?たとえば、メソッドonCreate()のsetLocale()でこれを解決できますか?
モロゾフ

アプリはアプリケーションの拡張であり、アクティビティではありません。何が必要かわかりません。多分あなたは私をもう一度説明しようとすることができます:)
ダニエルS.

1
私のようなAndroid初心者のために、ここに来て、何Applicationがどのように使用するかを学びましょう。 mobomo.com/2011/05/how-to-use-application-object-of-android
Siwei Shen申思维

2
configuration.locateは非推奨で、setLocaleにはAPI
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()
Kra

パーティーに遅れるのはわかっていますが、必要なのは新しいロケール(lang、国)だけでした!
Jacob Holloway

activity.recreate()どのように機能するか、またはこれを計算した場合、String lang = "fr"; String country = "BE"; 実行時間をオーバーライドすることは決してありません
Amitsharma '

android.content.res.Configuration conf = res.getConfiguration();新しいConfigurationインスタンスを作成する代わりに使用するのはどうですか?フレッシュなものを使うメリットはありますか?
Bianca Daniciuc

14

アプリの起動自体がドイツ語に変更されました。

これが私の正しいコードです。誰もが私のためにこれを同じように使用したい..(プログラムでアンドロイドの言語を変更する方法)

私のコード:

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 2013

13

回答が遅いのはわかっていますが、この記事はこちらで見つかりまし 。これはプロセス全体を非常によく説明し、適切に構造化されたコードを提供します。

ロケールヘルパークラス:

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

ロケールを変更したい場所。


LocaleHelperは記事のクラスです。リンクはすべて削除されるリスクがあります。回答にコードを追加してください。
ゾーイ

アプリが画面の記録などのタスクを実行しているため、アプリを再起動したくありません。したがって、アプリを再起動せずにAndroid 7.0の解決策があります
PriyankaChauhan

1
@PriyankaChauhanこの記事はこのケースをカバーしていると思います:現在表示されているレイアウトを更新するには2つのオプションがあります: 最初に、テキストまたは他の言語依存リソースを1つずつ更新できます。
2017年

新しいを追加してくれてありがとう、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は非推奨です。リンクは役に立ちます。回答に追加してください。(リンクがダウンする可能性があるため、リンクのみの回答は適切ではありません。その場合、この回答は
Zoe

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

1
アプリが画面の記録などのタスクを実行しているため、アプリを再起動したくありません。したがって、アプリを再起動せずにAndroid 7.0の解決策があります
PriyankaChauhan

7

私も同じ問題に直面していました。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");
        }
    }
}

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はどうですか?

TargetApiアノテーションなしでupdateConfigurationを使用して別のメソッドを作成する必要があります。

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に基づいて適切なメソッドを呼び出す1つのメソッドを持つことで機能します。これは、さまざまな非推奨の呼び出し(Html.fromHtmlを含む)で私が行ったものです。必要な引数を受け取る1つのメソッドがあり、それを2つ(または3つ以上)のメソッドのいずれかに分割し、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()に、アクティビティを使用してコンテンツを更新します。更新するインテントを作成する必要がないショートカット。


1
作成されたコンテキストがメモリを消費するのではないかと考える人もいます。ただし、Androidの公式ドキュメントによると、「このメソッドを呼び出すたびにContextオブジェクトの新しいインスタンスが返されます。Contextオブジェクトは共有されませんが、一般的な状態(ClassLoader、同じ構成の他のリソース)は、コンテキスト自体を公平にすることができます。軽量。" ですから、Androidは、ロケールの事物に対して個別のコンテキストオブジェクトを使用することを期待していると思います。
シララム2017

7

あなたが書くなら

android:configChanges="locale"

すべてのアクティビティ(マニフェストファイル内)では、を入力するたびに設定する必要はありませんActivity


11
それがマニフェストにある場合、これは実行時に変更をどのように構成しますか?これはOPが望んでいたように見えましたか?
user316117 2012年

1
@ user316117 Androidに対して、アプリがロケール設定に関するすべての問題を内部的に処理することを示します。ただし、configChangesローテーションなどでアクティビティの状態を保持するためのハックに使用されただけなので、アクティビティが切り替わるときにAndroidがロケールを設定できないかどうかはわかりません。
JAB 2014

言語を英語固有にのみ設定する方法?
Kaveesh Kanwal

1
...より多くのRAMを必要とするためにAndroidがアクティビティを終了するまで
Louis 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

私はそれが非難されていることを知っています。しかし、とにかく私はアンドロイド5以上で動作する解決策を知りません。
МаксимПетлюк

次に、javadocを確認しませんでした。createConfigurationContextから作成されたコンテキストを呼び出す
Zoe

わかりましたが、とにかくupdateConfiguration()を呼び出す必要がありますよね?
МаксимПетлюк

1
非推奨の呼び出しは使用しないでください。何の呼び出しupdateConfiguration意味しない
ゾーイ・

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 configurationactivityコンテンツを設定する前に、それぞれに設定する必要があります-this.setContentView(R.layout.main);


しかし、setContentView()が呼び出された後でオンザフライで切り替えたい場合はどうでしょうか?
IgorGanapolsky 2014年

2
ロケールの変更後は、次の方法で呼び出すこともできますactivity.recreate()
Kra Kra

4

最初に、異なる言語用のマルチ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);

ありがとう、このコードは素晴らしい作品、私は何の問題もなくアンドロイドの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

ここに記載されている解決策はどれも役に立ちませんでした。

AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)の場合、言語がandroid> = 7.0に切り替わりませんでした

この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の回答は、アクティビティの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);

それがお役に立てば幸いです。


19
あなたは「すべての方法で機能する答えは別のスレッドにある」と言いましたが、あなたのリンクはこのスレッドを指しています!
user316117

1
config.localeは非推奨
Zoe

2
StackOverflowの再帰的回答の可能性
tamtom

2

このソリューションを使用updateConfiguration すると、数週間後のAndroid Mリリースでは機能しなくなります。これを行う新しい方法は、APIドキュメントapplyOverrideConfigurationContextThemeWrapper 参照してください。

私が自分で問題に直面したので、ここで私の完全な解決策を見つけることができます:https : //stackoverflow.com/a/31787201/2776572


私はAndroid 6.0.1でupdateConfigurationコードを試してみましたが、うまく機能しています。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());

次に、変更を表示されているレイアウトに直接適用したい場合は、ビューを直接更新するか、またはactivity.recreate()を呼び出して現在のアクティビティを再開できます。

また、ユーザーがアプリケーションを閉じた後、言語の変更が失われるため、変更を永続化する必要があります。

Androidでプログラム的に言語を変更するブログ投稿で、より詳細な解決策を説明しました

基本的に、アプリケーションクラスでLocaleHelper.onCreate()を呼び出すだけです。その場でロケールを変更したい場合は、LocaleHelper.setLocale()を呼び出すことができます。


@LunarWatcherはい、実際にgithubまたはgistでコードをチェックする場合は、すでに処理されています。
Gunhan

1

これは、ボタンを押してTextViewのテキスト言語を変更すると機能します。(values-deフォルダーのstrings.xml)

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.