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

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

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


当前回答

这个功能是由谷歌为Android 13正式推出的(也有向后支持)。Android现在允许你为每个应用程序选择语言。

官方文件在这里- https://developer.android.com/guide/topics/resources/app-languages

要设置用户的首选语言,你会要求用户在语言选择器中选择一个地区,然后在系统中设置该值:

// 1. Inside an activity, in-app language picker gets an input locale "xx-YY"
// 2. App calls the API to set its locale
mContext.getSystemService(LocaleManager.class
    ).setApplicationLocales(newLocaleList(Locale.forLanguageTag("xx-YY")));
// 3. The system updates the locale and restarts the app, including any configuration updates
// 4. The app is now displayed in "xx-YY" language

要在语言选择器中显示用户当前的首选语言,你的应用程序可以从系统中获取返回的值:


// 1. App calls the API to get the preferred locale
LocaleList currentAppLocales =
    mContext.getSystemService(LocaleManager.class).getApplicationLocales();
// 2. App uses the returned LocaleList to display languages to the user

其他回答

我终于弄清楚如何设置它工作在两个=N安卓版本。

用你自己的抽象类扩展AppCompatActivity,比如:

abstract class MLAppCompatActivity : AppCompatActivity() {
  override fun attachBaseContext(newBase: Context?) {
    super.attachBaseContext(LocaleHelper.wrap(newBase))
  }

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
        LocaleHelper.wrap(this)
    }
  }
}

attachBaseContext在Android >=N版本上被调用,这样activity将使用正确的上下文。在Android <N上,我们必须以另一种方式调用这个函数,在设置内容视图之前。因此,我们重写onCreate函数来设置正确的上下文。 意思是,每当你创建一个新的Activity时,你必须扩展你的抽象类。比如这个:

class TermsActivity : MLAppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_terms)
  }
}

最后LocaleHelper是这样的:

import android.annotation.TargetApi;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.util.DisplayMetrics;

import com.at_zone.constants.SharedPreferencesKeys;

import java.util.Locale;

public class LocaleHelper extends ContextWrapper {

    public LocaleHelper(Context base) {
        super(base);
    }

    public static Context wrap(Context context) {
        SharedPreferences sharedPreferences = context.getSharedPreferences(
                SharedPreferencesKeys.SHARED_PREFERENCES, Context.MODE_PRIVATE
        );
        String language = sharedPreferences.getString(SharedPreferencesKeys.CURRENT_LANGUAGE, "default");
        if (!language.equals("default")) {
            Configuration config = context.getResources().getConfiguration();
            if (!language.equals("")) {
                Locale locale = new Locale(language);
                Locale.setDefault(locale);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    setSystemLocale(config, locale);
                } else {
                    setSystemLocaleLegacy(context, config, locale);
                }
                config.setLayoutDirection(locale);
                context = context.createConfigurationContext(config);
            }
            return new LocaleHelper(context);
        }
        return context;
    }

    public static String getSystemLanguage(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return getSystemLocale(context).getLanguage().toLowerCase();
        } else {
            return getSystemLocaleLegacy(context).getLanguage().toLowerCase();
        }
    }

    public static Locale getSystemLocaleLegacy(Context context) {
        Configuration config = context.getResources().getConfiguration();
        return config.locale;
    }

    @TargetApi(Build.VERSION_CODES.N)
    public static Locale getSystemLocale(Context context) {
        return context.getResources().getConfiguration().getLocales().get(0);
    }

    public static void setSystemLocaleLegacy(Context context, Configuration config, Locale locale) {
        config.locale = locale;
        Resources res = context.getResources();
        DisplayMetrics dm = res.getDisplayMetrics();
        res.updateConfiguration(config, dm);
    }

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

}

这个功能是由谷歌为Android 13正式推出的(也有向后支持)。Android现在允许你为每个应用程序选择语言。

官方文件在这里- https://developer.android.com/guide/topics/resources/app-languages

要设置用户的首选语言,你会要求用户在语言选择器中选择一个地区,然后在系统中设置该值:

// 1. Inside an activity, in-app language picker gets an input locale "xx-YY"
// 2. App calls the API to set its locale
mContext.getSystemService(LocaleManager.class
    ).setApplicationLocales(newLocaleList(Locale.forLanguageTag("xx-YY")));
// 3. The system updates the locale and restarts the app, including any configuration updates
// 4. The app is now displayed in "xx-YY" language

要在语言选择器中显示用户当前的首选语言,你的应用程序可以从系统中获取返回的值:


// 1. App calls the API to get the preferred locale
LocaleList currentAppLocales =
    mContext.getSystemService(LocaleManager.class).getApplicationLocales();
// 2. App uses the returned LocaleList to display languages to the user

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

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中以编程方式更改应用程序语言,请使用此方法

  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,在你调用方法的地方,这基本上是刷新布局来获得视图上的新字符串 如果你想在另一个类上设置这个方法只需像这样添加context

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

首先为不同的语言创建多个string.xml;然后在onCreate()方法中使用这段代码:

super.onCreate(savedInstanceState);
String languageToLoad  = "fr"; // change your language here
Locale locale = new Locale(languageToLoad); 
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, 
  getBaseContext().getResources().getDisplayMetrics());
this.setContentView(R.layout.main);