प्रोग्राम को स्थानीय रूप से सेट करें


139

मेरा ऐप 3 (जल्द ही 4) भाषाओं को सपोर्ट करता है। चूंकि कई स्थान काफी समान हैं, इसलिए मैं उपयोगकर्ता को अपने आवेदन में स्थान बदलने का विकल्प देना चाहता हूं, उदाहरण के लिए एक इतालवी व्यक्ति अंग्रेजी में स्पेनिश पसंद कर सकता है।

क्या उपयोगकर्ता के लिए उन स्थानों में से एक का चयन करने का तरीका है जो अनुप्रयोग के लिए उपलब्ध हैं और फिर क्या लोकेल का उपयोग किया जाता है? मैं इसे प्रत्येक गतिविधि के लिए स्थान निर्धारित करने की समस्या के रूप में नहीं देखता क्योंकि यह एक आधार वर्ग में प्रदर्शन करने के लिए एक सरल कार्य है।


यदि आपको बाद में डिफ़ॉल्ट लोकेल को पुनर्स्थापित करने के लिए एक तरीका चाहिए या यदि आपको भाषा वरीयता की आवश्यकता है जिसमें भाषाओं की एक सूची है, और यदि आप लोकेल को अधिक आसानी से बदलना चाहते हैं, तो यह सहायक हो सकता है: github.com/delight-im/Android -भाषाएँ
caw

जवाबों:


114

अभी भी इस उत्तर की तलाश कर रहे लोगों के लिए, चूंकि configuration.localeएपीआई 24 से हटा दिया गया था, अब आप इसका उपयोग कर सकते हैं:

configuration.setLocale(locale);

ध्यान रखें कि इस विधि के लिए minSkdVersion एपीआई 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);
    }
}

यह न भूलें कि, यदि आप एक रनिंग गतिविधि के साथ स्थान बदलते हैं, तो आपको परिवर्तनों को प्रभावी करने के लिए इसे फिर से शुरू करना होगा।

EDIT 11 वीं मई 2018

जैसा कि @ CookieMonster के पोस्ट से, आपको उच्च एपीआई संस्करणों में स्थानीय परिवर्तन को बनाए रखने में समस्या हो सकती है। यदि ऐसा है, तो अपनी आधार गतिविधि में निम्न कोड जोड़ें ताकि आप हर गतिविधि के निर्माण पर संदर्भ स्थान को अपडेट करें:

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

यदि आप इसका उपयोग करते हैं, तो जब आप लोकेल सेट करते हैं, तो भाषा को साझा करने के लिए सहेजना न भूलें setLocate(locale)

EDIT 7 वाँ APRIL 2020

आप एंड्रॉइड 6 और 7 में समस्याओं का सामना कर रहे हैं, और नाइट मोड को संभालते हुए एंड्रॉइड लाइब्रेरी में एक समस्या के कारण ऐसा होता है। इसके लिए आपको 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
यह गतिविधियों के लिए काम करता है, लेकिन क्या आवेदन के संदर्भ को अपडेट करने का कोई तरीका है?
एलेकॉप

2
एंड्रॉइड 7 पर काम नहीं करने के लिए androidx.appcompat:appcompat:संस्करण बदलने के बाद , लेकिन एंड्रॉइड 9 पर काम करना।1.0.21.1.0
Bek

4
मेरे लिए और 1.1.0Androidx के लिए एक ही समस्या
अलेक्जेंडर दादुकिन

2
मेरे लिए भी यही समस्या है। बाद मैं androidx.appcompat: appcompat: 1.1.0 'के लिए बदल गया
राहुल जीज

4
समस्या को अंदर और कोड के appcompat:1.1.0साथ ठीक किया जा सकता हैappcompat:1.2.0-alpha02Set<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()
वोजटेक पोहल

178

आशा है कि यह मदद (onResume में):

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

2
तो यह हर गतिविधि के लिए निर्धारित किया जाना है?
टोबियास

6
1. getBaseContext () का उपयोग करना अनिवार्य है या एप्लिकेशन संदर्भ का उपयोग करने के लिए बेहतर होना चाहिए? 2. इस कोड को प्रत्येक गतिविधि में बुलाया जाना चाहिए? धन्यवाद।
पॉल

10
मैंने इस कोड को अपने लॉन्चर एक्टिविटी (और कहीं और) के ऑनक्रिएट () में रखा और यह देखकर सुखद आश्चर्य हुआ कि लोकेल ने पूरे ऐप पर लागू किया। यह 14 (ICS) के एक मिनट के साथ 4.3 लक्ष्य में एक app है।
IAmKale 16

8
नया कॉन्फ़िगरेशन ऑब्जेक्ट बनाने की कोई आवश्यकता नहीं है। आप वर्तमान कॉन्फ़िगरेशन का उपयोग कर सकते हैं और इसे अपडेट कर सकते हैं: getResources ()। GetConfiguration ()
jmart

1
नए कॉन्फ़िगरेशन का उपयोग न करें (); यह टेक्स्ट चेंज को बदलता है, fontSize
Jemshit Iskenderov

22

मुझे एंड्रॉइड ओएस एन और उच्चतर वाले उपकरणों के साथ स्थानीय रूप से प्रोग्राम सेट करने में समस्या थी । मेरे लिए समाधान मेरी आधार गतिविधि में इस कोड को लिख रहा था:

(यदि आपके पास आधार गतिविधि नहीं है तो आपको अपनी सभी गतिविधियों में ये बदलाव करने चाहिए)

@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विधि में सेट करें ।


यह सबसे आसान और कारगर उपाय है! यह स्वीकृत उत्तर होना चाहिए।
प्रसाद पवार

3
यह कोड 7 से ऊपर के एंड्रॉइड पर बहुत काम करता है, लेकिन एन के नीचे के संस्करणों में काम नहीं कर रहा है। क्या आपके पास कोई समाधान है?
मतीन अष्टानी

यकीन नहीं हुआ क्योंकि यह मेरे लिए काम कर रहा है। क्या आप मुझे अपना कार्यान्वयन भेजना चाहते हैं ताकि मैं देख सकूं?
कुकीमेस्टर

2
Android N के तहत संस्करणों में काम नहीं करता है क्योंकि resource.updateConfiguration को onBreate () के बजाय संलग्नक में बुलाया जाना है ()
Chandler

@ चांडलर सही है। एंड्रॉइड 6- के लिए, अपने माता-पिता / आधार गतिविधि की updateBaseContextLocaleविधि को शांत करें onCreate
अजीजजोन खोलमातोव

22

जैसा कि इस समस्या को हल करने के मौजूदा तरीके के लिए कोई जवाब पूरा नहीं है, मैं एक पूर्ण समाधान के लिए निर्देश देने की कोशिश करता हूं। कृपया टिप्पणी करें कि क्या कुछ याद आ रहा है या बेहतर किया जा सकता है।

सामान्य जानकारी

सबसे पहले, कुछ पुस्तकालय मौजूद हैं, जो समस्या को हल करना चाहते हैं, लेकिन वे सभी पुराने लगते हैं या कुछ विशेषताएं याद कर रहे हैं:

  • https://github.com/delight-im/Android-Languages
    • आउटडेटेड ( समस्याएँ देखें )
    • यूआई में एक भाषा का चयन करते समय, यह हमेशा सभी भाषाओं को दिखाता है (पुस्तकालय में हार्डकोड), न केवल उन जहां अनुवाद मौजूद हैं
  • https://github.com/akexorcist/Android-LocalizationActivity
    • काफी परिष्कृत लगता है और नीचे दिखाए गए अनुसार एक समान दृष्टिकोण का उपयोग कर सकता है

इसके अलावा, मुझे लगता है कि एक पुस्तकालय लिखना इस समस्या को हल करने का एक अच्छा / आसान तरीका नहीं हो सकता है क्योंकि ऐसा करने के लिए बहुत कुछ नहीं है, और जो करना है वह मौजूदा कोड को पूरी तरह से डिकोड किए गए उपयोग करने के बजाय बदल रहा है। इसलिए मैंने निम्नलिखित निर्देशों की रचना की, जो पूर्ण होने चाहिए।

मेरा समाधान मुख्य रूप से https://github.com/gunhansancar/ChangeLanguageExample (जैसा कि पहले से हीहोस्टेन से जुड़ा हुआ है ) पर आधारित है । यह सबसे अच्छा कोड है जिस पर मुझे ध्यान देना चाहिए। कुछ टिप्पणी:

  • आवश्यकतानुसार, यह एंड्रॉइड एन (और ऊपर) और नीचे के लिए स्थान बदलने के लिए अलग-अलग कार्यान्वयन प्रदान करता है
  • यह updateViews()प्रत्येक गतिविधि में एक विधि का उपयोग करता है जो स्थानीय रूप से (सामान्य रूप से getString(id)) बदलते हुए सभी स्ट्रिंग्स को मैन्युअल रूप से अपडेट करने के लिए है जो नीचे दिखाए गए दृष्टिकोण में आवश्यक नहीं है
  • यह केवल भाषाओं का समर्थन करता है, न कि पूर्ण स्थानों (जिसमें क्षेत्र (देश) और भिन्न कोड भी शामिल हैं)

मैंने इसे थोड़ा बदल दिया, उस हिस्से को डीकोपिंग करना जो चुने हुए स्थान को बनाए रखता है (जैसा कि अलग-अलग करना चाहते हैं, जैसा कि नीचे सुझाया गया है)।

उपाय

समाधान में निम्नलिखित दो चरण होते हैं:

  • एप्लिकेशन द्वारा उपयोग किए जाने वाले स्थान को स्थायी रूप से बदल दें
  • एप्लिकेशन को पुनः आरंभ किए बिना, कस्टम लोकल सेट का उपयोग करें

चरण 1: स्थान बदलें

गनशंकर के लोकेल हेल्पर केLocaleHelper आधार पर कक्षा का उपयोग करें :

  • एक जोड़े ListPreferenceएक में 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
  • लोकेल के एक परिवर्तन का पता लगाएं और उसके तार को अद्यतन करने के लिए गतिविधि को फिर से बनाएँ

इस समाधान पर नोट्स

  • किसी गतिविधि को फिर से बनाना क्रिया के शीर्षक को अद्यतन नहीं करता है (जैसा कि पहले ही यहाँ देखा गया है: https://github.com/gunhansancar/ChangeLanguageExample/issues/1 )।

    • यह केवल प्रत्येक गतिविधि setTitle(R.string.mytitle)की onCreate()विधि में होने से प्राप्त किया जा सकता है ।
  • यह उपयोगकर्ता को सिस्टम डिफ़ॉल्ट लोकेल, साथ ही ऐप के डिफ़ॉल्ट लोकेल (जो कि इस मामले में "अंग्रेजी" नाम दिया जा सकता है) को चुनने देता है।

  • अब तक केवल भाषा कोड, कोई क्षेत्र (देश) और भिन्न कोड (जैसे fr-rCA) समर्थित नहीं हैं। पूर्ण स्थानीय विशिष्टताओं का समर्थन करने के लिए, एंड्रॉइड-लैंग्वेज लाइब्रेरी के समान एक पार्सर का उपयोग किया जा सकता है (जो क्षेत्र का समर्थन करता है, लेकिन कोई भिन्न कोड नहीं)।

    • अगर कोई अच्छा पार्सर लिखता है या लिखता है, तो टिप्पणी जोड़ें ताकि मैं इसे समाधान में शामिल कर सकूं।

1
उत्कृष्ट लेकिन दुःस्वप्न के राजा
ओडीस

1
नरक नहीं, मेरा ऐप पहले से ही बहुत जटिल है, यह दृष्टिकोण भविष्य में बनाए रखने के लिए एक बुरा सपना होगा।
जोश

@ जोश आप इसे थोड़ा और समझा सकते हैं? वास्तव में आपके द्वारा उपयोग की जाने वाली प्रत्येक गतिविधि बेस क्लास में केवल कुछ पंक्तियाँ जोड़ी जानी हैं। मैं देखता हूं कि सभी गतिविधियों के लिए एक ही आधार वर्ग का उपयोग करना संभव नहीं हो सकता है, लेकिन कुछ के साथ बड़ी परियोजनाओं को भी प्राप्त करने में सक्षम होना चाहिए। पहलू उन्मुख प्रोग्रामिंग यहाँ मदद कर सकता है लेकिन रचना (से कोड के लिए कदम attachBaseContext(Context base)और onResume()एक अलग वर्ग के लिए) चाल कर सकते हैं। फिर आपको केवल प्रत्येक गतिविधि बेस क्लास में एक ऑब्जेक्ट की घोषणा करनी है और उन दो कॉल को डेलिगेट करना है।
user905686

यदि उपयोगकर्ता अपना स्थान बदलता है, तो क्या पिछले सभी गतिविधि पृष्ठों का स्थान भी बदला जा सकता है?
राजू 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);

जहां "एन" भाषा कोड है और "यूएस" देश कोड है।


जैसा कि मेरे पोस्ट में कहा गया है conf.locale=locale;कि पदावनत है, और यह भी है updateConfiguration
रिकार्डो

बहुत सरल और कम जटिल :)
रामकेश यादव

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

या जहां आप नए संदर्भ की जरूरत है, टुकड़े, एडेप्टर, आदि पर localeUpdateResource कॉल करें।

क्रेडिट: यारोस्लाव बेरेज़ांस्की


2

एक सुपर सरल तरीका है।

बेसएक्टिविटी, एक्टिविटी या फ्रैग्मेंट में अटैचमेंटबास कॉन्टेक्स्ट ओवरराइड करता है

 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

उन लोगों के लिए जिन्होंने सब कुछ करने की कोशिश की लेकिन काम नहीं किया । कृपया जांचें कि यदि आपने सेट darkmodeकिया है AppCompatDelegate.setDefaultNightModeऔर सिस्टम अंधेरा नहीं है, तो एंडरिड 7.0 सेConfiguration.setLocale ऊपर काम नहीं करेगा ।

इस समस्या को हल करने के लिए अपनी हर गतिविधि में इस कोड को जोड़ें:

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();
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.