Jeśli mój plik strings.xml zawiera następujący zasób liczby mnogiej:
<plurals name="item_shop">
<item quantity="zero">No item</item>
<item quantity="one">One item</item>
<item quantity="other">%d items</item>
</plurals>
Wynik pokazuję użytkownikowi za pomocą:
textView.setText(getQuantityString(R.plurals.item_shop, quantity, quantity));
Działa dobrze z 1 i wyższymi, ale jeśli ilość wynosi 0, widzę „0 pozycji”. Czy wartość „zero” jest obsługiwana tylko w języku arabskim, jak wskazuje dokumentacja? A może coś mi brakuje?
Odpowiedzi:
Metoda internacjonalizacji zasobów Androida jest dość ograniczona. Używając standardu odniosłem znacznie większy sukces
java.text.MessageFormat
.Zasadniczo wszystko, co musisz zrobić, to użyć standardowego zasobu ciągu w następujący sposób:
<resources> <string name="item_shop">{0,choice,0#No items|1#One item|1<{0} items}</string> </resources>
Następnie z kodu wszystko, co musisz zrobić, to:
String fmt = getResources().getText(R.string.item_shop).toString(); textView.setText(MessageFormat.format(fmt, amount));
Możesz przeczytać więcej o ciągach formatujących w javadocs dla MessageFormat
źródło
Od http://developer.android.com/guide/topics/resources/string-resource.html#Plurals :
Zwróć uwagę, że wybór jest dokonywany na podstawie konieczności gramatycznej. Ciąg znaków zerowy w języku angielskim zostanie zignorowany, nawet jeśli ilość wynosi 0, ponieważ 0 nie różni się gramatycznie od 2 ani żadnej innej liczby poza 1 („zero książek”, „jedna książka”, „dwie książki” itd. na). Nie dajcie się też zwieść faktowi, że, powiedzmy, dwa dźwięki, które mogą mieć zastosowanie tylko do wielkości 2: język może wymagać, aby 2, 12, 102 (i tak dalej) były traktowane tak samo, ale inaczej wielkie ilości. Polegaj na swoim tłumaczu, aby wiedział, na jakie rozróżnienia kładzie nacisk jego język.
Podsumowując, „zero” jest używane tylko w przypadku niektórych języków (to samo dotyczy „dwóch”, „kilku” itp.), Ponieważ inne języki nie mają specjalnej koniugacji i dlatego pole „zero” jest uważane za niepotrzebne
źródło
Oto obejście, którego używam, aby rozwiązać ten problem bez przełączania się na MessageFormat.
Najpierw wyodrębniam ciąg „zero” do własnego zasobu ciągu.
<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>
Następnie mam kilka wygodnych metod w moim własnym 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); } }
Teraz za każdym razem, gdy chcę użyć określonego ciągu dla ilości zerowej, wzywam:
String pluralString = ResourcesUtil.getQuantityStringZero( getContext().getResources(), R.plural.x_items, R.string.x_items_zero, quantity );
Chciałbym, żeby było coś lepszego, ale przynajmniej załatwia to zadanie, zachowując czytelność XML zasobu ciągu.
źródło
Android używa systemu liczby mnogiej CLDR, a to po prostu nie działa (więc nie spodziewaj się, że to się zmieni).
System jest opisany tutaj:
http://cldr.unicode.org/index/cldr-spec/plural-rules
Krótko mówiąc, ważne jest, aby zrozumieć, że „jeden” nie oznacza liczby 1. Zamiast tego te słowa kluczowe są kategoriami, a konkretne liczby n, które należą do każdej kategorii, są zdefiniowane przez reguły w bazie danych CLDR:
http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
Chociaż wydaje się, że nie ma języka, który używa „zera” dla czegokolwiek innego niż 0, są języki, które przypisują 0 do „jedynki”. Z pewnością jest wiele przypadków, w których „dwa” zawiera inne liczby niż tylko 2.
Jeśli Android umożliwi Ci robienie tego, co zamierzałeś, Twoje aplikacje nie mogą zostać poprawnie przetłumaczone na dowolną liczbę języków z bardziej złożonymi regułami liczby mnogiej.
źródło
Napisałem rozszerzenie Kotlin, aby obsłużyć wszystkie scenariusze, o których mogę pomyśleć.
mam
zeroResId
jako opcjonalne, więc czasami chcemy obsłużyć zero, wyświetlając „Brak pozycji” zamiast „0 pozycji”.Angielski traktuje zero gramatycznie jako liczbę mnogą.
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) } }
źródło
Jeśli używasz powiązania danych, możesz obejść ten problem za pomocą czegoś takiego:
<TextView ... android:text="@{collection.size() > 0 ? @plurals/plural_str(collection.size(), collection.size()) : @string/zero_str}"/>
źródło