Android-动态更改语言

时间:2019-07-30 16:00:01

标签: android locale

我正在尝试在Spinner的{​​{1}}中的两种语言之间切换:“英语”和“法语”。

我有我的Activity文件夹和values文件夹,在这些文件夹中有一个名为values-fr的文件,其中包含我要即时翻译的一项活动的字符串。

对于string_my_activity.xml,我目前在普通的strings.xml中用一个字符串数组填充它(稍后将进行翻译)。

我一直在使用来自StackOverflow的样本,说使用SpinnerLocaleHelper。但是,两者都不起作用。我认为问题是我如何使用它们,就像其他人一样成功。

当我尝试在CustomContextWrapper的{​​{1}}中使用它们时,显然没有任何反应。我在活动上执行了onItemSelected,但是当前所有字符串仍然是默认语言。

我正在使用Spinner

recreate()

ContextWrapper

public class CustomContextWrapper extends ContextWrapper {
    public CustomContextWrapper(Context base) {
        super(base);
    }

    @SuppressWarnings("deprecation")
    public static ContextWrapper wrap(Context context, String language) {
        Configuration config = context.getResources().getConfiguration();
        Locale sysLocale;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            sysLocale = getSystemLocale(config);
        } else {
            sysLocale = getSystemLocaleLegacy(config);
        }
        if (!language.equals("") && !sysLocale.getLanguage().equals(language)) {
            Locale locale = new Locale(language);
            Locale.setDefault(locale);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                setSystemLocale(config, locale);
            } else {
                setSystemLocaleLegacy(config, locale);
            }

            context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
        }

        return new ContextWrapper(context);
    }

    @SuppressWarnings("deprecation")
    public static Locale getSystemLocaleLegacy(Configuration config) {
        return config.locale;
    }

    @TargetApi(Build.VERSION_CODES.N)
    public static Locale getSystemLocale(Configuration config) {
        return config.getLocales().get(0);
    }

    @SuppressWarnings("deprecation")
    public static void setSystemLocaleLegacy(Configuration config, Locale locale) {
        config.locale = locale;
    }

    @TargetApi(Build.VERSION_CODES.N)
    public static void setSystemLocale(Configuration config, Locale locale) {
        config.setLocale(locale);
    }
}

但是他们两个都无法正常工作。

在我的LocaleHelper中,我像这样使用它们:

public class LocaleHelper {

    private static final String TAG = LocaleHelper.class.getSimpleName();

    private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
    public static final String DEFAULT_LANGUAGE = "en";

    public static Context onAttach(Context context) {
        Log.d(TAG, "onAttach(context)");
        String lang = getStoredLanguage(context, Locale.getDefault().getLanguage());
//        String lang = getStoredLanguage(context, DEFAULT_LANGUAGE);
        return setLocale(context, lang);
    }

    public static Context onAttach(Context context, String defaultLanguage) {
        Log.d(TAG, "onAttach(context, language)");
        String lang = getStoredLanguage(context, defaultLanguage);
        return setLocale(context, lang);
    }

    public static String getLanguage(Context context) {
        return getStoredLanguage(context, Locale.getDefault().getLanguage());
    }

    public static Context setLocale(Context context, String language) {
        Log.d(TAG, "Setting locale: " + language);
        saveLanguage(context, language);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return updateResources(context, language);
        }

        return updateResourcesLegacy(context, language);
    }

    private static String getStoredLanguage(Context context, String defaultLanguage) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
    }

    private static void saveLanguage(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) {
        Log.d(TAG, "updateResources::" + language);
        Locale locale = new Locale(language);
        Locale.setDefault(locale);

        Resources resources = context.getResources();

        Log.d(TAG, "updateResources:: Getting config");

        Configuration configuration = resources.getConfiguration();
        configuration.setLocale(locale);
        configuration.setLayoutDirection(locale);

        Log.d(TAG, "updateResources:: Creating config context");
        return context.createConfigurationContext(configuration);
    }

    @SuppressWarnings("deprecation")
    private static Context updateResourcesLegacy(Context context, String language) {
        Log.d(TAG, "updateResourcesLegacy");
        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.LOLLIPOP) {
            configuration.setLayoutDirection(locale);
        }

        resources.updateConfiguration(configuration, resources.getDisplayMetrics());

        return context;
    }

    public static Locale getLocale(Configuration config) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return getSystemLocale(config);
        } else {
            return getSystemLocaleLegacy(config);
        }
    }

    @SuppressWarnings("deprecation")
    private static Locale getSystemLocaleLegacy(Configuration config) {
        return config.locale;
    }

    @TargetApi(Build.VERSION_CODES.N)
    private static Locale getSystemLocale(Configuration config) {
        return config.getLocales().get(0);
    }
}

我能得到的最好的语言是显示在日志中的语言,但没有反映在UI中。目前,它似乎总是获得默认语言“ en”,这是另一个问题。

所以我的问题是,如何获取UI进行自我更新? 谢谢。

1 个答案:

答案 0 :(得分:0)

我在互联网上找到了此代码,对我来说,它工作得很好,看看它是否也可以解决您的问题,请根据您的微调器进行修改

 languagebutton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    LocaleManager.setNewLocale(language.this, LocaleManager.LANGUAGE_KEY_ENGLISH);

                String languageToLoad  = LocaleManager.LANGUAGE_KEY_ENGLISH; // your language
                Locale locale = new Locale(languageToLoad);
                Locale.setDefault(locale);
                Configuration config = new Configuration();
                config.locale = locale;
                getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
                try {
                    ActivityInfo info = getPackageManager().getActivityInfo(getComponentName(), GET_META_DATA);
                    if (info.labelRes != 0) {
                        setTitle(info.labelRes);
                    }
                } catch (PackageManager.NameNotFoundException e) {
                    e.printStackTrace();
                }


            }
        });

LocaleManager.java

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;

public class LocaleManager {
    /**
     * For english locale
     */
    public static final String LANGUAGE_KEY_ENGLISH = "en";
    /**
     * for hindi locale
     */
    public static final String LANGUAGE_KEY_HINDI = "hi";
    /***
     * // for spanish locale
     */
    private static final String LANGUAGE_KEY = "language_key";

    /**
     * set current pref locale
     * @param mContext
     * @return
     */
    public static Context setLocale(Context mContext) {
        return updateResources(mContext, getLanguagePref(mContext));
    }

    /**
     * Set new Locale with context
     * @param mContext
     * @param mLocaleKey
     * @return
     */
    public static Context setNewLocale(Context mContext, String mLocaleKey) {
        setLanguagePref(mContext, mLocaleKey);
        return updateResources(mContext, mLocaleKey);
    }

    /**
     * Get saved Locale from SharedPreferences
     * @param mContext current context
     * @return current locale key by default return english locale
     */
    public static String getLanguagePref(Context mContext) {
        SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
        return mPreferences.getString(LANGUAGE_KEY, LANGUAGE_KEY_ENGLISH);
    }

    /**
     *  set pref key
     * @param mContext
     * @param localeKey
     */
    private static void setLanguagePref(Context mContext, String localeKey) {
        SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
        mPreferences.edit().putString(LANGUAGE_KEY, localeKey).commit();
    }

    /**
     * update resource
     * @param context
     * @param language
     * @return
     */
    private static Context updateResources(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);
        Resources res = context.getResources();
        Configuration config = new Configuration(res.getConfiguration());
        if (Build.VERSION.SDK_INT >= 17) {
            config.setLocale(locale);
            context = context.createConfigurationContext(config);
        } else {
            config.locale = locale;
            res.updateConfiguration(config, res.getDisplayMetrics());
        }
        return context;
    }

    /**
     * get current locale
     * @param res
     * @return
     */
    public static Locale getLocale(Resources res) {
        Configuration config = res.getConfiguration();
        return Build.VERSION.SDK_INT >= 24 ? config.getLocales().get(0) : config.locale;
    }
}