【问题标题】:how to get string from different locales in Android?如何从 Android 中的不同语言环境获取字符串?
【发布时间】:2012-03-17 13:11:52
【问题描述】:

因此,无论设备/应用程序的当前区域设置如何,我都想在多个区域设置中获取字符串的值。我该怎么做?

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

我该怎么做?

谢谢

【问题讨论】:

  • 你是如何实现这个的??请回复:)
  • 作为公认的答案
  • ResourceBundle 应该指资产吗?或者他们可以访问我们的 res 文件夹吗?
  • @chengyang 请更改已接受的答案
  • 您需要指定其他语言而不是通常的语言?如果您使用不同的语言资源,当您使用getString(R.strings.text) 时,您将获得用户语言的字符串(如果用户语言没有文件夹,则为默认值)

标签: android locale android-resources


【解决方案1】:

例如可以这样做吗?

String stringFormat = getString(stringId);
String string = String.format(Locale.ENGLISH, stringFormat, 6);

【讨论】:

    【解决方案2】:

    将此 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
    }
    

    【讨论】:

      【解决方案3】:

      基于上述答案,这很棒但有点复杂。 试试这个简单的功能:

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

      快乐的代码:)

      【讨论】:

        【解决方案4】:

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

        注意如果您使用的是 App Bundle,则需要确保禁用语言拆分或动态安装不同的语言。请参阅https://stackoverflow.com/a/51054393。如果您不这样做,它将始终使用回退。

        如果你有不同地区的各种 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 对象中检索您喜欢的资源。检索资源后无需重置任何内容。

        【讨论】:

        • 你不应该从getResources().getConfiguration()返回的配置中进行新的配置吗?根据 GrepCode,它返回存储在资源中的本地实例。之后更改语言环境字段可能是 Android 感到困惑的真正原因。您可能应该在第一行和第二行之间执行conf = new Configuration(conf);(克隆返回的配置)。
        • @Nulano - 值得一试,但我认为这不是 Android 为何“混乱”(如您所说)的根源。查看Resources 构造函数的源代码,您会发现像这样创建一个新的Resources 对象会改变进程资产(显然是单例)中的内容。一旦我意识到事情需要重新设置,我就没有费心去追查到底是什么原因。构造新的Resources 对象的另一种(可能更简洁)方法是在更改语言环境后调用resources.updateConfiguration(conf, null)
        • 在 API 级别 17+ 中有更好的 API:stackoverflow.com/a/33629163/2245107
        • @Mygod - 是的,这似乎是正确的方法。我会更新我的答案以表明这一点。谢谢!
        • 编辑了答案,并附上了关于默认情况下会破坏此功能的应用程序包的注释,因为用户只会收到一种语言的包。请参阅stackoverflow.com/a/51054393 了解如何解决此问题。
        【解决方案5】:

        这里是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() 调用可能更有效。

        【讨论】:

          猜你喜欢
          • 2011-09-25
          • 2023-03-21
          • 2010-09-23
          • 1970-01-01
          • 1970-01-01
          • 2019-04-24
          • 2022-12-10
          • 1970-01-01
          • 2021-05-20
          相关资源
          最近更新 更多