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

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

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


当前回答

根据这篇文章。您需要下载那篇文章中引用的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; } }

其他回答

在设置内容之前,应该在每个活动中设置区域配置- this.setContentView(r.b ayout.main);

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

我们对改变语言有同样的要求,但决定接受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个小写字母

唯一完全适合我的解决方案是结合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);         
    }
}

这是工作时,我按下按钮改变我的TextView的文本语言。(strings.xml在值-de文件夹)

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

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:在Application的Manifest中添加localeConfig

<manifest>
<application
    android:localeConfig="@xml/locales_config">
</application>

步骤3:在Manifest中应用此服务

<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
android:exported="false">
<meta-data
  android:name="autoStoreLocales"
  android:value="true" />
</service>

步骤4:在应用程序的模块级构建中使用resConfigs属性指定相同的语言。gradle文件:

  android {
  defaultConfig {
      ...
      resConfigs "hi","en"
  }
  }

(要求appCompat版本1.6.0或更高)

implementation 'androidx.appcompat:appcompat:1.6.0'

第5步:现在你可以使用下面的代码来更改应用程序语言(在android 9,10,12和13上测试)

  LocaleListCompat appLocale = LocaleListCompat.forLanguageTags("hi"); //Give user selected language code 
  AppCompatDelegate.setApplicationLocales(appLocale);