2012-07-23 3 views
14

Ist es möglich, zur Laufzeit, zu wissen, welche Ressourcen Sprachen sind eingebettet in meine app?erhalten die Ressourcen der Anwendungssprachen

heißt das Vorhandensein dieser Ordner:

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

Nur neugierig: aber wissen Sie standardmäßig nicht, welche Gebietsschemas es gibt, seit Sie sie in die App gelegt haben? –

+2

Sie haben Recht!aber ich erstelle eine Bibliothek (so Ende Entwickler können Sprachen hinzufügen) und ich muss programmgesteuert wissen, wie viele sind eingebettet – VinceFR

Antwort

10

AssetManager.getLocales() ist tatsächlich die Art und Weise, dies zu tun. Von der öffentlichen API hat jeder erstellte AssetManager jedoch auch die Framework-Ressourcen in seinem Suchpfad ... Wenn Sie also AssetManager.getLocales() aufrufen, sehen Sie auch alle Gebietsschemata, die Teil der Framework-Ressourcen sind. Es gibt keine Möglichkeit, dies mit dem SDK zu umgehen, sorry.

1

Sie sprechen darüber sind?

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

Nein, diese Methode nur die Standardsprache zurückgeben, möchte ich alle Sprachen in meinem Ordner res – VinceFR

2

diese res-lang hängt wirklich von Locales, so müssen Sie locale von Gerät zu erhalten und Sie bekommen können, welche Sprache von locale gezeigt wird immer ..

Locale myPhoneLocale = Locale.getDefault(); 

Sie können dann getDisplayLanguage nennen () um zu wissen, welche Sprache angezeigt wird.

Referenz: Locale

+0

angegeben kennen Als user370305 möchte ich alle verfügbaren Sprachen in meiner App kennen. – VinceFR

1

Try Aufruf AssetManager.getLocales():

die Locales bekommen, dass diese Asset-Manager für Daten enthält.

Oder Sie können versuchen, wenn Sie eine Liste mit list() erhalten können.

Gibt ein String-Array aller Assets im angegebenen Pfad zurück.

+0

getLocales() gib mir die Sprache zurück, die auf meinem Gerät verfügbar ist, nicht auf meiner App. Liste (String-Pfad) macht nicht den Trick – VinceFR

0

Meinen Sie:

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

Dies würde Sie die Sprache, die Ihr Gerät erhalten lassen.

+1

Ich möchte nicht die Sprachen, die mein Gerät haben, aber die Sprache, die meine Anwendung haben – VinceFR

11

Es ist kompliziert, denn selbst wenn Sie einen Ordner values-de es bedeutet nicht, Sie haben alle Ressourcen dort genannt haben. Wenn Sie string.xml in values-de haben, bedeutet es nicht, dass Sie String-Wert dort haben.

Werte:

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

Werte-de:

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

können Sie testen, ob eine Ressource für ein bestimmtes Gebietsschema als der Standard unterscheidet:

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]); 
    } 
} 

Es hat eine Fehler - Sie können einen Wert prüfen, ob er übersetzt wurde.

Der schmutzige Code wird über Druck etwas wie:

LOCALE (5667): 51: en_NZ LOCALE (5667): 52: uk_UA LOCALE (5667): 53: nl_BE LOCALE (5667): 54 : de_DE VERSCHIEDENE LOCALE (5667): 54: Hallo Welt! Hallo Welt! de_DE LOCALE (5667): 55: ka_GE LOCALE (5667): 56: sv_SE LOCALE (5667): 57: bg_BG LOCALE (5667): 58: de_CH VERSCHIEDENE LOCALE (5667): 58: Hallo Welt! Hallo Welt!de_CH locale (5667): 59: fr_CH locale (5667): 60: fi_FI

+0

Dies sollte eine Antwort sein – injecteer

2

Inspiriert von den Antworten oben habe ich eine einfache Methode, um alle Sprachen der App zu erhalten, basierend auf bereitgestellten Übersetzungen:

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; 
} 

wo als id arg sollte eine R.string.some_message verwendet werden, die in allen Übersetzungen zur Verfügung gestellt und enthält deutlich unterscheidbar Text, wie "Do you really want to delete the object?"

Vielleicht wäre es jemand helfen ...

2

Für alle Gradle mit, ich habe es wie so darunter alle strings.xml durchquert , greift nach den Verzeichnisnamen und ermittelt die Gebietsschemata von dort. Es fügt eine String[] zu BuildConfig, die Sie als 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 

So zugreifen können, nachdem die obige Aufgabe (auf vorkompilierte) tritt die BuildConfig.TRANSLATION_ARRAY Liste der Schauplätze hat.

Ich bin kein Gradle/Groovy Experte, also könnte dies definitiv ein bisschen besser sein.

Schlussfolgerung - Ich stieß auf zu viele Probleme bei der Implementierung von Pawelziebas Lösung. Ich hatte keine zuverlässigen Strings zum "Vergleichen", da die Übersetzungen Crowdsourcing waren. Am einfachsten war es dann, sich die value-blah-Ordner anzusehen.

0

mit dem Code Inspiriert von @ Injecteer Ich habe das getan folgenden:

für die Liste der Sprachen, die die App unterstützen, ist es notwendig, die Standardsprache zu übergeben, da es nicht möglich ist, zu erkennen,

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; 
} 

das Ergebnis ist eine Liste map<key,value> von Sprachen, die von der Anwendung unterstützt, das erste, was ist denn, wenn Sie wollen eine listPreference

3

Inspiriert von Mend zu füllen verwenden hak Lösung habe ich etwas ein wenig sauberer:

defaultConfig { 
     .... 

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

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

dann in Java verwenden:

BuildConfig.TRANSLATION_ARRAY 

Advatages dieser Methode:

  • Kleinere apk - resConfigs werden Ressourcen von Bibliotheken ausgeschnitten die Sie brauchen nicht (einige haben Hunderte)
  • Schnell - Keine Notwendigkeit, Ressourcenkonfigurationen zu analysieren
Verwandte Themen