Android 리소스를 계속 사용하면서 프로그래밍 방식으로 앱의 언어를 변경할 수 있습니까?
그렇지 않은 경우 특정 언어로 리소스를 요청할 수 있습니까?
사용자가 앱에서 앱의 언어를 변경하도록하고 싶습니다.
Android 리소스를 계속 사용하면서 프로그래밍 방식으로 앱의 언어를 변경할 수 있습니까?
그렇지 않은 경우 특정 언어로 리소스를 요청할 수 있습니까?
사용자가 앱에서 앱의 언어를 변경하도록하고 싶습니다.
답변:
있을 수있다. 로케일을 설정할 수 있습니다. 그러나 나는 그것을 권장하지 않습니다. 초기 단계에서 시도했지만 기본적으로 시스템과 싸우고 있습니다.
언어 변경에 대한 요구 사항은 동일하지만 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());
}
Context.createConfigurationContext()
로케일 별 구성으로 기본 컨텍스트를 랩핑 한 다음 getResources
자원 오브젝트 자체의 구성을 업데이트하지 않고도 호출 할 수있는 API 레벨 17이 도입 된 것처럼 보입니다 .
conf.setLayoutDirection(locale)
, 당신은 대체 할 수 conf.locale = new Locale(...))
와를 conf.setLocale(new Locale(...))
. 내부적으로 호출 setLayoutDirection
합니다.
이 코드는 실제로 작동합니다.
fa = 페르시아어, en = 영어
languageToLoad
변수에 언어 코드를 입력하십시오 :
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
public class Main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String languageToLoad = "fa"; // your language
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
this.setContentView(R.layout.main);
}
}
Resources.updateConfiguration
메소드 의 두 번째 주장 일뿐 입니다. 더 명확하게하기 위해 코드를 들여 쓰기했습니다.
프로그래밍 방식으로 시스템 언어를 변경하는 방법을 찾고있었습니다. 정상적인 응용 프로그램은 절대 그렇게하지 않아야하며 다음 중 하나를 수행해야한다는 것을 완전히 이해하고 있습니다.
프로그래밍 방식으로 시스템 언어를 실제로 변경해야했습니다.
이것은 문서화되지 않은 API이므로 시장 / 최종 사용자 애플리케이션에 사용해서는 안됩니다!
어쨌든 내가 찾은 해결책은 다음과 같습니다.
Locale locale = new Locale(targetLocaleAsString);
Class amnClass = Class.forName("android.app.ActivityManagerNative");
Object amn = null;
Configuration config = null;
// amn = ActivityManagerNative.getDefault();
Method methodGetDefault = amnClass.getMethod("getDefault");
methodGetDefault.setAccessible(true);
amn = methodGetDefault.invoke(amnClass);
// config = amn.getConfiguration();
Method methodGetConfiguration = amnClass.getMethod("getConfiguration");
methodGetConfiguration.setAccessible(true);
config = (Configuration) methodGetConfiguration.invoke(amn);
// config.userSetLocale = true;
Class configClass = config.getClass();
Field f = configClass.getField("userSetLocale");
f.setBoolean(config, true);
// set the locale to the new value
config.locale = locale;
// amn.updateConfiguration(config);
Method methodUpdateConfiguration = amnClass.getMethod("updateConfiguration", Configuration.class);
methodUpdateConfiguration.setAccessible(true);
methodUpdateConfiguration.invoke(amn, config);
android.permission.CHANGE_CONFIGURATION
perform 키로 서명 된 앱에서만 부여 할 수 있습니다.
모든 앱에서 변경된 언어를 유지하려면 두 가지 작업을 수행해야합니다.
먼저 기본 활동을 작성하고 모든 활동을 다음에서 확장하십시오.
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 ()은 위와 동일합니다.
그게 다야! 이것이 누군가를 도울 수 있기를 바랍니다.
Application
사용법과 사용법을 배우십시오 . mobomo.com/2011/05/how-to-use-application-android-object-of-android
configuration.locate
더 이상 사용되지 않습니다. setLocale에는 API 17 이상이 필요하고 updateConfiguration은 더 이상 사용되지 않습니다
이 기사 에 따르면 . LocaleHelper.java
해당 기사에서 참조 된 파일을 다운로드해야합니다 .
MyApplication
확장 할 수업 만들기Application
attachBaseContext()
언어 업데이트를 재정의 합니다.이 클래스를 매니페스트에 등록하십시오.
public class MyApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
}
}
<application
android:name="com.package.MyApplication"
.../>
언어를 업데이트하기 위해 작성 BaseActivity
하고 대체 하십시오 onAttach()
. 안드로이드 6 이상에 필요
public class BaseActivity extends Activity {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base));
}
}
앱의 모든 활동이에서 확장되도록 BaseActivity
합니다.
public class LocaleHelper {
private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
public static Context onAttach(Context context) {
String lang = getPersistedData(context, Locale.getDefault().getLanguage());
return setLocale(context, lang);
}
public static Context onAttach(Context context, String defaultLanguage) {
String lang = getPersistedData(context, defaultLanguage);
return setLocale(context, lang);
}
public static String getLanguage(Context context) {
return getPersistedData(context, Locale.getDefault().getLanguage());
}
public static Context setLocale(Context context, String language) {
persist(context, language);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
}
return updateResourcesLegacy(context, language);
}
private static String getPersistedData(Context context, String defaultLanguage) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
}
private static void persist(Context context, String language) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(SELECTED_LANGUAGE, language);
editor.apply();
}
@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
return context.createConfigurationContext(configuration);
}
@SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLayoutDirection(locale);
}
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
}
나를 넘어 뜨린 여분의 조각을 추가하기 만하면됩니다.
예를 들어 다른 답변은 "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());
activity.recreate()
android.content.res.Configuration conf = res.getConfiguration();
새 Configuration
인스턴스 를 만드는 대신 사용 하는 것은 어떻습니까? 신선한 것을 사용하면 어떤 이점이 있습니까?
앱 시작 자체로 독일어로 변경되었습니다.
올바른 코드는 다음과 같습니다. 누구나 나를 위해 이것을 사용하고 싶습니다 .. (프로그래밍 방식으로 안드로이드에서 언어를 변경하는 방법)
내 코드 :
Configuration config ; // variable declaration in globally
// this part is given inside onCreate Method starting and before setContentView()
public void onCreate(Bundle icic)
{
super.onCreate(icic);
config = new Configuration(getResources().getConfiguration());
config.locale = Locale.GERMAN ;
getResources().updateConfiguration(config,getResources().getDisplayMetrics());
setContentView(R.layout.newdesign);
}
답변이 늦었다는 것을 알고 있지만 여기서이 기사를 찾았 습니다 . 전체 프로세스를 잘 설명하고 잘 구성된 코드를 제공합니다.
로케일 헬퍼 클래스 :
import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.preference.PreferenceManager;
import java.util.Locale;
/**
* This class is used to change your application locale and persist this change for the next time
* that your app is going to be used.
* <p/>
* You can also change the locale of your application on the fly by using the setLocale method.
* <p/>
* Created by gunhansancar on 07/10/15.
*/
public class LocaleHelper {
private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
public static Context onAttach(Context context) {
String lang = getPersistedData(context, Locale.getDefault().getLanguage());
return setLocale(context, lang);
}
public static Context onAttach(Context context, String defaultLanguage) {
String lang = getPersistedData(context, defaultLanguage);
return setLocale(context, lang);
}
public static String getLanguage(Context context) {
return getPersistedData(context, Locale.getDefault().getLanguage());
}
public static Context setLocale(Context context, String language) {
persist(context, language);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
}
return updateResourcesLegacy(context, language);
}
private static String getPersistedData(Context context, String defaultLanguage) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
}
private static void persist(Context context, String language) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(SELECTED_LANGUAGE, language);
editor.apply();
}
@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
return context.createConfigurationContext(configuration);
}
@SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLayoutDirection(locale);
}
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
}
응용 프로그램에서 로캘 설정을 초기화하려면 attachBaseContext를 재정의하고 LocaleHelper.onAttach ()를 호출해야합니다.
import android.app.Application;
import android.content.Context;
import com.gunhansancar.changelanguageexample.helper.LocaleHelper;
public class MainApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
}
}
당신이해야 할 추가
LocaleHelper.onCreate(this, "en");
로케일을 변경하려는 경우
createConfigurationContext
도움이되었다,
클래스 만들기 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);
}
기존 답변
여기에는 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());
}
나를 위해 완전히 작동하는 유일한 솔루션은 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);
}
}
activity.recreate()
나는 같은 문제에 직면했다. 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");
}
}
}
만기 업데이트를위한 시간입니다.
먼저 사용되지 않는 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 17 이상을 대상으로하는 API가 필요하다는 경고가 표시 될 수 있습니다. 메서드에 넣고 주석을 추가하여 해결할 수 있습니다.@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를 기반으로 적절한 메소드를 호출하는 하나의 메소드를 사용하여 작동합니다. 이것은 더 이상 사용되지 않는 많은 호출 (Html.fromHtml 포함)로 수행 한 것입니다. 필요한 인수를 취하는 하나의 메소드가 있으며,이 메소드를 두 개 (또는 세 개 이상의) 메소드 중 하나로 나누고 API 레벨에 따라 적절한 결과를 리턴합니다. 여러 번 확인할 필요가 없기 때문에 융통성이 뛰어납니다. "entry"방법으로 확인하십시오. 여기에 입력 방법은setLanguage
리소스를 얻을 때 반환 된 컨텍스트를 사용해야합니다. 왜? createConfigurationContext를 사용하고 반환하는 컨텍스트를 사용하지 않는 다른 답변을 보았습니다. 그렇게 작동하려면 updateConfiguration을 호출해야합니다. 더 이상 사용되지 않습니다. 메소드가 리턴 한 컨텍스트를 사용하여 자원을 확보하십시오.
사용법 예 :
생성자 또는 비슷한 곳 :
ctx = getLanguage(lang);//lang is loaded or generated. How you get the String lang is not something this answer handles (nor will handle in the future)
그런 다음 리소스를 얻고 싶은 곳이라면 어디든지 :
String fromResources = ctx.getString(R.string.helloworld);
다른 문맥을 사용하면 (이론적으로) 이것을 깨뜨릴 수 있습니다.
AFAIK 대화 상자 또는 토스트를 표시하려면 여전히 활동 컨텍스트를 사용해야합니다. 이를 위해 활동의 인스턴스를 사용할 수 있습니다 (외부인 경우)
마지막으로 recreate()
활동을 사용 하여 컨텐츠를 새로 고칩니다. 새로 고침 의도를 만들 필요가없는 바로 가기
당신이 쓰는 경우
android:configChanges="locale"
매니페스트 파일의 모든 활동에서를 입력 할 때마다 설정할 필요가 없습니다 Activity
.
configChanges
. 회전 등의 활동 상태를 유지하기 위해 해킹에 사용 된 것으로 나타났습니다 .
Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration config = context.getResources().getConfiguration();
config.setLocale(locale);
context.createConfigurationContext(config);
중요 업데이트 :
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
SDK> = 21에서는 'Resources.updateConfiguration ()' 을 호출해야합니다 . 그렇지 않으면 리소스가 업데이트되지 않습니다.
Context ctx = createConfigurationContext(args);
그 자원을 얻을
/*change language at Run-time*/
//use method like that:
//setLocale("en");
public void setLocale(String lang) {
myLocale = new Locale(lang);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
Intent refresh = new Intent(this, AndroidLocalize.class);
startActivity(refresh);
}
activity.recreate()
Locale
configuration
activity
내용을 설정하기 전에 각각 설정해야합니다-this.setContentView(R.layout.main);
activity.recreate()
처음에는 다른 언어에 대해 다중 string.xml을 작성하십시오. 그런 다음이 코드 블록을 onCreate()
메소드에 사용하십시오.
super.onCreate(savedInstanceState);
String languageToLoad = "fr"; // change your language here
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
this.setContentView(R.layout.main);
나를 위해 작동하는 코드는 다음과 같습니다.
public class MainActivity extends AppCompatActivity {
public static String storeLang;
@Override
protected void onCreate(Bundle savedInstanceState) {
SharedPreferences shp = PreferenceManager.getDefaultSharedPreferences(this);
storeLang = shp.getString(getString(R.string.key_lang), "");
// Create a new Locale object
Locale locale = new Locale(storeLang);
// Create a new configuration object
Configuration config = new Configuration();
// Set the locale of the new configuration
config.locale = locale;
// Update the configuration of the Accplication context
getResources().updateConfiguration(
config,
getResources().getDisplayMetrics()
);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
출처 : here
여기에 나열된 해결책 중 어느 것도 도움이되지 않았습니다.
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);
}
}
Alex Volovoy 답변은 활동의 onCreate 메소드에있는 경우에만 작동합니다.
모든 방법에서 작동하는 대답은 다른 스레드에 있습니다.
다음은 코드의 적응입니다
Resources standardResources = getBaseContext().getResources();
AssetManager assets = standardResources.getAssets();
DisplayMetrics metrics = standardResources.getDisplayMetrics();
Configuration config = new Configuration(standardResources.getConfiguration());
config.locale = new Locale(languageToLoad);
Resources defaultResources = new Resources(assets, metrics, config);
도움이 되길 바랍니다.
몇 주 후에 출시 updateConfiguration
되는 Android M 릴리스 에서는이 솔루션을 더 이상 사용할 수 없습니다 . 이를 수행하는 새로운 방법은 이제 API doc 참조 의 applyOverrideConfiguration
메소드를 사용하는 것입니다.ContextThemeWrapper
https://stackoverflow.com/a/31787201/2776572 내가 직접 문제에 직면했기 때문에 내 전체 솔루션을 찾을 수 있습니다.
구현해야 할 몇 가지 단계가 있습니다
먼저 구성의 로캘을 변경해야합니다
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = new Locale(language);
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
둘째, 표시되는 레이아웃에 변경 사항을 직접 적용하려면 뷰를 직접 업데이트하거나 activity.recreate ()를 호출하여 현재 활동을 다시 시작할 수 있습니다.
또한 사용자가 응용 프로그램을 닫은 후에는 언어 변경 내용이 손실되므로 변경 내용을 유지해야합니다.
내 블로그 게시물 에서 언어를 프로그래밍 방식으로 Android에서 보다 자세하게 설명 했습니다.
기본적으로 응용 프로그램 클래스에서 LocaleHelper.onCreate ()를 호출하고 로케일을 즉시 변경하려면 LocaleHelper.setLocale ()을 호출 할 수 있습니다
버튼을 눌러 TextView의 텍스트 언어를 변경하면 작동합니다 (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();
LocaleHelper 클래스 추가
public class LocaleHelper{
private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
public static Context onAttach(Context context) {
String lang = getPersistedData(context, Locale.getDefault().getLanguage());
return setLocale(context, lang);
}
public static Context onAttach(Context context, String defaultLanguage) {
String lang = getPersistedData(context, defaultLanguage);
return setLocale(context, lang);
}
public static String getLanguage(Context context) {
return getPersistedData(context, Locale.getDefault().getLanguage());
}
public static Context setLocale(Context context, String language) {
persist(context, language);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
}
return updateResourcesLegacy(context, language);
}
private static String getPersistedData(Context context, String defaultLanguage) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
}
private static void persist(Context context, String language) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(SELECTED_LANGUAGE, language);
editor.apply();
}
@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
return context.createConfigurationContext(configuration);
}
@SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLayoutDirection(locale);
}
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
}
활동 중 또는 조각
Context context = LocaleHelper.setLocale(this, App.getSharedPre().getLanguage());
Resource resources = context.getResources();
이제 모든 텍스트에 SetText
TextView tv = findViewById(R.id.tv);
tv.setText(resources.getString(R.string.tv));
허용되지만 응답했지만 2017 버전과 유사하고 다시 시작을 추가했습니다 (다시 시작하지 않고 때로는 다음 활동이 여전히 영어를 렌더링합니다).
// Inside some activity...
private void changeDisplayLanguage(String langCode) {
// Step 1. Change the locale in the app's configuration
Resources res = getResources();
android.content.res.Configuration conf = res.getConfiguration();
conf.setLocale(currentLocale);
createConfigurationContext(conf);
// Step 2. IMPORTANT! you must restart the app to make sure it works 100%
restart();
}
private void restart() {
PackageManager packageManager = getPackageManager();
Intent intent = packageManager.getLaunchIntentForPackage(getPackageName());
ComponentName componentName = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(componentName);
mainIntent.putExtra("app_restarting", true);
PrefUtils.putBoolean("app_restarting", true);
startActivity(mainIntent);
System.exit(0);
}
activity.recreate()
3) 반환 된 컨텍스트 리소스를 얻는 데 사용해야한다고 생각합니다
먼저 "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();
conf.locale
더 이상 사용되지 않습니다
private void setLanguage(String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration config = new Configuration();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
config.setLocale(locale);
} else {
config.locale = locale;
}
getResources().updateConfiguration(config,
getResources().getDisplayMetrics());
}
예를 들어 영어를 설정합니다 :
Configuration config = GetBaseContext().getResources().getConfiguration();
Locale locale = new Locale("en");
Locale.setDefault(locale);
config.locale = locale;
GetBaseContext().getResources().updateConfiguration(config,
GetBaseContext().getResources().getDisplayMetrics());
언어는 응용 프로그램뿐만 아니라 장치 시스템에서도 발견되는 경우에만 작동합니다.
아랍어 / RTL 지원
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(updateBaseContextLocale(newBase));
}
public Context updateBaseContextLocale(Context context) {
String language = SharedPreference.getInstance().getValue(context, "lan");//it return "en", "ar" like this
if (language == null || language.isEmpty()) {
//when first time enter into app (get the device language and set it
language = Locale.getDefault().getLanguage();
if (language.equals("ar")) {
SharedPreference.getInstance().save(mContext, "lan", "ar");
}
}
Locale locale = new Locale(language);
Locale.setDefault(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
updateResourcesLocale(context, locale);
return updateResourcesLocaleLegacy(context, locale);
}
return updateResourcesLocaleLegacy(context, locale);
}
@TargetApi(Build.VERSION_CODES.N)
private Context updateResourcesLocale(Context context, Locale locale) {
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
return context.createConfigurationContext(configuration);
}
@SuppressWarnings("deprecation")
private Context updateResourcesLocaleLegacy(Context context, Locale locale) {
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}