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

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

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


当前回答

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

其他回答

我也面临着同样的问题。在GitHub上,我找到了Android-LocalizationActivity库。

这个库使得在运行时更改应用程序的语言变得非常简单,如下面的代码示例所示。包含下面示例代码的示例项目和更多信息可以在github页面上找到。

LocalizationActivity扩展了AppCompatActivity,所以你也可以在使用Fragments时使用它。

public class MainActivity extends LocalizationActivity implements View.OnClickListener {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple);

        findViewById(R.id.btn_th).setOnClickListener(this);
        findViewById(R.id.btn_en).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.btn_en) {
            setLanguage("en");
        } else if (id == R.id.btn_th) {
            setLanguage("th");
        }
    }
}

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

这个功能是由谷歌为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

只是多添了一块,把我绊倒了。

而其他的答案,比如“de”,都没问题

String lang = "de";
Locale locale = new Locale(lang); 
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, 
    getBaseContext().getResources().getDisplayMetrics());

上面不会工作,例如“fr_BE”地区,所以它将使用values-fr-rBE文件夹或类似的。

需要以下轻微更改工作与“fr_BE”

String lang = "fr";

//create a string for country
String country = "BE";
//use constructor with country
Locale locale = new Locale(lang, country);

Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, 
    getBaseContext().getResources().getDisplayMetrics());

Resources.updateConfiguration()已经弃用,我已经解决了这个问题,没有创建任何自定义的ContextWrapper。

首先我创建了一个扩展函数

fun Context.setAppLocale(language: String): Context {
    val locale = Locale(language)
    Locale.setDefault(locale)
    val config = resources.configuration
    config.setLocale(locale)
    config.setLayoutDirection(locale)
    return createConfigurationContext(config)
}

然后在活动的attachBaseContext方法中,简单地用新的上下文替换上下文。

override fun attachBaseContext(newBase: Context) {
  super.attachBaseContext(ContextWrapper(newBase.setAppLocale("bn")))
}