Open gustawdaniel opened 4 years ago
Jak ktoś w przyszłości będzie potrzebował to załączam fragment kodu
let defaultChoiceIndex;
export function setDefaultChoiceIndexGet(fn) {
defaultChoiceIndex = fn
}
/**
* @param choice {number} a choice index given by the input to
* $tc: `$tc('path.to.rule', choiceIndex)`
* @param choicesLength {number} an overall amount of available choices
* @returns number - a final choice index to select plural word by
**/
export function getChoiceIndex(choice, choicesLength) {
if (defaultChoiceIndex === undefined) {
return choice
}
// this === VueI18n instance, so the locale property also exists here
if (this.locale !== "pl") {
return defaultChoiceIndex.apply(this, [choice, choicesLength])
}
if (1 === choice) {
return 0 // "komentarz"
}
if (choice % 10 >= 2 && choice % 10 <= 4 && (choice % 100 < 10 || choice % 100 >= 20)) {
return 1 // eg. "komentarze"
}
return 2 // eg. "komentarzy"
}
Jeszcze raz dzięki za kluczowy warunek logiczny :)
Niestety warunek choice % 100 < 10 || choice % 100 >= 20
jest niepoprawny zgodnie z https://unicode-org.github.io/cldr-staging/charts/37/supplemental/language_plural_rules.html#pl
Modulo 100 musi być różne niż 12, 13 i 14.
A więc:
if ([0, 1].includes(choice)) return choice;
const mod10: number = choice % 10;
const mod100: number = choice % 100;
if ([2, 3, 4].includes(mod10) && ![12, 13, 14].includes(mod100)) return 2;
return 3;
^ wersja pod Vue z 4 opcjami:
"people": "Nikogo tu nie ma | Tylko {n} osoba | {n} osoby | {n} osób"
{{ $tc('people', peopleCount) }}
To i tak tylko dla liczb całkowitych, na wymierne powinien być sprawdzany jeszcze dodatkowy warunek.
@skix123 czy możesz podać przykład, w którym kod z tej paczki zawodzi? https://github.com/mmiszy/polish-plurals/blob/5d2dc0cdea93e68e0a320a0201f0acb7a53206d0/index.mjs#L5
@skix123 przeprowadziłem następujący test:
function polishPlurals1(singularNominativ, pluralNominativ, pluralGenitive, value) {
value = Math.abs(value);
if (value === 1) {
return singularNominativ;
} else if (value % 10 >= 2 && value % 10 <= 4 && (value % 100 < 10 || value % 100 >= 20)) {
return pluralNominativ;
} else {
return pluralGenitive;
}
}
function polishPlurals2(singularNominativ, pluralNominativ, pluralGenitive, value) {
value = Math.abs(value);
const mod10 = value % 10;
const mod100 = value % 100;
if (value === 1) {
return singularNominativ;
} else if ([2,3,4].includes(mod10) && ![12,13,14].includes(mod100)) {
return pluralNominativ;
} else {
return pluralGenitive;
}
}
polishPlurals1
to oryginalna implementacja, a polishPlurals2
to ta sugerowana przez Ciebie. Okazuje się, że obie zwracają dokładnie to samo dla dowolnych liczb :)
for (let i = 0; i < 1000000; ++i) {
console.assert(
polishPlurals1("komentarz", "komentarze", "komentarzy", i)
===
polishPlurals2("komentarz", "komentarze", "komentarzy", i)
)
}
// brak błędów
Ciekawe, zatem sory za wprowadzenie w błąd
Właśnie sprawdzam jak to można wykorzystać w integracji z Vue
https://phrase.com/blog/posts/ultimate-guide-to-vue-localization-with-vue-i18n/#Custom_Pluralization