2012-07-23 29 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將從庫切出資源,你不需要(一些有數百)
  • 快速 - 無需解析資源配置
相關問題