是否有可能在使用Android资源的同时以编程方式改变应用程序的语言?

如果不是,是否可以用特定的语言请求资源?

我想让用户改变应用程序的语言从应用程序。


当前回答

您可以要求用户在第一个屏幕中选择语言并将其保存在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;

    }
}

其他回答

下面是一些适合我的代码:

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

来源:这里

对于Android 7.0牛轧糖(或更低),请遵循这篇文章:

在Android中以编程方式改变语言

旧的答案 这包括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());
}

这是有可能的。您可以设置区域。然而,我不建议这样做。我们在早期阶段尝试过,基本上是在对抗这个系统。

我们对改变语言有同样的要求,但决定接受UI应该与手机UI相同的事实。它是通过设置locale工作,但太bug了。根据我的经验,每次输入活动(每个活动)时都必须设置它。这里是一个代码,如果你仍然需要这个(再次强调,我不推荐)

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个小写字母

根据这篇文章。您需要下载那篇文章中引用的LocaleHelper.java。

Create MyApplication class that will extends Application Override attachBaseContext() to update language. Register this class in manifest. public class MyApplication extends Application { @Override protected void attachBaseContext(Context base) { super.attachBaseContext(LocaleHelper.onAttach(base, "en")); } } <application android:name="com.package.MyApplication" .../> Create BaseActivity and override onAttach() to update language. Needed for Android 6+ public class BaseActivity extends Activity { @Override protected void attachBaseContext(Context base) { super.attachBaseContext(LocaleHelper.onAttach(base)); } } Make all activities on your app extends from 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; } }

对我来说,最好的解决办法是: https://www.bitcaal.com/how-to-change-the-app-language-programmatically-in-android/

package me.mehadih.multiplelanguage;

import androidx.appcompat.app.AppCompatActivity;

import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.util.DisplayMetrics;

import java.util.Locale;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setApplicationLocale("az"); // short name of language. "en" for English
        setContentView(R.layout.activity_main);

    }

    private void setApplicationLocale(String locale) {
        Resources resources = getResources();
        DisplayMetrics dm = resources.getDisplayMetrics();
        Configuration config = resources.getConfiguration();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            config.setLocale(new Locale(locale.toLowerCase()));
        } else {
            config.locale = new Locale(locale.toLowerCase());
        }
        resources.updateConfiguration(config, dm);
    }
}