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(Activity activity, String languageCode) {
Locale locale = new Locale(languageCode);
Locale.setDefault(locale);
Resources resources = activity.getResources();
Configuration config = resources.getConfiguration();
config.setLocale(locale);
resources.updateConfiguration(config, resources.getDisplayMetrics());
}
- 참고: 언어 코드는 '-'를 얻을 수 없으며 소문자만 2자여야 합니다.
이 코드는 실제로 작동합니다.
fa = 페르시아어, en = 영어
- 참고: 언어 코드는 '-'를 얻을 수 없으며 소문자만 2자여야 합니다.
언코드어에 언어 합니다.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);
}
}
2021년 6월 업데이트(코틀린):
class Main : Activity() {
// Called when the activity is first created.
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val config = resources.configuration
val lang = "fa" // your language code
val locale = Locale(lang)
Locale.setDefault(locale)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
config.setLocale(locale)
else
config.locale = locale
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
createConfigurationContext(config)
resources.updateConfiguration(config, resources.displayMetrics)
this.setContentView(R.layout.main)
}
}
저는 시스템 언어를 프로그래밍 방식으로 변경하는 방법을 찾고 있었습니다.일반적인 애플리케이션은 절대 그렇게 하지 않고 대신 다음 중 하나를 수행해야 한다는 것을 충분히 이해하고 있습니다.
- 수동으로 변경하려면 사용자가 시스템 설정을 가리켜야 합니다.
- 애플리케이션은 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);
만약 당신이 당신의 모든 앱에서 변경된 언어를 유지하고 싶다면 당신은 두 가지를 해야 합니다.
먼저 기본 활동을 작성하고 모든 활동이 다음과 같이 확장되도록 합니다.
public class BaseActivity extends AppCompatActivity {
private Locale mCurrentLocale;
@Override
protected void onStart() {
super.onStart();
mCurrentLocale = getResources().getConfiguration().locale;
}
@Override
protected void onRestart() {
super.onRestart();
Locale locale = getLocale(this);
if (!locale.equals(mCurrentLocale)) {
mCurrentLocale = locale;
recreate();
}
}
public static Locale getLocale(Context context){
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
String lang = sharedPreferences.getString("language", "en");
switch (lang) {
case "English":
lang = "en";
break;
case "Spanish":
lang = "es";
break;
}
return new Locale(lang);
}
}
공유 환경설정에 새 언어를 저장합니다.
둘째, 다음과 같은 응용프로그램 확장을 만듭니다.
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
setLocale();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setLocale();
}
private void setLocale() {
final Resources resources = getResources();
final Configuration configuration = resources.getConfiguration();
final Locale locale = getLocale(this);
if (!configuration.locale.equals(locale)) {
configuration.setLocale(locale);
resources.updateConfiguration(configuration, null);
}
}
}
getLocale()은 위와 같습니다.
그게 다야!이것이 누군가에게 도움이 되기를 바랍니다.
이 기사에 따르면.해당 기사에서 참조한 내용을 다운로드해야 합니다.
- 를 작성
MyApplication
▁를 확장할 수업Application
- 재정의
attachBaseContext()
언어를 업데이트합니다. 매니페스트에 이 클래스를 등록합니다.
public class MyApplication extends Application { @Override protected void attachBaseContext(Context base) { super.attachBaseContext(LocaleHelper.onAttach(base, "en")); } } <application android:name="com.package.MyApplication" .../>
를 작성
BaseActivity
및오라드이버드를 재정의합니다.onAttach()
언어를 업데이트합니다.Android 6+에 필요합니다.public class BaseActivity extends Activity { @Override protected void attachBaseContext(Context base) { super.attachBaseContext(LocaleHelper.onAttach(base)); } }
앱의 모든 활동을 다음에서 확장
BaseActivity
.public class LocaleHelper { private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language"; public static Context onAttach(Context context) { String lang = getPersistedData(context, Locale.getDefault().getLanguage()); return setLocale(context, lang); } public static Context onAttach(Context context, String defaultLanguage) { String lang = getPersistedData(context, defaultLanguage); return setLocale(context, lang); } public static String getLanguage(Context context) { return getPersistedData(context, Locale.getDefault().getLanguage()); } public static Context setLocale(Context context, String language) { persist(context, language); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return updateResources(context, language); } return updateResourcesLegacy(context, language); } private static String getPersistedData(Context context, String defaultLanguage) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); return preferences.getString(SELECTED_LANGUAGE, defaultLanguage); } private static void persist(Context context, String language) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences.Editor editor = preferences.edit(); editor.putString(SELECTED_LANGUAGE, language); editor.apply(); } @TargetApi(Build.VERSION_CODES.N) private static Context updateResources(Context context, String language) { Locale locale = new Locale(language); Locale.setDefault(locale); Configuration configuration = context.getResources().getConfiguration(); configuration.setLocale(locale); configuration.setLayoutDirection(locale); return context.createConfigurationContext(configuration); } @SuppressWarnings("deprecation") private static Context updateResourcesLegacy(Context context, String language) { Locale locale = new Locale(language); Locale.setDefault(locale); Resources resources = context.getResources(); Configuration configuration = resources.getConfiguration(); configuration.locale = locale; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { configuration.setLayoutDirection(locale); } resources.updateConfiguration(configuration, resources.getDisplayMetrics()); return context; } }
발이 걸려 넘어진 부분을 하나 더 추가하는 것뿐입니다.
다른 답은 예를 들어 "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());
Extends 클래확장기들Application
정적 메서드를 만듭니다.그러면 이전의 모든 활동에서 이 메서드를 호출할 수 있습니다.setContentView()
.
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
}
public static void setLocaleFa (Context context){
Locale locale = new Locale("fa");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
context.getApplicationContext().getResources().updateConfiguration(config, null);
}
public static void setLocaleEn (Context context){
Locale locale = new Locale("en_US");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
context.getApplicationContext().getResources().updateConfiguration(config, null);
}
}
활동에서의 사용:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApp.setLocaleFa(MainActivity.this);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
}
저는 앱 시작 자체를 위해 독일어로 변경되었습니다.
여기 제 정확한 코드가 있습니다.누구든 나를 위해 이것을 똑같이 사용하기를 원합니다.(Android에서 프로그래밍 방식으로 언어를 변경하는 방법)
내 코드:
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를 재정의하고 로케일을 호출해야 합니다.Helper.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");
원하는 위치로 이동할 수 있습니다.
업데이트가 필요한 시간입니다.
먼저, 사용되지 않는 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: https://stackoverflow.com/questions/7973023/what-is-the-list-of-supported-languages-locales-on-android
* @param lang language code (e.g. en_US)
* @return the context
* PLEASE READ: This method can be changed for usage outside an Activity. Simply add a COntext to the arguments
*/
public Context setLanguage(String lang/*, Context c*/){
Context c = AndroidLauncher.this;//remove if the context argument is passed. This is a utility line, can be removed totally by replacing calls to c with the activity (if argument Context isn't passed)
int API = Build.VERSION.SDK_INT;
if(API >= 17){
return setLanguage17(lang, c);
}else{
return setLanguageLegacy(lang, c);
}
}
/**
* Set language for API 17
* @param lang
* @param c
* @return
*/
@TargetApi(17)
public Context setLanguage17(String lang, Context c){
Configuration overrideConfiguration = c.getResources().getConfiguration();
Locale locale = new Locale(lang);
Locale.setDefault(locale);
overrideConfiguration.setLocale(locale);
//the configuration can be used for other stuff as well
Context context = createConfigurationContext(overrideConfiguration);//"local variable is redundant" if the below line is uncommented, it is needed
//Resources resources = context.getResources();//If you want to pass the resources instead of a Context, uncomment this line and put it somewhere useful
return context;
}
public Context setLanguageLegacy(String lang, Context c){
Resources res = c.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();//Utility line
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = new Locale(lang);//setLocale requires API 17+ - just like createConfigurationContext
Locale.setDefault(conf.locale);
res.updateConfiguration(conf, dm);
//Using this method you don't need to modify the Context itself. Setting it at the start of the app is enough. As you
//target both API's though, you want to return the context as you have no clue what is called. Now you can use the Context
//supplied for both things
return c;
}
이 코드는 어떤 API를 기반으로 적절한 메서드를 호출하는 하나의 메서드를 가지고 작동합니다.이것은 제가 (Html.fromHtml을 포함하여) 많은 다른 사용되지 않는 통화들을 통해 수행한 것입니다.필요한 인수를 가져온 다음 두 개(또는 세 개 이상)의 메서드 중 하나로 나누고 API 수준에 따라 적절한 결과를 반환하는 메서드가 하나 있습니다.여러 번 확인할 필요가 없기 때문에 유연합니다. "엔트리" 방식이 대신 사용합니다.여기서 입력 방법은 다음과 같습니다.setLanguage
사용하기 전에 이 문서를 읽어 주십시오.
리소스를 얻을 때 반환된 컨텍스트를 사용해야 합니다. 왜죠?여기에서 createConfigurationContext를 사용하고 반환되는 컨텍스트를 사용하지 않는 다른 답변을 보았습니다.이렇게 작동하려면 updateConfiguration을 호출해야 합니다.그것은 더 이상 사용되지 않습니다.메소드에서 반환된 컨텍스트를 사용하여 리소스를 가져옵니다.
사용 예:
생성자 또는 유사한 위치:
ctx = getLanguage(lang);//lang is loaded or generated. How you get the String lang is not something this answer handles (nor will handle in the future)
그런 다음 리소스를 원하는 곳에서 다음을 수행할 수 있습니다.
String fromResources = ctx.getString(R.string.helloworld);
다른 맥락을 사용하면 (이론적으로) 이 문제를 해결할 수 있습니다.
AFAIK 대화상자 또는 토스트를 표시하려면 여전히 활동 컨텍스트를 사용해야 합니다.활동 인스턴스를 사용할 수 있습니다(외부에 있는 경우).
그리고 마지막으로 사용합니다.recreate()
내용을 새로 고칩니다.새로 고침할 의도를 만들지 않아도 되는 바로 가기입니다.
Android 7.0 Nougat 이하 버전의 경우 다음 문서를 참조하십시오.
여기에는 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());
}
당신이 쓴다면,
android:configChanges="locale"
파일)에서 " " " " " " " (" (" " " " " " " " 을 입력할 할 필요가 없습니다.Activity
.
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);
}
}
저도 같은 문제에 직면해 있었습니다.GitHub에서 Android-Localization Activity 라이브러리를 찾았습니다.
이 라이브러리를 사용하면 아래 코드 샘플에서 볼 수 있듯이 런타임에 앱의 언어를 쉽게 변경할 수 있습니다.아래 샘플 코드를 포함한 샘플 프로젝트와 자세한 정보는 github 페이지에서 확인할 수 있습니다.
지역화 활동은 AppCompativity를 확장하므로 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");
}
}
}
첫 화면에서 하고 사자에게첫화언서선어택저요수있다습니청할록도에 하도록 할 수 .SharedPreferences
SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
editor.putString("lang", "si");
editor.apply();
recreate();
그러면 당신은 그것을 매일 가져갈 수 있습니다.Activity
당신의 신청서에.여기서 저는 영어와 신할라어를 설정했습니다.
@Override
protected void attachBaseContext(Context base) {
SharedPreferences prefs = base.getSharedPreferences("uinfo", MODE_PRIVATE);
String restoredText = prefs.getString("lang", "No name defined");
if (restoredText.equals("si")){
super.attachBaseContext(LocaleHelper.localeUpdateResources(base, "si"));
}else{
super.attachBaseContext(LocaleHelper.localeUpdateResources(base, "en"));
}
}
그리고 이것은 당신의localUpdateResources
방법. .LocalHelper
시간
public class LocaleHelper {
public static Context localeUpdateResources(Context context, String languageCode) {
Context newContext = context;
Locale locale = new Locale(languageCode);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration config = new Configuration(resources.getConfiguration());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
config.setLocale(locale);
newContext = context.createConfigurationContext(config);
} else {
config.locale = locale;
resources.updateConfiguration(config, resources.getDisplayMetrics());
}
return newContext;
}
}
Resources.updateConfiguration()
사용자 지정을 생성하지 않고 이 문제를 해결했습니다.
처음에 나는 확장 함수를 만들었습니다.
fun Context.setAppLocale(language: String): Context {
val locale = Locale(language)
Locale.setDefault(locale)
val config = resources.configuration
config.setLocale(locale)
config.setLayoutDirection(locale)
return createConfigurationContext(config)
}
▁the▁then.attachBaseContext
메소드, 단순히 컨텍스트를 새 컨텍스트로 바꿉니다.
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(ContextWrapper(newBase.setAppLocale("bn")))
}
아랍어/RTL 지원용
- - attachBaseContext()를 통해 언어 설정을 업데이트해야 합니다.
- 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;
}
Per-app 언어 기본 설정에 대한 지원이 API 33(Android 13, 현재 Developer Preview 중인 Tiramisu)에 추가되었습니다.
앱의 로케일을 변경하려면 LocaleManager에서 setApplicationLocales를 호출하면 됩니다.
// Set app locale to pt-BR (Portuguese, Brazil)
getSystemService(LocaleManager::class.java)
.applicationLocales = LocaleList(Locale.forLanguageTag("pt-BR"))
https://developer.android.com/about/versions/13/features/app-languages#api-impl 에서 더 보기
저는 이 기능에 대한 기사를 썼습니다. https://proandroiddev.com/exploring-the-new-android-13-per-app-language-preferences-8d99b971b578
언어에 .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);
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()'을 호출해야 합니다. 그렇지 않으면 리소스가 업데이트되지 않습니다.
여기 나열된 솔루션 중 어떤 것도 도움이 되지 않았습니다.
AppCompatDelegate의 경우 Android >= 7.0에서 언어가 켜지지 않았습니다.setDefaultNightMode(AppCompDelicate)를 선택합니다.MODE_NIGHT_YES)
이 LocalUtils는 제대로 작동합니다. https://gist.github.com/GigigoGreenLabs/7d555c762ba2d3a810fe
로케일 유틸리티
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);
}
}
이 기능은 Google for Android 13에 의해 공식적으로 출시되었으며 이전 버전에서도 지원됩니다.Android는 이제 앱별로 언어를 선택할 수 있습니다.
공식 설명서는 여기에 있습니다 - https://developer.android.com/guide/topics/resources/app-languages
사용자가 선호하는 언어를 설정하려면 사용자에게 언어 선택기에서 로케일을 선택한 다음 시스템에서 해당 값을 설정하도록 요청합니다.
// 1. Inside an activity, in-app language picker gets an input locale "xx-YY"
// 2. App calls the API to set its locale
mContext.getSystemService(LocaleManager.class
).setApplicationLocales(newLocaleList(Locale.forLanguageTag("xx-YY")));
// 3. The system updates the locale and restarts the app, including any configuration updates
// 4. The app is now displayed in "xx-YY" language
언어 선택기에 표시할 사용자의 현재 기본 언어를 가져오려면 앱이 시스템에서 값을 다시 가져올 수 있습니다.
// 1. App calls the API to get the preferred locale
LocaleList currentAppLocales =
mContext.getSystemService(LocaleManager.class).getApplicationLocales();
// 2. App uses the returned LocaleList to display languages to the user
Mayuri의 답변은 맞지만 API 33 이상에서만 작동합니다.다음은 단계별 하위 호환 솔루션입니다.
1단계: res/xml 폴더 아래에 locales_config.xml을 만듭니다.
//res/xml/locales_config.xml
<?xml version="1.0" encoding="utf-8"?>
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Add your required languages -->
<locale android:name="hi" />
<locale android:name="en" />
</locale-config>
2단계: 응용 프로그램의 매니페스트에 localeConfig 추가
<manifest>
<application
android:localeConfig="@xml/locales_config">
</application>
3단계: 매니페스트에 이 서비스 추가
<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
android:exported="false">
<meta-data
android:name="autoStoreLocales"
android:value="true" />
</service>
4단계: 앱의 모듈 수준 build.gradle 파일에 있는 resConfigs 속성을 사용하여 동일한 언어를 지정합니다.
android {
defaultConfig {
...
resConfigs "hi","en"
}
}
(appCompat 버전 1.6.0 이상이 필요합니다.)
implementation 'androidx.appcompat:appcompat:1.6.0'
5단계: 이제 아래 코드를 사용하여 앱 언어를 변경할 수 있습니다(안드로이드 9, 10, 12, 13에서 테스트됨).
LocaleListCompat appLocale = LocaleListCompat.forLanguageTags("hi"); //Give user selected language code
AppCompatDelegate.setApplicationLocales(appLocale);
/*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);
}
Locale
configuration
는 각 각각설어합니에 .activity
에 - 내을설기전에하정용 -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);
}
}
출처: 여기
마침내 =N 안드로이드 버전 모두에서 작동하도록 설정하는 방법을 알게 되었습니다.
AppCompativity를 다음과 같은 고유한 추상 클래스로 확장합니다.
abstract class MLAppCompatActivity : AppCompatActivity() {
override fun attachBaseContext(newBase: Context?) {
super.attachBaseContext(LocaleHelper.wrap(newBase))
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
LocaleHelper.wrap(this)
}
}
}
attachBaseContext는 Android >=N 버전에서 호출되며 이 방식으로 활동은 올바른 컨텍스트를 사용합니다.Android < N에서는 콘텐츠 뷰를 설정하기 전에 이 기능을 다른 방법으로 호출해야 합니다.따라서 Create 함수를 재정의하여 올바른 컨텍스트를 설정합니다.즉, 새로운 활동을 작성할 때마다 추상 클래스를 확장해야 합니다.예를 들어 다음과 같습니다.
class TermsActivity : MLAppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_terms)
}
}
그리고 마지막으로 로케일도우미는 다음과 같습니다.
import android.annotation.TargetApi;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.util.DisplayMetrics;
import com.at_zone.constants.SharedPreferencesKeys;
import java.util.Locale;
public class LocaleHelper extends ContextWrapper {
public LocaleHelper(Context base) {
super(base);
}
public static Context wrap(Context context) {
SharedPreferences sharedPreferences = context.getSharedPreferences(
SharedPreferencesKeys.SHARED_PREFERENCES, Context.MODE_PRIVATE
);
String language = sharedPreferences.getString(SharedPreferencesKeys.CURRENT_LANGUAGE, "default");
if (!language.equals("default")) {
Configuration config = context.getResources().getConfiguration();
if (!language.equals("")) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
setSystemLocale(config, locale);
} else {
setSystemLocaleLegacy(context, config, locale);
}
config.setLayoutDirection(locale);
context = context.createConfigurationContext(config);
}
return new LocaleHelper(context);
}
return context;
}
public static String getSystemLanguage(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return getSystemLocale(context).getLanguage().toLowerCase();
} else {
return getSystemLocaleLegacy(context).getLanguage().toLowerCase();
}
}
public static Locale getSystemLocaleLegacy(Context context) {
Configuration config = context.getResources().getConfiguration();
return config.locale;
}
@TargetApi(Build.VERSION_CODES.N)
public static Locale getSystemLocale(Context context) {
return context.getResources().getConfiguration().getLocales().get(0);
}
public static void setSystemLocaleLegacy(Context context, Configuration config, Locale locale) {
config.locale = locale;
Resources res = context.getResources();
DisplayMetrics dm = res.getDisplayMetrics();
res.updateConfiguration(config, dm);
}
@TargetApi(Build.VERSION_CODES.N)
public static void setSystemLocale(Configuration config, Locale locale) {
config.setLocale(locale);
}
}
구현해야 하는 몇 가지 단계가 있습니다.
먼저 구성의 로케일을 변경해야 합니다.
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = new Locale(language);
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
둘째, 변경사항을 표시되는 레이아웃에 직접 적용하려면 보기를 직접 업데이트하거나 activity.recreate()를 호출하여 현재 활동을 다시 시작할 수 있습니다.
또한 사용자가 응용프로그램을 닫은 후 언어 변경 내용이 손실되기 때문에 변경 내용을 유지해야 합니다.
Android에서 프로그래밍 방식으로 언어 변경 블로그 게시물에서 더 자세한 솔루션을 설명했습니다.
기본적으로, 당신은 그냥 로케일에게 전화를 합니다.Helper.onCreate()는 응용 프로그램 클래스에 있으며 로케일을 즉시 변경하려면 로케일에 문의할 수 있습니다.Helper.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();
로케일 추가도우미 클래스
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();
이제 모든 텍스트에 텍스트 설정
TextView tv = findViewById(R.id.tv);
tv.setText(resources.getString(R.string.tv));
언급URL : https://stackoverflow.com/questions/2900023/change-app-language-programmatically-in-android
'programing' 카테고리의 다른 글
vuetify 데이터 테이블 및 json 개체에서 가져온 바인딩 데이터 (0) | 2023.07.15 |
---|---|
판다 데이터 프레임에서 NaN으로 셀을 설정하는 방법 (0) | 2023.07.10 |
SQL Server 2005 쿼리를 CSV로 내보내는 방법 (0) | 2023.07.10 |
사용자 정의 로그인 양식.JSON 응답을 가져오도록 Spring 보안 구성 (0) | 2023.07.10 |
특정 커밋 이후 커밋을 어떻게 나열합니까? (0) | 2023.07.10 |