如何从Android中的不同语言环境中获取字符串?

时间:2012-02-28 02:30:48

标签: android locale android-resources

所以我想在多个语言环境中获取String的值,而不管设备/ app的当前语言环境设置如何。我该怎么做?

基本上我需要的是一个函数getString(int id, String locale)而不是getString(int id)

我怎么能这样做?

由于

5 个答案:

答案 0 :(得分:113)

注意如果您的最低API为17+,请直接转到此答案的底部。否则,请继续阅读...

如果您有不同语言环境的各种res文件夹,您可以执行以下操作:

Configuration conf = getResources().getConfiguration();
conf.locale = new Locale("pl");
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
Resources resources = new Resources(getAssets(), metrics, conf);
String str = resources.getString(id);

或者,您可以使用@jyotiprakash指向的方法重新启动您的活动。

注意像这样调用Resources构造函数会在Android内部发生变化。您必须使用原始语言环境调用构造函数,以便以原来的方式恢复原状。

编辑从特定区域设置中检索资源的略有不同(且稍微清晰一点)的方法是:

Resources res = getResources();
Configuration conf = res.getConfiguration();
Locale savedLocale = conf.locale;
conf.locale = desiredLocale; // whatever you want here
res.updateConfiguration(conf, null); // second arg null means don't change

// retrieve resources from desired locale
String str = res.getString(id);

// restore original locale
conf.locale = savedLocale;
res.updateConfiguration(conf, null);

从API级别17开始,您应该使用conf.setLocale()而不是直接设置conf.locale。如果您正好在从右到左和从左到右的区域设置之间切换,这将正确更新配置的布局方向。 (布局方向在17中引入。)

创建新的Configuration对象没有意义(正如@Nulano在评论中建议的那样),因为调用updateConfiguration将改变通过调用res.getConfiguration()获得的原始配置。

如果您要为区域设置加载多个字符串资源,我会毫不犹豫地将其捆绑到getString(int id, String locale)方法中。更改语言环境(使用任一配方)要求框架执行大量重新绑定所有资源的工作。更新区域设置一次,检索所需的所有内容,然后重新设置区域设置要好得多。

编辑(感谢@Mygod):

如果您的最低API级别为17+,那么有一种更好的方法,如this answer另一个帖子所示。例如,您可以创建多个Resource对象,每个对象用于您需要的每个区域设置:

@NonNull Resources getLocalizedResources(Context context, Locale desiredLocale) {
    Configuration conf = context.getResources().getConfiguration();
    conf = new Configuration(conf);
    conf.setLocale(desiredLocale);
    Context localizedContext = context.createConfigurationContext(conf);
    return localizedContext.getResources();
}

然后只需从此方法返回的本地化Resource对象中检索您喜欢的资源。一旦您检索到资源,就无需重置任何内容。

答案 1 :(得分:18)

以下是Ted Hopp描述的方法的组合版本。这样,该代码适用于任何Android版本:

public static String getLocaleStringResource(Locale requestedLocale, int resourceId, Context context) {
    String result;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // use latest api
        Configuration config = new Configuration(context.getResources().getConfiguration());
        config.setLocale(requestedLocale);
        result = context.createConfigurationContext(config).getText(resourceId).toString();
    }
    else { // support older android versions
        Resources resources = context.getResources();
        Configuration conf = resources.getConfiguration();
        Locale savedLocale = conf.locale;
        conf.locale = requestedLocale;
        resources.updateConfiguration(conf, null);

        // retrieve resources from desired locale
        result = resources.getString(resourceId);

        // restore original locale
        conf.locale = savedLocale;
        resources.updateConfiguration(conf, null);
    }

    return result;
}

用法示例:

String englishName = getLocaleStringResource(new Locale("en"), R.string.name, context);

注意

正如原始答案中所述,使用单个配置更改和多个resources.getString()调用替换上述代码的多个调用可能更有效。

答案 2 :(得分:2)

基于以上回答,这些结果真棒,但有些复杂。 试试这个简单的功能:

public String getResStringLanguage(int id, String lang){
    //Get default locale to back it
    Resources res = getResources();
    Configuration conf = res.getConfiguration();
    Locale savedLocale = conf.locale;
    //Retrieve resources from desired locale
    Configuration confAr = getResources().getConfiguration();
    confAr.locale = new Locale(lang);
    DisplayMetrics metrics = new DisplayMetrics();
    Resources resources = new Resources(getAssets(), metrics, confAr);
    //Get string which you want
    String string = resources.getString(id);
    //Restore default locale
    conf.locale = savedLocale;
    res.updateConfiguration(conf, null);
    //return the string that you want
    return string;
}

然后简单地称呼它:String str = getResStringLanguage(R.string.any_string, "en");

快乐代码:)

答案 3 :(得分:0)

单行代码会不会更容易?

String.format(Locale("en"), getString(R.string.your_string))

而且您可以从翻译中访问字符串,而无需进行任何配置更改和其他不可思议的事情。

答案 4 :(得分:0)

将此 Kotlin 扩展函数放入您的代码中并像这样使用它:

getLocaleStringResource(Locale.ENGLISH,R.string.app_name)

fun Context.getLocaleStringResource(
requestedLocale: Locale?,
resourceId: Int,
): String {
val result: String
val config =
    Configuration(resources.configuration)
config.setLocale(requestedLocale)
result = createConfigurationContext(config).getText(resourceId).toString()

return result
}