使用 resConfig 强制 Android 风格的语言环境 [英] Force locale for Android flavor with resConfig

查看:61
本文介绍了使用 resConfig 强制 Android 风格的语言环境的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Android Build 系统中的 resConfig 和 resConfigs.

I am trying to use the resConfig and resConfigs from the Android Build system.

  • Android Studio 1.2.2 版
  • Gradle 构建版本 1.2.3
  • OSX 10.10.3

我的项目的这两个选项有问题,所以我用 android studio 开始了一个新的空白项目.我附上了我的 build.gradle,其中我只在

I was having problem with these 2 options with my project so I started a new blank project with android studio. I attached my build.gradle where I only added resConfigs "en", "fr" under

android { 
   defaultConfig {
        ...
        resConfigs "en", "fr" 
        ...
   }
}

并定义了 2 种基本口味

And defined 2 basic flavors

productFlavors {
        fr {
            resConfig "fr"
        }

        en {
            resConfig "en"
        }
}

然后我创建了 2 个 strings.xml 文件并翻译了 hello_world 默认标签

I then created a 2 strings.xml files and translated the hello_world default label

/src/main/res/values/strings.xml (默认)
/src/main/res/values-en/strings.xml
/src/main/res/values-fr/strings.xml

/src/main/res/values/strings.xml (default)
/src/main/res/values-en/strings.xml
/src/main/res/values-fr/strings.xml

有了这个,我希望在 MyApplication/app/builds/intermediates/res/en/debug 中只看到 3 个值文件夹,因为我在 resConfigs 中定义为仅使用en"和fr"并过滤任何其他内容

With this, I would expect to see only 3 values folders in MyApplication/app/builds/intermediates/res/en/debug since I defined in the resConfigs to only use "en" and "fr" and filter anything else

/values/
/values-en/
/values-fr/

/values/
/values-en/
/values-fr/

尽管,所有语言的值文件夹仍然在那里,所以 resConfigs 显然没有过滤任何东西.

Although, all languages values folder are still in there so the resConfigs is not filtering anything apparently.

我还希望在运行 enDebug 风味变体时从 values-en 看到标签 hello_world 因为我指定风味 en 将使用 resConfig "en" 尽管当我运行测试应用程序时我看到来自/values-fr 的标签/strings.xml 而不是/values-en/strings.xml 因为平板电脑上的语言被配置为加拿大法语

I would also expect to see the label hello_world from values-en when running enDebug flavor variant since I specified that the flavor en would use resConfig "en" although when I run the test app I see the label from /values-fr/strings.xml instead of /values-en/strings.xml since the language on the tablet is configured as French Canada

我是否误解了 resConfig 背后的目的?如果是这样,我应该如何强制一种风格仅以语言运行而不依赖于操作系统区域设置?此解决方案也必须与 flavorDimensions 兼容,因为我在尝试配置的实际应用中使用它们.

Am I misunderstanding the purpose behind resConfig? If so, how am I supposed to force a flavor to only run in only language and not be dependant on the OS locale setting? This solution must be compatible with flavorDimensions too since I use them in the real app I'm trying to configure.

注意:我还提交了一个错误,因为我认为这种 resConfig 行为确实存在问题https://code.google.com/p/android/issues/detail?id=180694

NOTE: I also filed a bug since I think there really is a problem with this resConfig behavior https://code.google.com/p/android/issues/detail?id=180694

谢谢

推荐答案

好吧,经过几个小时后,对于那些最终遇到相同问题的人,这里是我的问题的解决方案.

Well, after many hours, here's the solution to my problem for those ending up with the same problem.

事实证明 resConfig 不适合我.我发现强制使用特定风味的语言环境的正确且唯一的方法是这样的:

Turns out that resConfig is not for what I though. The proper and only way I found to force the locale for a specific flavor is like this:

首先,确保您的所有活动都扩展了一个公共活动,该活动将负责强制区域设置.(我不得不创建 2,因为我有一些活动扩展了 FragmentActivity 和一些扩展活动.我也不太喜欢在活动构造函数中这样做,但是因为我必须在对 getResources 进行任何调用之前调用 applyOverrideConfiguration,我需要在活动的 onStart 之前调用它).

First, make sure all your activities extends a common activity which will be responsible to force the locale. (I had to create 2 since I have some activities extending FragmentActivity and some extending Activity. I also don't really like doing so in the Activities constructor but since I have to call applyOverrideConfiguration before any call is done on getResources, I need to call it before the activity's onStart).

public class LocaleMainActivity extends Activity {

    public LocaleMainActivity() {
        ActivityUtils.forceLocale(this);
    }
}

public class LocaleMainFragmentActivity extends FragmentActivity {

    public LocaleMainFragmentActivity() {
        ActivityUtils.forceLocale(this);
    }
}

//Method from ActivityUtils
public static void forceLocale(ContextThemeWrapper contextThemeWrapper) {
    Configuration configuration = new Configuration();
    Locale defaultLocale = new Locale(BuildConfig.LOCALE);
    configuration.locale = defaultLocale;
    contextThemeWrapper.applyOverrideConfiguration(configuration);      
}

接下来,您需要在 build.gradle 风格中定义语言环境

Next, you need to define the locale in your build.gradle flavors

productFlavors {

    myFrenchFlavor {
     buildConfigField "String", "LOCALE", ""fr""
    }
    myEnglishFlavor {
      buildConfigField "String", "LOCALE", ""en""
    }
}

我在 API 19+ 上测试了该解决方案.当您在应用中更改语言时也可以使用.

I tested the solution on API 19+. Works when you change language while in the app too.



替代解决方案(不适用于 Android M+ 查看android错误报告)此解决方案在 stackOverflow 上广泛传播,但我在 Android M 上实施此解决方案时遇到了障碍,因此请记住这一点.



Alternate solution (won't work on Android M+ see android bug report) This solution is wide spreaded on stackOverflow but I faced a wall while implementing this on Android M so keep this in mind.

在您的 AndroidApplication 的 onCreate() 中,您可以使用区域设置调用 updateConfiguration.

In the onCreate() of your AndroidApplication you can call updateConfiguration with the locale set.

Locale myLocale = new Locale(BuildConfig.LOCALE);
Resources res = getResources();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, res.getDisplayMetrics());

如果您定义了 onConfigurationChanged(),您还需要重置它

You will also need to reset it if you defined onConfigurationChanged()

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);            
        Configuration config = new Configuration(newConfig);
        config.locale = new Locale(BuildConfig.LOCALE);
        getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
    }

请注意,此 applyOverrideConfiguration 当前具有副作用,此处说明 Chromium webview 似乎不适用于 Android applyOverrideConfiguration.Chromium 团队目前正在致力于此!

Be aware that this applyOverrideConfiguration currently has a side effect which is explained here Chromium webview does not seems to work with Android applyOverrideConfiguration. The Chromium team are currently working on it!

谢谢.

这篇关于使用 resConfig 强制 Android 风格的语言环境的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆