在Android中编程实现应用程序语言的更改

572

在仍然使用Android资源的情况下,是否可能通过编程方式更改应用程序的语言?

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

我希望允许用户从应用程序中更改应用程序的语言。


4
您可以使用以下库,它提供语言列表、设置屏幕的偏好以及覆盖应用程序中的语言:https://github.com/delight-im/Android-Languages。 - caw
1
@neu242 是的,它在Android 5.0上运行没有任何问题。 - caw
我已经在另一个帖子中回答了这个问题,请在这里查看: https://dev59.com/MY3da4cB1Zd3GeqP7Pkf#33079919 - Sindri Þór
2
您可以使用以下库:https://github.com/zeugma-solutions/locale-helper-android - josue.0
1
@josue.0,这个库确实是解决这个问题最干净的方案。 - amitavk
显示剩余4条评论
35个回答

1
对我来说,最好的解决方案是这个: 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);
    }
}

1
我明白了,在找到更好的解决方案后,我会在这里发布。 - Kamran Gasimov

1
添加 LocaleHelper 类。
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;
}
}

在Activity或Fragment中。
Context context = LocaleHelper.setLocale(this, App.getSharedPre().getLanguage());
Resource resources = context.getResources();

现在对每个文本执行SetText操作。
TextView tv = findViewById(R.id.tv);
tv.setText(resources.getString(R.string.tv));

1
事情变了,今天,相关的解决方案来自于:Android网站
有很多方法,但最简单的解决方案是使用AndroidX支持库来实现它。
  1. 在AndroidManifest.xml中添加:

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

    dependencies { implementation 'androidx.appcompat:appcompat:1.6.1'`

  3. 在需要更改语言环境的地方添加以下代码:

     SharedPreferences preferences = getSharedPreferences("priv_settings", Context.MODE_PRIVATE);
     String langCode = preferences.getString("Lang_code", "En");
    
     LocaleListCompat appLocale = LocaleListCompat.forLanguageTags(langCode);  // 或使用 "xx-YY"
     AppCompatDelegate.setApplicationLocales(appLocale);
    
小心:调用setApplicationLocales()会重新创建您的Activity。

谢谢。这对我来说很有效。我正在使用安卓倒挂蛋糕。 - undefined

0
如果你正在使用Fragment,并且想要在Android应用程序中以编程方式更改语言,请使用此方法。
  public 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());
     SettingsFragment settingsFragment = new SettingsFragment();
     FragmentManager fragmentManager = requireActivity().getSupportFragmentManager();
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    activity.overridePendingTransition(0,0);
     fragmentTransaction.replace(R.id.main, settingsFragment).commit();
}

然后像这样调用它

setLocale(requireActivity(),"fr");

只需在调用该方法的位置将SettingsFragment更改为您的片段名称,这基本上会刷新布局以获取视图上的新字符串。如果您想将该方法设置在另一个类中,只需像这样添加上下文

public void setLocale(Activity activity, String languageCode,Context context) {
    Locale locale = new Locale(languageCode);
    Locale.setDefault(locale);
    Resources resources = activity.getResources();
    Configuration config = resources.getConfiguration();
    config.setLocale(locale);
    resources.updateConfiguration(config, resources.getDisplayMetrics());
    SettingsFragment settingsFragment = new SettingsFragment();
    FragmentManager fragmentManager = ((AppCompatActivity) context).getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    activity.overridePendingTransition(0,0);
    fragmentTransaction.replace(R.id.main, settingsFragment).commit();
}

0

对于 androidx.appcompat:appcompat 用户,在版本1.3.0之后上述解决方案将会生效。 如此处所提到。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接