프로그래밍 방식으로 로캘 설정


139

내 앱은 3 개 언어 (4 개 언어)를 지원합니다. 여러 로케일이 상당히 유사하기 때문에 사용자가 내 응용 프로그램에서 로케일을 변경하는 옵션을 제공하고 싶습니다. 예를 들어 이탈리아 사람은 영어보다 스페인어를 선호 할 수 있습니다.

사용자가 응용 프로그램에 사용할 수있는 로캘 중에서 선택한 다음 사용되는 로캘을 변경할 수있는 방법이 있습니까? 기본 클래스에서 수행하는 간단한 작업이므로 각 활동에 대한 로캘을 설정하는 데 문제가 있다고 생각하지 않습니다.


나중에 기본 로케일을 복원하는 방법이 필요하거나 언어 목록이 포함 된 언어 환경 설정이 필요하고 로케일을보다 편리하게 변경하려면 github.com/delight-im/Android
caw

답변:


114

configuration.localeAPI 24에서 더 이상 사용되지 않으므로이 답변을 찾고있는 사람들 은 이제 다음을 사용할 수 있습니다.

configuration.setLocale(locale);

이 메소드의 minSkdVersion이 API 17임을 고려하십시오.

전체 예제 코드 :

@SuppressWarnings("deprecation")
private void setLocale(Locale locale){
    SharedPrefUtils.saveLocale(locale); // optional - Helper method to save the selected language to SharedPreferences in case you might need to attach to activity context (you will need to code this)
    Resources resources = getResources();
    Configuration configuration = resources.getConfiguration();
    DisplayMetrics displayMetrics = resources.getDisplayMetrics();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
        configuration.setLocale(locale);
    } else{
        configuration.locale=locale;
    }
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N){
        getApplicationContext().createConfigurationContext(configuration);
    } else {
        resources.updateConfiguration(configuration,displayMetrics);
    }
}

실행중인 활동으로 로케일을 변경하는 경우 변경 사항을 적용하려면 로케일을 다시 시작해야합니다.

2018 년 5 월 11 일 수정

@CookieMonster의 게시물에서와 같이 고급 API 버전에서 로캘 변경을 유지하는 데 문제가있을 수 있습니다. 그렇다면 기본 활동에 다음 코드를 추가하여 모든 활동 작성시 컨텍스트 로케일을 업데이트하십시오.

@Override
protected void attachBaseContext(Context base) {
     super.attachBaseContext(updateBaseContextLocale(base));
}

private Context updateBaseContextLocale(Context context) {
    String language = SharedPrefUtils.getSavedLanguage(); // Helper method to get saved language from SharedPreferences
    Locale locale = new Locale(language);
    Locale.setDefault(locale);

    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
        return updateResourcesLocale(context, locale);
    }

    return updateResourcesLocaleLegacy(context, locale);
}

@TargetApi(Build.VERSION_CODES.N_MR1)
private Context updateResourcesLocale(Context context, Locale locale) {
    Configuration configuration = new 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;
}

이것을 사용하는 경우 로케일을 설정할 때 언어를 SharedPreferences에 저장하는 것을 잊지 마십시오 setLocate(locale)

2020 년 4 월 7 일 수정

Android 6 및 7에서 문제가 발생했을 수 있으며 야간 모드를 처리하는 동안 androidx 라이브러리의 문제로 인해 발생합니다. 이를 applyOverrideConfiguration위해 기본 활동에서 재정의 하고 새로운 로케일이 새로 생성 될 경우 구성 로케일을 업데이트해야합니다.

샘플 코드 :

@Override
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) {
        // update overrideConfiguration with your locale  
        setLocale(overrideConfiguration) // you will need to implement this
    }
    super.applyOverrideConfiguration(overrideConfiguration);
} 

2
이것은 활동에 효과적이지만 응용 프로그램 컨텍스트를 업데이트하는 방법이 있습니까?
alekop

2
Android 7에서는 작동하지 않지만 Android 9에서는 작동 하도록 androidx.appcompat:appcompat:버전을 변경 한 후1.0.21.1.0
Bek

4
나와 1.1.0Androidx에 대한 동일한 문제
Alexander Dadukin

2
나에게도 같은 문제입니다. 1.1.0 'LIB : APPCOMPAT : 나는 androidx.appcompat로 변경 후
라훌 Jidge

4
내부에서 문제를 appcompat:1.1.0해결할 수 있으며 내부 appcompat:1.2.0-alpha02코드Set<Locale> set = new LinkedHashSet<>(); // bring the target locale to the front of the list set.add(locale); LocaleList all = LocaleList.getDefault(); for (int i = 0; i < all.size(); i++) { // append other locales supported by the user set.add(all.get(i)); } Locale[] locales = set.toArray(new Locale[0]); configuration.setLocales(new LocaleList(locales));@TargetApi(Build.VERSION_CODES.N) updateResourcesLocale()
Vojtech Pohl

178

on on Resume 에서이 도움을 바랍니다.

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

2
모든 활동에 대해 설정해야합니까?
Tobias

6
1. getBaseContext ()를 사용해야합니까? 아니면 응용 프로그램 contex를 사용하는 것이 더 좋습니까? 2.이 코드는 각 활동에서 호출되어야합니까? 감사.
Paul

10
이 코드를 내 런처 활동 (및 다른 곳)의 onCreate ()에 넣고 로케일이 전체 앱에 적용되었음을 알게되어 기뻤습니다. 이 앱은 minSDK가 14 (ICS) 인 4.3을 타겟팅하는 앱에 있습니다.
IAmKale

8
새로운 Configuration 객체를 만들 필요가 없습니다. 현재 구성을 사용하고 업데이트 할 수 있습니다. getResources (). getConfiguration ()
jmart

1
) 새로운 구성 (사용하지 않는 ;, 그것은 textAppearance, fontSize는 변경
Jemshit Iskenderov

22

Android OS N 이상이 설치된 장치에서 프로그래밍 방식으로 로캘을 설정하는 데 문제가있었습니다 . 나를 위해 솔루션은 기본 활동 에서이 코드를 작성했습니다.

(기본 활동이없는 경우 모든 활동에서 이러한 변경을 수행해야합니다)

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(updateBaseContextLocale(base));
}

private Context updateBaseContextLocale(Context context) {
    String language = SharedPref.getInstance().getSavedLanguage();
    Locale locale = new Locale(language);
    Locale.setDefault(locale);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        return updateResourcesLocale(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;
}

여기서는 전화하기에 충분하지 않습니다.

createConfigurationContext(configuration)

또한이 메소드가 리턴하는 컨텍스트를 확보 한 후 메소드에서이 컨텍스트를 설정해야합니다 attachBaseContext.


가장 쉽고 효과적인 솔루션입니다! 이것이 정답입니다.
Prasad Pawar

3
이 코드는 7 이상의 안드로이드에서는 크게 작동하지만 N 이하의 버전에서는 작동하지 않습니다. 해결책이 있습니까?
Matin Ashtiani

그것이 나를 위해 일하고 있기 때문에 확실하지 않습니다. 내가 볼 수 있도록 구현을 보내시겠습니까?
CookieMonster

2
resources.updateConfiguration이 attachBaseContext () 대신 onCreate ()에서 호출되어야하기 때문에 Android N 버전에서는 작동하지 않습니다.
Chandler

@Chandler가 옳습니다. Android 6-의 경우 부모 / 기본 활동 updateBaseContextLocale에서 메소드를 호출하십시오 onCreate.
Azizjon Kholmatov

22

이 문제를 해결하는 현재 방법에 대한 답변이 완료되지 않았으므로 완벽한 솔루션에 대한 지침을 제공하려고합니다. 빠진 것이 있거나 더 잘할 수 있으면 의견을 말하십시오.

일반 정보

먼저, 문제를 해결하고자하는 라이브러리가 있지만 모두 구식이거나 일부 기능이 없습니다.

또한 라이브러리를 작성하는 것이이 문제를 해결하는 좋은 방법이 아닐 수 있다고 생각합니다. 할 일이 많지 않기 때문에해야 할 일은 완전히 분리 된 것을 사용하는 것보다 기존 코드를 변경하는 것입니다. 따라서 다음 지침을 완성해야합니다.

내 솔루션은 주로 https://github.com/gunhansancar/ChangeLanguageExample ( localhost 에 의해 이미 연결된)을 기반으로 합니다. 내가 찾은 최고의 코드입니다. 일부 비고 :

  • 필요에 따라 Android N (이상) 이하의 로케일을 변경하기 위해 다양한 구현을 제공합니다.
  • 방법을 사용합니다 updateViews()각 액티비티 를 사용하여 로케일을 변경 한 후 (보통 사용) 모든 문자열을 수동으로 업데이트 getString(id)합니다.
  • 언어 만 지원하며 지역 (국가) 및 변형 코드도 포함하는 완전한 로캘은 지원하지 않습니다.

선택한 로케일을 유지하는 부분을 분리하여 조금 변경했습니다 (아래 제안 된대로 별도로 수행 할 수도 있음).

해결책

솔루션은 다음 두 단계로 구성됩니다.

  • 앱에서 사용할 로캘을 영구적으로 변경
  • 앱을 다시 시작하지 않고 사용자 지정 로캘 세트를 사용하도록 설정

1 단계 : 로캘 변경

gunhansancar의 LocaleHelper를LocaleHelper 기반으로 클래스를 사용하십시오 .

  • 사용 가능한 언어로 ListPreferencea PreferenceFragment를 추가하십시오 (언어가 나중에 추가 될 때 유지되어야 함).
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;

import mypackage.SettingsFragment;

/**
 * Manages setting of the app's locale.
 */
public class LocaleHelper {

    public static Context onAttach(Context context) {
        String locale = getPersistedLocale(context);
        return setLocale(context, locale);
    }

    public static String getPersistedLocale(Context context) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        return preferences.getString(SettingsFragment.KEY_PREF_LANGUAGE, "");
    }

    /**
     * Set the app's locale to the one specified by the given String.
     *
     * @param context
     * @param localeSpec a locale specification as used for Android resources (NOTE: does not
     *                   support country and variant codes so far); the special string "system" sets
     *                   the locale to the locale specified in system settings
     * @return
     */
    public static Context setLocale(Context context, String localeSpec) {
        Locale locale;
        if (localeSpec.equals("system")) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                locale = Resources.getSystem().getConfiguration().getLocales().get(0);
            } else {
                //noinspection deprecation
                locale = Resources.getSystem().getConfiguration().locale;
            }
        } else {
            locale = new Locale(localeSpec);
        }
        Locale.setDefault(locale);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return updateResources(context, locale);
        } else {
            return updateResourcesLegacy(context, locale);
        }
    }

    @TargetApi(Build.VERSION_CODES.N)
    private static Context updateResources(Context context, Locale locale) {
        Configuration configuration = context.getResources().getConfiguration();
        configuration.setLocale(locale);
        configuration.setLayoutDirection(locale);

        return context.createConfigurationContext(configuration);
    }

    @SuppressWarnings("deprecation")
    private static Context updateResourcesLegacy(Context context, Locale 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;
    }
}

SettingsFragment다음과 같이 작성하십시오 .

import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import mypackage.LocaleHelper;
import mypackage.R;

/**
 * Fragment containing the app's main settings.
 */
public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
    public static final String KEY_PREF_LANGUAGE = "pref_key_language";

    public SettingsFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_settings, container, false);
        return view;
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        switch (key) {
            case KEY_PREF_LANGUAGE:
                LocaleHelper.setLocale(getContext(), PreferenceManager.getDefaultSharedPreferences(getContext()).getString(key, ""));
                getActivity().recreate(); // necessary here because this Activity is currently running and thus a recreate() in onResume() would be too late
                break;
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        // documentation requires that a reference to the listener is kept as long as it may be called, which is the case as it can only be called from this Fragment
        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onPause() {
        super.onPause();
        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
    }
}

locales.xml다음과 같은 방식으로 사용 가능한 번역이 포함 된 모든 로케일을 나열 하는 자원을 작성하십시오 ( 로케일 코드 목록 ).

<!-- Lists available locales used for setting the locale manually.
     For now only language codes (locale codes without country and variant) are supported.
     Has to be in sync with "settings_language_values" in strings.xml (the entries must correspond).
  -->
<resources>
    <string name="system_locale" translatable="false">system</string>
    <string name="default_locale" translatable="false"></string>
    <string-array name="locales">
        <item>@string/system_locale</item> <!-- system setting -->
        <item>@string/default_locale</item> <!-- default locale -->
        <item>de</item>
    </string-array>
</resources>

당신에 PreferenceScreen당신은 사용자가 사용할 수있는 언어를 선택할 수 있도록하기 위해 다음 섹션을 사용할 수 있습니다 :

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory
        android:title="@string/preferences_category_general">
        <ListPreference
            android:key="pref_key_language"
            android:title="@string/preferences_language"
            android:dialogTitle="@string/preferences_language"
            android:entries="@array/settings_language_values"
            android:entryValues="@array/locales"
            android:defaultValue="@string/system_locale"
            android:summary="%s">
        </ListPreference>
    </PreferenceCategory>
</PreferenceScreen>

다음에서 다음 문자열을 사용합니다 strings.xml.

<string name="preferences_category_general">General</string>
<string name="preferences_language">Language</string>
<!-- NOTE: Has to correspond to array "locales" in locales.xml (elements in same orderwith) -->
<string-array name="settings_language_values">
    <item>Default (System setting)</item>
    <item>English</item>
    <item>German</item>
</string-array>

2 단계 : 앱에서 사용자 지정 로캘을 사용하도록 설정

이제 사용자 정의 로케일 세트를 사용하도록 각 활동을 설정하십시오. 이를 달성하는 가장 쉬운 방법은 다음 코드 (중요 코드가 attachBaseContext(Context base)및에있는 onResume())를 사용하여 모든 활동에 대한 공통 기본 클래스를 갖는 것입니다 .

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

import mypackage.LocaleHelper;
import mypackage.R;

/**
 * {@link AppCompatActivity} with main menu in the action bar. Automatically recreates
 * the activity when the locale has changed.
 */
public class MenuAppCompatActivity extends AppCompatActivity {
    private String initialLocale;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initialLocale = LocaleHelper.getPersistedLocale(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_settings:
                Intent intent = new Intent(this, SettingsActivity.class);
                startActivity(intent);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base));
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (initialLocale != null && !initialLocale.equals(LocaleHelper.getPersistedLocale(this))) {
            recreate();
        }
    }
}

그것이하는 일은

  • attachBaseContext(Context base)이전에 유지했던 로캘을 사용하도록 재정의LocaleHelper
  • 로케일 변경을 감지하고 활동을 다시 작성하여 문자열을 업데이트하십시오.

이 솔루션에 대한 참고 사항

  • 활동을 다시 생성해도 ActionBar의 제목이 업데이트되지 않습니다 (이미 여기에서 관찰 됨) : https://github.com/gunhansancar/ChangeLanguageExample/issues/1 ).

    • 이것은 단순히 각 활동 setTitle(R.string.mytitle)onCreate()방법 을 사용하여 달성 할 수 있습니다 .
  • 사용자가 시스템 기본 로케일과 앱의 기본 로케일 (이 경우 "영어")을 선택할 수 있습니다.

  • fr-rCA지금까지 언어 코드, 지역 (국가) 및 변형 코드 (예 :) 만 지원됩니다. 전체 로케일 사양을 지원하기 위해 Android-Languages ​​라이브러리 와 유사한 파서를 사용할 수 있습니다 (지역 코드는 지원하지만 변형 코드는 지원하지 않음).

    • 누군가가 좋은 파서를 찾거나 작성한 경우 솔루션에 주석을 포함시킬 수 있도록 주석을 추가하십시오.

1
훌륭하지만 악몽의 왕
Odys

1
지옥 아니, 내 응용 프로그램은 이미 너무 복잡합니다.이 접근법은 미래에 유지하기에는 악몽이 될 것입니다.
Josh

@Josh 이것에 대해 좀 더 설명해 주시겠습니까? 실제로 사용하는 각 활동 기본 클래스에 몇 줄만 추가하면됩니다. 모든 활동에 동일한 기본 클래스를 사용하는 것이 불가능할 수도 있지만 더 큰 프로젝트조차도 소수의 사람들과 함께 할 수 있어야합니다. 가로 지향 프로그래밍은 여기에 도움이되지만 구성 (의 코드 움직일 수 attachBaseContext(Context base)onResume()트릭을 할 수있는 별도의 클래스를). 그런 다음 각 활동 기본 클래스에서 하나의 오브젝트를 선언하고 해당 두 호출을 위임하기 만하면됩니다.
user905686

사용자가 로케일을 변경하면 이전의 모든 활동 페이지의 로케일도 변경할 수 있습니까?
Raju yourPepe

이것이이 문제에 대한 최상의 답변입니다. 감사합니다 형제, 그것은 작동
알록 굽타에게

16
@SuppressWarnings("deprecation")
public static void forceLocale(Context context, String localeCode) {
    String localeCodeLowerCase = localeCode.toLowerCase();

    Resources resources = context.getApplicationContext().getResources();
    Configuration overrideConfiguration = resources.getConfiguration();
    Locale overrideLocale = new Locale(localeCodeLowerCase);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        overrideConfiguration.setLocale(overrideLocale);
    } else {
        overrideConfiguration.locale = overrideLocale;
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        context.getApplicationContext().createConfigurationContext(overrideConfiguration);
    } else {
        resources.updateConfiguration(overrideConfiguration, null);
    }
}

이 도우미 메서드를 사용하여 특정 로캘을 적용하십시오.

UDPATE 22 AUG 2017. 이 방법을 사용 하는 것이 좋습니다 .


4

다음 메소드를 사용하여 헬퍼 클래스를 추가하십시오.

public class LanguageHelper {
    public static final void setAppLocale(String language, Activity activity) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            Resources resources = activity.getResources();
            Configuration configuration = resources.getConfiguration();
            configuration.setLocale(new Locale(language));
            activity.getApplicationContext().createConfigurationContext(configuration);
        } else {
            Locale locale = new Locale(language);
            Locale.setDefault(locale);
            Configuration config = activity.getResources().getConfiguration();
            config.locale = locale;
            activity.getResources().updateConfiguration(config,
                    activity.getResources().getDisplayMetrics());
        }

    }
}

시작 활동에서 다음과 같이 호출하십시오 MainActivity.java.

public void onCreate(Bundle savedInstanceState) {
    ...
    LanguageHelper.setAppLocale("fa", this);
    ...
}

3

간단하고 쉬운

Locale locale = new Locale("en", "US");
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = locale;
res.updateConfiguration(conf, dm);

여기서 "en"은 언어 코드이고 "US"는 국가 코드입니다.


내 게시물에 명시된 바와 같이 conf.locale=locale;더 이상 사용되지 않으며 또한입니다 updateConfiguration.
Ricardo

매우 간단하고 덜 복잡한 :)
Ramkesh Yadav

2

API16에서 API28까지 유효합니다.이 메소드를 다음 위치에 두십시오.

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

다음을 사용하여 모든 활동에이 코드를 삽입하십시오.

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(localeUpdateResources(base, "<-- language code -->"));
    }

새 컨텍스트가 필요한 조각, 어댑터 등에서 localeUpdateResources를 호출하십시오.

크레딧 : Yaroslav Berezanskyi


2

매우 간단한 방법이 있습니다.

BaseActivity, Activity 또는 Fragment에서 overrideBaseBaseContext

 override fun attachBaseContext(context: Context) {
    super.attachBaseContext(context.changeLocale("tr"))
}

신장

fun Context.changeLocale(language:String): Context {
    val locale = Locale(language)
    Locale.setDefault(locale)
    val config = this.resources.configuration
    config.setLocale(locale)
    return createConfigurationContext(config)
}

2

나는 발견 된 androidx.appcompat:appcompat:1.1.0버그는 단순히 호출하여 고정 할 수 getResources()있는applyOverrideConfiguration()

@Override public void
applyOverrideConfiguration(Configuration cfgOverride)
{
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
      Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
    // add this to fix androidx.appcompat:appcompat 1.1.0 bug
    // which happens on Android 6.x ~ 7.x
    getResources();
  }

  super.applyOverrideConfiguration(cfgOverride);
}

1
 /**
 * Requests the system to update the list of system locales.
 * Note that the system looks halted for a while during the Locale migration,
 * so the caller need to take care of it.
 */
public static void updateLocales(LocaleList locales) {
    try {
        final IActivityManager am = ActivityManager.getService();
        final Configuration config = am.getConfiguration();

        config.setLocales(locales);
        config.userSetLocale = true;

        am.updatePersistentConfiguration(config);
    } catch (RemoteException e) {
        // Intentionally left blank
    }
}

1

모든 것을 시도했지만 작동하지 않는 사람들을 위해 . 확인하십시오 당신이 설정 한 경우 darkmodeAppCompatDelegate.setDefaultNightMode시스템은, 어두운 아닌 Configuration.setLocale이상하지 않습니다 작업 의 Andorid 7.0 .

이 문제를 해결하려면 모든 활동에이 코드를 추가하십시오.

override fun applyOverrideConfiguration(overrideConfiguration: Configuration?) {
  if (overrideConfiguration != null) {
    val uiMode = overrideConfiguration.uiMode
    overrideConfiguration.setTo(baseContext.resources.configuration)
    overrideConfiguration.uiMode = uiMode
  }
  super.applyOverrideConfiguration(overrideConfiguration)
}

-1

이 코드를 활동에 넣으십시오

 if (id==R.id.uz)
    {
        LocaleHelper.setLocale(MainActivity.this, mLanguageCode);

        //It is required to recreate the activity to reflect the change in UI.
        recreate();
        return true;
    }
    if (id == R.id.ru) {

        LocaleHelper.setLocale(MainActivity.this, mLanguageCode);

        //It is required to recreate the activity to reflect the change in UI.
        recreate();
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.