Android Plural Behandlung von "Null"

83

Wenn die folgende plural ressource in meiner strings.xml enthalten ist:

   <plurals name="item_shop">
        <item quantity="zero">No item</item>
        <item quantity="one">One item</item>
        <item quantity="other">%d items</item>
   </plurals>   

Ich zeige dem Benutzer das Ergebnis mit:

textView.setText(getQuantityString(R.plurals.item_shop, quantity, quantity));

Es funktioniert gut mit 1 und höher, aber wenn die Menge 0 ist, sehe ich "0 Artikel". Wird der Wert "Null" nur in arabischer Sprache unterstützt, wie aus der Dokumentation hervorgeht? Oder fehlt mir etwas?

EricLarch
quelle
20
Dieses Problem wird hier gemeldet . Code.google.com/p/android/issues/detail?id=8287 . Noch nicht behoben: /
OcuS
5
Ich denke nicht, dass es ein Fehler ist: Beachten Sie, dass die Auswahl basierend auf der grammatikalischen Notwendigkeit getroffen wird. Eine Zeichenfolge für Null in Englisch wird ignoriert, auch wenn die Menge 0 ist, da 0 sich grammatikalisch nicht von 2 oder einer anderen Zahl außer 1 unterscheidet ("Null Bücher", "Ein Buch", "Zwei Bücher" usw.) on)
ByteMe
1
Leider sind nicht alle Sprachen mit Englisch identisch
Armand
2
Ich denke, dies ist ein Fehler in dem Sinne, dass ich, abgesehen von der Grammatik, 99% der Fälle, in denen ich dies verwenden musste, die fehlende Funktionalität benötigte . Also, ja, ich glaube, das ist ein Fehler, den Google wahrscheinlich nie beheben wird. Daher ist eine Problemumgehung erforderlich. Sie sehen, APIs sind dazu da, Verbrauchern zu helfen, Dinge zu erledigen und nicht ausschließlich abstrakte Konzepte aus der realen Welt darzustellen. Wenn Zero sofort unterstützt worden wäre, könnten beide Gruppen (diejenigen, die die Grammatikkorrektheit benötigen und diejenigen, die dies nicht tun) davonkommen, ohne etwas anderes verwenden zu müssen.
Martin Marconcini

Antworten:

88

Die Android-Ressourcenmethode der Internationalisierung ist recht begrenzt. Ich habe mit dem Standard viel bessere Erfolge erzieltjava.text.MessageFormat .

Grundsätzlich müssen Sie lediglich die Standard-String-Ressource wie folgt verwenden:

<resources>
    <string name="item_shop">{0,choice,0#No items|1#One item|1&lt;{0} items}</string>
</resources>

Aus dem Code müssen Sie dann nur noch Folgendes tun:

String fmt = getResources().getText(R.string.item_shop).toString();
textView.setText(MessageFormat.format(fmt, amount));

Weitere Informationen zu den Formatzeichenfolgen finden Sie in den Javadocs für MessageFormat

Elias Mårtenson
quelle
7
Schöne Problemumgehung. Ich kann mir gerade vorstellen, was für ein Durcheinander die Leute, die meine Anwendungen übersetzen, in meine Dateien
stecken
1
Wie erstelle ich eine Formatzeichenfolge für "wenige" Zahlen (Zahlen, die mit 2,3,4 enden, aber nicht mit 12,13,14 enden)?
Vokilam
3
Wow, das ist hässlich. Eine solche Logik sollte in Code und nicht in Übersetzungen enthalten sein. Pluralformen sollen nur bei Sprachunterschieden für Zahlen helfen. Mit der Empfehlung für "wenige" haben Sie jetzt erfolgreich Logik in Übersetzungen und Übersetzungen in Logik verschoben.
DennisK
2
Es ist sicherlich keine gute Lösung. Fügen Sie einfach eine Zeichenfolge für no_items und eine if-Klausel hinzu. If (items.count == 0) {benutze den String} else {benutze den Plural} und DANN lassen die Übersetzer das Problem in der Datei strings.xml behandeln…
Martin Marconcini
2
@ MartínMarconcini Sie sind richtig ... über 3 Jahre später :-)
GreyBeardedGeek
45

Von http://developer.android.com/guide/topics/resources/string-resource.html#Plurals :

Beachten Sie, dass die Auswahl basierend auf der grammatikalischen Notwendigkeit getroffen wird. Eine Zeichenfolge für Null in Englisch wird ignoriert, auch wenn die Menge 0 ist, da 0 sich grammatikalisch nicht von 2 oder einer anderen Zahl außer 1 unterscheidet ("Null Bücher", "Ein Buch", "Zwei Bücher" usw.) auf). Lassen Sie sich auch nicht von der Tatsache irreführen, dass beispielsweise zwei Klänge nur für die Menge 2 gelten könnten: Eine Sprache kann erfordern, dass 2, 12, 102 (usw.) alle wie einander behandelt werden, aber unterschiedlich zu anderen Mengen. Verlassen Sie sich darauf, dass Ihr Übersetzer weiß, auf welchen Unterschieden seine Sprache tatsächlich besteht.

Zusammenfassend wird "Null" nur für bestimmte Sprachen verwendet (dasselbe gilt für "zwei", "wenige" usw.), da die anderen Sprachen keine spezielle Konjugation haben und daher das Feld "Null" als unnötig angesehen wird

ByteMe
quelle
4
"Eine Zeichenfolge für Null in Englisch wird ignoriert, auch wenn die Menge 0 ist, da 0 sich grammatikalisch nicht von 2 unterscheidet" ... wie wäre es mit "Ich habe keine Früchte" vs. "Ich habe einen Apfel und eine Orange"?
Jeffrey Blattman
4
Es gibt viele verschiedene Möglichkeiten, 0 gegen 2 zu formulieren. Die Idee hinter diesen Ressourcen ist jedoch, sie mit einer Zahl zu verwenden. Also so etwas wie: Ich habe 0 Äpfel. Ich habe 1 Apfel. Ich habe 2 Äpfel.
ByteMe
4
das ist sehr schade. Sie hätten nicht versuchen sollen, sprachspezifische Annahmen zu treffen. Jeder, den ich kenne, der Plural verwendet, ist dadurch verwirrt.
Jeffrey Blattman
2
@ miracle2k: Nachrichten werden nicht nach Kategorien übersetzt, sodass alle Kategorien oder Nachrichten, die Sie in einer Sprache haben, keine Auswirkungen auf eine andere Sprache haben. Wenn Sie also eine Null-Klassen-Nachricht in Englisch nur für die Null-Zählung haben und eine andere Sprache die Null-Klasse für 10.100-Zählungen verwendet, spielt dies keine Rolle, da Sie keine Null-Klassen-Nachricht übersetzen. Auf der anderen Seite: Wenn Sie eine separate Nachrichtenressource für die Anzahl 0 in Englisch erstellen, erstellen Sie ein Workflow-Problem für Übersetzer, da dieser Fall bereits durch die ursprüngliche Nachricht der Klasse "Null" in ihrer Sprache abgedeckt ist.
Basel Shishani
2
Es ist wahr, dass das Aktivieren der Kategorie "Null" in Englisch als Annehmlichkeitsfunktion durchgeführt werden könnte, aber es ist nicht "sauber" und fördert nur schlechtes Verhalten. Sie könnten auf die Idee kommen, Text einzufügen, der den Benutzer dazu ermutigt, Elemente in die Zeichenfolge "Null" einzufügen - und dann möglicherweise nicht übersetzbar. Genau genommen weist das Beispiel des OP ("Keine Elemente") dieses Problem bereits auf, da ein Übersetzer den 0-Fall möglicherweise auch mit Wörtern ausdrücken möchte. Es ist kein Workflow-Problem, wenn Sie "% s item" als singuläre Version von "% s items" und "No items" als sprachlich etwas ganz anderes betrachten.
miracle2k
13

Android verwendet das CLDR-Plural-System, und so funktioniert es einfach nicht (erwarten Sie also nicht, dass sich dies ändert).

Das System wird hier beschrieben:

http://cldr.unicode.org/index/cldr-spec/plural-rules

Kurz gesagt, es ist wichtig zu verstehen, dass "Eins" nicht die Zahl 1 bedeutet. Stattdessen sind diese Schlüsselwörter Kategorien, und die spezifischen Zahlen n, die zu jeder Kategorie gehören, werden durch Regeln in der CLDR-Datenbank definiert:

http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html

Während es keine Sprache zu geben scheint, die "Null" für etwas anderes als 0 verwendet, gibt es Sprachen, die "Eins" 0 zuweisen. Es gibt sicherlich viele Fälle, in denen "zwei" andere Zahlen als nur 2 enthält.

Wenn Android es Ihnen ermöglicht, das zu tun, was Sie beabsichtigt haben, können Ihre Anwendungen nicht ordnungsgemäß in eine beliebige Anzahl von Sprachen mit komplexeren Pluralregeln übersetzt werden.

miracle2k
quelle
5
Seien Sie vorsichtig, wenn Sie Antworten auf mehrere Fragen kopieren und einfügen. Diese werden von der Community in der Regel als "Spam" gekennzeichnet. Wenn Sie dies tun, bedeutet dies normalerweise, dass es sich bei den Fragen um Duplikate handelt. Kennzeichnen Sie sie stattdessen als solche: stackoverflow.com/questions/8473816
Kev
13

Hier ist eine Problemumgehung, mit der ich dieses Problem behebe, ohne zu MessageFormat zu wechseln.

Zuerst extrahiere ich die Zeichenfolge "Null" in eine eigene Zeichenfolgenressource.

<string name="x_items_zero">No items.</string>
<plurals name="x_items">
    <!-- NOTE: This "zero" value is never accessed but is kept here to show the intended usage of the "zero" string -->
    <item quantity="zero">@string/x_items_zero</item>
    <item quantity="one">One item.</item>
    <item quantity="other">%d items.</item>
</plurals>

Dann habe ich einige praktische Methoden in meinem eigenen ResourcesUtil

public static String getQuantityStringZero(Resources resources, int resId, int zeroResId, int quantity) {
    if (quantity == 0) {
        return resources.getString(zeroResId);
    } else {
        return resources.getQuantityString(resId, quantity, quantity);
    }
}

public static String getQuantityStringZero(Resources resources, int resId, int zeroResId, int quantity, Object... formatArgs) {
    if (quantity == 0) {
        return resources.getString(zeroResId);
    } else {
        return resources.getQuantityString(resId, quantity, formatArgs);
    }
}

Jetzt rufe ich jedes Mal, wenn ich eine bestimmte Zeichenfolge für die Menge Null verwenden möchte, Folgendes auf:

String pluralString = ResourcesUtil.getQuantityStringZero(
     getContext().getResources(),
     R.plural.x_items,
     R.string.x_items_zero,
     quantity
);

Ich wünschte, es gäbe etwas Besseres, aber dies erledigt zumindest die Arbeit, während die XML-Zeichenfolgenressource lesbar bleibt.

Justin Fiedler
quelle
Wird "<item Quantity =" Zero ">" damit eigentlich nie verwendet?
Android-Entwickler
4
Das korrekte '<item Quantity = "zero">' wird nicht verwendet. Ich habe es dort, weil ich denke, es hilft, die beabsichtigte Verwendung dieses Wertes für Null zu klären.
Justin Fiedler
Dachte mir. Es könnte Übersetzern helfen, zu verstehen, was los ist.
Android-Entwickler
2

Wenn Sie Datenbindung verwenden, können Sie dies wie folgt umgehen:

<TextView ... 
android:text="@{collection.size() > 0 ? @plurals/plural_str(collection.size(), collection.size()) : @string/zero_str}"/>
Kennzeichen
quelle
2

Ich habe eine Kotlin-Erweiterung geschrieben, um alle Szenarien zu behandeln, an die ich denken kann.

ich habe zeroResId als optional, so dass wir manchmal die Null behandeln wollen, indem wir "Keine Elemente" anstelle von "0 Elemente" anzeigen.

Englisch behandelt Null grammatikalisch als Plural.

Die Auswahl der zu verwendenden Zeichenfolge erfolgt ausschließlich anhand der grammatikalischen Notwendigkeit.

Im Englischen wird eine Zeichenfolge für Null ignoriert, auch wenn die Menge 0 ist, da 0 sich grammatikalisch nicht von 2 oder einer anderen Zahl außer 1 unterscheidet ("Null Bücher", "Ein Buch", "Zwei Bücher" usw.) auf).

https://developer.android.com/guide/topics/resources/string-resource.html#Plurals

fun Context.getQuantityStringZero(
    quantity: Int, 
    pluralResId: Int, 
    zeroResId: Int? = null
): String {
    return if (zeroResId != null && quantity == 0) {
        resources.getString(zeroResId)
    } else {
        resources.getQuantityString(pluralResId, quantity, quantity)
    }
}
Morgan Koh
quelle