2012-07-23 31 views
14

是否可以在运行时知道我的应用程序中嵌入了哪些资源语言?获取应用程序的资源语言

即该文件夹的存在:

values-en 
values-de 
values-fr 
... 
+1

只是好奇:但默认情况下,你不知道哪些语言环境,因为你把它们放在应用程序? – 2012-07-25 17:53:32

+2

你是对的!但我创建一个库(所以最终开发人员可以添加语言),我需要以编程方式知道有多少嵌入 – VinceFR 2012-07-26 07:49:11

回答

10

AssetManager.getLocales()实际上是做到这一点的方式。但是,从公共API中,您创建的每个AssetManager也都具有包含在其搜索路径中的框架资源...因此,当您调用AssetManager.getLocales()时,您还将看到属于框架资源一部分的任何区域设置。没有办法用SDK解决这个问题,对不起。

1

你在说什么吗?

String language = Locale.getDefault().getDisplayLanguage(); 
+0

不,这种方法只是返回默认语言,我想知道我的res文件夹中指定的所有语言 – VinceFR 2012-07-23 10:55:21

2

这些资源琅实际上依赖于语言环境,所以你需要从设备获得区域,你可以从语言环境越来越显示其语言..

Locale myPhoneLocale = Locale.getDefault(); 

然后,您可以调用getDisplayLanguage( )知道哪种语言正在显示。

参考:Locale

+0

相同作为user370305,我想知道我应用程序中的所有可用语言 – VinceFR 2012-07-23 10:57:08

1

尝试调用AssetManager.getLocales()

获取这个资产管理包含数据的语言环境。

或者你可以尝试,如果你可以使用list()得到一个列表。

返回给定路径中所有资产的字符串数组。

+0

getLocales()返回我的设备上可用的语言,而不是我的应用程序。 列表(字符串路径)没有把戏 – VinceFR 2012-07-26 08:19:50

0

你的意思是:

String[] locales = getAssets().getLocales(); 

这将让你得到您的设备安装的语言。

+1

我不想拥有我的设备的语言,但我的应用程序有语言 – VinceFR 2012-07-26 08:07:43

11

这很复杂,因为即使您有一个名为values-de的文件夹,也并不意味着您在那里有任何资源。如果你有string.xmlvalues-de这并不意味着你有字符串值。

值:

<resources> 
    <string name="app_name">LocTest</string> 
    <string name="hello_world">Hello world!</string> 
    <string name="menu_settings">Settings</string> 
</resources> 

值-DE:

<resources> 
    <string name="hello_world">Hallo Welt!</string> 
</resources> 

您可以测试是否为特定的语言环境的资源是不同于默认:

DisplayMetrics metrics = new DisplayMetrics(); 
getWindowManager().getDefaultDisplay().getMetrics(metrics); 
Resources r = getResources(); 
Configuration c = r.getConfiguration(); 
String[] loc = r.getAssets().getLocales(); 
for (int i = 0; i < loc.length; i++) { 
    Log.d("LOCALE", i + ": " + loc[i]); 

    c.locale = new Locale(loc[i]); 
    Resources res = new Resources(getAssets(), metrics, c); 
    String s1 = res.getString(R.string.hello_world); 
    c.locale = new Locale(""); 
    Resources res2 = new Resources(getAssets(), metrics, c); 
    String s2 = res2.getString(R.string.hello_world); 

    if(!s1.equals(s2)){ 
     Log.d("DIFFERENT LOCALE", i + ": "+ s1+" "+s2 +" "+ loc[i]); 
    } 
} 

它有一个错误 - 你可以检查一个值是否有翻译。

上述脏代码将打印类似:

区域设置(5667):51:en_NZ区域设置(5667):52:uk_UA区域设置(5667):53: nl_BE区域设置(5667):54 :de_DE不同的地方(5667):54:Hallo世界! Hello world! de_DE LOCALE(5667):55:ka_GE LOCALE(5667):56:sv_SE LOCALE(5667):57:bg_BG LOCALE(5667):58:de_CH DIFFERENT LOCALE(5667):58:Hallo Welt!你好,世界!将de_CH区域设置(5667):59: fr_CH表示区域设置(5667):60:fi_FI

+0

这应该是一个答案 – injecteer 2015-10-14 15:30:24

2

通过以上我的答案启发创建了一个简单的方法来获得基于提供的翻译所有应用程序的语言:

public static Set<String> getAppLanguages(Context ctx, int id) { 
    DisplayMetrics dm = ctx.getResources().getDisplayMetrics(); 
    Configuration conf = ctx.getResources().getConfiguration(); 
    Locale originalLocale = conf.locale; 
    conf.locale = Locale.ENGLISH; 
    final String reference = new Resources(ctx.getAssets(), dm, conf).getString(id); 

    Set<String> result = new HashSet<>(); 
    result.add(Locale.ENGLISH.getLanguage()); 

    for(String loc : ctx.getAssets().getLocales()){ 
    if(loc.isEmpty()) continue; 
    Locale l = Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT_WATCH ? new Locale(loc.substring(0, 2)) : Locale.forLanguageTag(loc); 
    conf.locale = l; 
    if(!reference.equals(new Resources(ctx.getAssets(), dm, conf).getString(id))) result.add(l.getLanguage()); 
    } 
    conf.locale = originalLocale; 
    return result; 
} 

其中作为id ARG应该使用它在所有的翻译提供,并包含明确区分的R.string.some_message文字,像"Do you really want to delete the object?"

也许这将帮助别人......

2

对于使用摇篮的人,我做到了,就像下面这样遍历所有strings.xml ,抓取目录名称并从那里计算出语言环境。它增加了一个String[]BuildConfig,您可以访问如BuildConfig.TRANSLATION_ARRAY

task buildTranslationArray << { 
    def foundLocales = new StringBuilder() 
    foundLocales.append("new String[]{") 

    fileTree("src/main/res").visit { FileVisitDetails details -> 
     if(details.file.path.endsWith("strings.xml")){ 
      def languageCode = details.file.parent.tokenize('/').last().replaceAll('values-','').replaceAll('-r','-') 
      languageCode = (languageCode == "values") ? "en" : languageCode; 
      foundLocales.append("\"").append(languageCode).append("\"").append(",") 
     } 
    } 

    foundLocales.append("}") 
    //Don't forget to remove the trailing comma 
    def foundLocalesString = foundLocales.toString().replaceAll(',}','}') 
    android.defaultConfig.buildConfigField "String[]", "TRANSLATION_ARRAY", foundLocalesString 

} 
preBuild.dependsOn buildTranslationArray 

所以发生后,上述任务(上预生成)的BuildConfig.TRANSLATION_ARRAY有你的语言环境的列表。

我不是Gradle/Groovy的专家,所以这绝对可以有点整洁。

推理 - 我遇到了很多实施pawelzieba解决方案的问题,当翻译被众包时,我没有可靠的字符串来“比较”。最简单的方法是实际查看可用的值-blah文件夹。

0

通过@的代码启发Injecteer 我也做了以下内容:

的语言列表中的应用支持,有必要通过默认的语言,因为它是无法检测

public static Map<String,String> getAppLanguages(Context context, String appDefaultLang) { 
    Map<String, String> listAppLocales = new LinkedHashMap<>(); 

    listAppLocales.put("default","Auto"); 

    DisplayMetrics metrics = new DisplayMetrics(); 
      Resources res = context.getResources(); 
    Configuration conf = res.getConfiguration(); 
    String[] listLocates = res.getAssets().getLocales(); 

    for (String locate : listLocates) { 

     conf.locale = new Locale(locate); 
     Resources res1 = new Resources(context.getAssets(), metrics, conf); 
     String s1 = res1.getString(R.string.title_itinerary); 
     String value = ucfirst(conf.locale.getDisplayName()); 

     conf.locale = new Locale(""); 
     Resources res2 = new Resources(context.getAssets(), metrics, conf); 
     String s2 = res2.getString(R.string.title_itinerary); 

     if (!s1.equals(s2)) { 
      listAppLocales.put(locate, value); 
     } else if (locate.equals(appDefaultLang)) { 
      listAppLocales.put(locate, value); 
     } 
    } 
    return listAppLocales; 
} 

结果是应用程序所支持的语言列表map<key,value>,第一件事情是,如果你想用它来填充listPreference

3

的灵感来自正在好转哈克斯之解决方案我创建的东西有点清洁:

defaultConfig { 
     .... 

     def locales = ["en", "it", "pl", "fr", "es", "de", "ru"] 

     buildConfigField "String[]", "TRANSLATION_ARRAY", "new String[]{\""+locales.join("\",\"")+"\"}" 
     resConfigs locales 
    } 

然后在Java中使用:

BuildConfig.TRANSLATION_ARRAY 

这种方法的Advatages:

  • 较小的APK - resConfigs将从库切出资源,你不需要(一些有数百)
  • 快速 - 无需解析资源配置
相关问题