Verwendung von Android-Mengenstrings (Plural)

Lesezeit: 9 Minuten

Benutzer-Avatar
Andy

Ich versuche, die zu verwenden getQuantityString -Methode in den abzurufenden Ressourcen Menge Zeichenfolgen (Plural) basierend auf den Richtlinien für Android-Entwickler Mengenzeichenfolge (Plural)

Der Fehler, den ich bekomme, ist

Fehler: (604) Mehrere Ersetzungen in nicht-positionalem Format angegeben; Wollten Sie das Attribut formatted=”false” hinzufügen?
Fehler: (604) Tag gefunden, wo erwartet

wenn ich Plurale wie unten einrichte

<plurals name="productCount">
    <item quantity="one" formatted="true">%1$d of %2$d product</item>
    <item quantity="other" formatted="true">%1$d of %2$d products</item>
</plurals>

Und versuchen Sie es wie folgt zu lesen productIndexCountText.setText(getResources().getQuantityString(R.plurals.productCount, position, size));

Eine Problemumgehung besteht darin, die Zeichenfolge aufzuteilen, um den Plural nur für den letzten Teil der Zeichenfolge zu verwenden, und die beiden Teile zu verketten. Aber das versuche ich möglichst zu vermeiden.

Benutzer-Avatar
LWCris

Sie müssen das Attribut “formatiert” für keines dieser Elemente festlegen. Bei der Verwendung von Mengenstrings gibt es nur drei Möglichkeiten:

  1. Die Ressourcenzeichenfolge ist Klartext und enthält keine Parameter
  2. die Ressourcenzeichenfolge enthält nur einen Parameter (höchstwahrscheinlich die Menge); verwenden %d oder welches Format Sie benötigen
  3. die Ressourcenzeichenfolge enthält mehrere Parameter; auf alle Parameter muss beispielsweise explizit über ihre Position zugegriffen werden %1$d

Wie für die getQuantityString -Methode gibt es zwei Überladungen: eine mit nur der Ressourcen-ID und der Menge und eine mit einer zusätzlichen Object... formatArgs Parameter.

Für Fall 1. können Sie die verwenden getQuantityString(@PluralsRes int id, int quantity) Methode.

Für alle anderen Fälle, dh wenn Sie haben irgendein Parameter benötigen Sie die getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs) Überlast. Notiz: alle Parameter müssen im Parameterarray vorhanden sein. Das heißt, wenn der Ressourcen-String die Menge anzeigt, wird die Mengenvariable übergeben zweimal zur Funktion.

Das liegt daran, dass die quantity Der Parameter der Methode selbst wird beim Auflösen der Positionsparameter Ihrer Ressourcenzeichenfolge nicht berücksichtigt.

Wenn dies also Ihre Ressourcen sind,

<resources>
    <plurals name="test0">
        <item quantity="one">Test ok</item>
        <item quantity="other">Tests ok</item>
    </plurals>
    <plurals name="test1">
        <item quantity="one">%d test ok</item>
        <item quantity="other">%d tests ok</item>
    </plurals>
    <plurals name="test2">
        <item quantity="one">%2$s: %1$d test ok</item>
        <item quantity="other">%2$s: %1$d tests ok</item>
    </plurals>
    <plurals name="test3">
        <item quantity="one">%3$s: %1$d test out of %2$d ok</item>
        <item quantity="other">%3$s: %1$d tests out of %2$d ok</item>
    </plurals>
</resources>

dann die entsprechenden anrufe getQuantityString sind:

int success = 1;
int total = 10;
String group = "Group name";

getResources().getQuantityString(R.plurals.test0, success)
// Test ok
getResources().getQuantityString(R.plurals.test1, success, success)
// 1 test ok
getResources().getQuantityString(R.plurals.test2, success, success, group)
// Group name: 1 test ok
getResources().getQuantityString(R.plurals.test3, success, success, total, group)
// Group name: 1 test out of 10 ok

success = 5;
getResources().getQuantityString(R.plurals.test0, success)
// Tests ok
getResources().getQuantityString(R.plurals.test1, success, success)
// 5 tests ok
getResources().getQuantityString(R.plurals.test2, success, success, group)
// Group name: 5 tests ok
getResources().getQuantityString(R.plurals.test3, success, success, total, group)
// Group name: 5 tests out of 10 ok

Mengenklassen: Verständnis der quantity Parameter

Wie oben erwähnt, ist der Schlüssel zu verstehen, dass die quantity Parameter von getQuantityString wird nicht verwendet, um die Platzhalter wie zu ersetzen %d oder %1$d. Stattdessen wird es verwendet, um das Angemessene zu bestimmen item von dem plurals selbst, in Kombination mit dem Gebietsschema der Ressourcendatei.

Beachten Sie jedoch, dass dies eine weniger direkte Zuordnung ist als der Name des Attributs und seine möglichen Werte (zero, one, two, few, many, other) könnte vorschlagen. Zum Beispiel die Bereitstellung einer zusätzlichen <item quantity="zero"> wird nicht funktionieren (zumindest nicht in Englisch), auch wenn der Wert der quantity Parameter ist 0.

Der Grund dafür ist der Weg plurals Arbeit in Android ist durch das Konzept von Mengenklassen. Eine Mengenklasse ist eine Menge von Mengenwerten, die in einer bestimmten Sprache dieselben grammatikalischen Regeln haben. Dies bedeutet entscheidend, dass

  • welche Mengenklassen verwendet werden und
  • welche numerischen Werte ihnen zugeordnet sind

ist abhängig vom Gebietsschema, für das die jeweilige Ressourcendatei bestimmt ist.

Es ist wichtig zu verstehen, dass beide Fragen nur durch entschieden werden grammatikalische Notwendigkeit. Hier sind einige Beispiele:

  • Nur auf Chinesisch oder Koreanisch other verwendet, da sich Sätze in diesen Sprachen aufgrund der gegebenen Menge grammatikalisch nicht unterscheiden.
  • Auf Englisch gibt es zwei Klassen: one für den Literalwert 1 und other für alle anderen Werte einschließlich 0.
  • Auf Irisch wird 1 abgebildet one2 zugeordnet ist two3-6 ist few7-10 ist many0 und 11+ ist other.
  • Auf Slowenisch der Wert 1 und alle Werte Ende in 01 zugeordnet sind one (1, 101, 3001, …). 2 und Werte, die auf 02 enden, werden zugeordnet two (2, 302, 1002, …). 3, 4 und Werte, die auf 03 oder 04 enden, werden zugeordnet few (3, 4, 6004, …). Alles andere ist other (0, 11, 48, 312, …).
  • Auf Polnisch werden 5-19 und Werte, die auf 05-19 enden, zugeordnet many (5, 12, 216, 4711, …). Werte, die auf 2, 3 oder 4 enden, einschließlich 2-4 selbst, werden zugeordnet few (3, 42, 103, 12035374, …). Dies berücksichtigt jedoch, dass 12, 13 und 14 Ausnahmen von dieser Regel sind, weil sie zugeordnet sind many. (Nebenbemerkung: ja, grammatikalisch gesehen ist 5 viele während 12035374 ist wenig.)
  • Armenisch ist wie Englisch, mit der Ausnahme, dass auch der Wert 0 abgebildet wird one, denn so funktioniert ihre Grammatik. An diesem Beispiel können Sie erkennen, dass die Mengenklasse one stellt nicht einmal notwendigerweise nur einsige Zahlen dar.

Wie Sie sehen, kann es ziemlich kompliziert werden, die richtige Mengenklasse zu ermitteln. Deshalb getQuantityString tut das schon für dich, basierend auf der quantity -Parameter und das Gebietsschema der Ressourcendatei. Die Regeln, nach denen Android (meistens) spielt, sind in der definiert Sprachpluralregeln des Unicode Common Locale Data Repository. Daher stammen auch die Namen der Mengenklassen.

All dies bedeutet, dass der Satz von Mengenklassen, der zum Übersetzen einer beliebigen Mengenzeichenfolge benötigt wird, von Sprache zu Sprache unterschiedlich sein kann (Chinesisch braucht nur otherEnglisch braucht one und otherIrisch braucht alle aber zero, etc.). Innerhalb einer Sprache jedoch alle plurals sollten jeweils die gleiche Anzahl von Artikeln haben, die alle für diese bestimmte Sprache erforderlichen Mengenklassen abdecken.

Fazit

Ein Anruf bei getQuantityString kann so verstanden werden:

int success = 5;
int total = 10;
String group = "Group name";

getResources().getQuantityString(R.plurals.test3, success, success, total, group)
//                               \_____________/  \_____/  \___________________/
//                                      |            |               |
//         id: used to get the plurals resource      |               |
//   quantity: used to determine the appropriate quantity class      |
// formatArgs: used to positionally replace the placeholders %1, %2 and %3

Das quantity Der Wert des Parameters „5“ bedeutet „Verwendet“. item wird derjenige mit der Mengenklasse sein other aus chinesischen, koreanischen, englischen, slowenischen und armenischen Ressourcendateien, few für Irisch und many für Polnisch.


Es gibt zwei Sonderfälle, die ich auch kurz erwähnen möchte:

Nicht ganzzahlige Größen

Grundsätzlich hängt die gewählte Klasse wieder von sprachspezifischen Regeln ab. Es ist weder allgemeingültig, wie eine Klasse ausgewählt wird, noch garantiert, dass jede Klasse, die erforderlich ist, um alle Regeln für ganze Zahlen abzudecken, auch für alle Nicht-Ganzzahlen verwendet wird. Hier sind ein paar Beispiele:

  • Für Englisch wird jeder Wert mit Dezimalstellen immer zugeordnet other.
  • Für Slowenisch wird jeder Wert mit Dezimalstellen immer zugeordnet few.
  • Für Irisch hängt die Wahl vom ganzzahligen Teil ab.
  • Für Polnisch werden im Gegensatz zu den komplexen Regeln für ganze Zahlen immer Nicht-Ganzzahlen abgebildet other wie auf Englisch.

Notiz: So ist es sollte laut sein Sprachpluralregeln. Leider hat Android keine leicht verfügbare Methode für float oder double im Augenblick.

Mehrere Mengen in einer Zeichenfolge

Wenn Ihr Anzeigetext mehrere Mengen hat, z %d match(es) found in %d file(s).teilen Sie es auf drei getrennte Ressourcen:

  1. %d match(es) (plurals Artikel)
  2. %d file(s) (plurals Artikel)
  3. %1$s found in %2$s. (gewöhnlich parametrisiert strings Artikel)

Sie können dann die entsprechenden Anrufe tätigen getQuantityString für 1 und 2, und dann noch eins zu getString für die dritte, mit den ersten beiden leicht lokalisierten Saiten als formatArgs.

Der Grund dafür ist, dass Übersetzer die Parameterreihenfolge in der dritten Ressource ändern können, falls die Sprache dies erfordert. ZB wenn die einzige gültige Syntax in einer hypothetischen Sprache war In %d file(s) it found %d match(es).könnte der Übersetzer den Plural wie gewohnt übersetzen und dann die dritte Ressource als übersetzen In %2$s it found %1$s. um die vertauschte Bestellung zu berücksichtigen.

  • Was ist, wenn es zwei oder mehr Wörter gibt, die im Plural geändert werden müssen, z. B. “%1$d Ergebnis(se) in %2$d Kapitel(n) gefunden”. Ich möchte, dass sowohl Ergebnisse als auch Kapitel in der Lage sind, sich selbst zu ändern. Wie kann ich das erreichen?

    – Fehler passieren

    20. Februar 2019 um 4:16 Uhr

  • Was ist, wenn die Menge eine Float-ähnliche Distanz ist? Ich möchte 1 km oder 1,5 km anzeigen

    – Aman Verma

    21. Februar 2019 um 9:25 Uhr

  • @BugsHappen Sie müssten die Übersetzung dann in mehrere Teile aufteilen. Best Practice ist es dann, es nicht in zwei, sondern in drei Teile aufzuteilen: %d result(s), %d chapter(s)und Found %1$s in %2$s. Dies ermöglicht es einer hypothetischen Sprache, die Wortstellung im Satz bei Bedarf zu ändern (z. B. wenn die Syntax einer Sprache war In %d chapter(s), %d result(s) were found.), was unmöglich wäre, wenn Sie den Satz einfach in zwei Teile aufteilen und im Code verketten würden.

    – LWCris

    21. Februar 2019 um 12:31 Uhr


  • Ja, genau das habe ich getan. Ich habe gefragt, weil ich dachte, dass es vielleicht einen besseren Weg gibt, es zu tun. Vielen Dank.

    – Fehler passieren

    21. Februar 2019 um 13:19 Uhr

  • @Sniper Ich denke tatsächlich immer noch von Zeit zu Zeit darüber nach. TBH, das Schwierigste für mich ist, zu entscheiden, wie ich es tun würde wollen der Plural sich benehmen. Im Deutschen (meiner Muttersprache) ist der Plural von “km” immer noch “km”, das hilft also nicht weiter. Und auf Englisch, ich weiß nicht, würden Sie nicht “one point five miles” sagen, sondern “one and a half mile” für “1.5 mi”? Oder mit anderen Worten, haben Einheiten als solche überhaupt einen Plural?

    – LWCris

    29. November 2019 um 13:32 Uhr


1246850cookie-checkVerwendung von Android-Mengenstrings (Plural)

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy