Russian, and the first real use of the plural machinery
781 of 796 strings. Generated by AI, unreviewed, marked Beta.
This is the catalogue plural() was designed for. Russian needs three forms
where English has two, and the choice is not a question about the number 1:
1 is "one", 2-4 are "few", 5-20 are "many", 11-14 are "many" despite ending in
1-4, and 21 is "one" again. Intl.PluralRules knows all of that; a two-form
assumption would have shipped "5 письмо" and read as machine output however
good the vocabulary was.
Tested against the shipped catalogue rather than a fixture -- 1, 2, 3, 5, 11,
21, 22, 25 and 0 -- plus a check that every counted string carries all four
categories, because a missing "few" falls back to "other" silently and is
grammatical often enough to go unnoticed.
"Выбрано: {n}" for the selection count rather than an agreeing form: the
impersonal construction sidesteps agreement entirely and is what Russian
interfaces actually do there.
Register is "вы", lowercase. Capitalised «Вы» is correspondence style and
reads as a letter rather than as software, so it would be a small constant
wrongness on every screen. Most of the interface avoids the question anyway,
because Russian UI convention is the infinitive for actions.
«Письмо» rather than «сообщение» for a mail message, which is what Russian
mail clients call one; «сообщение» reads as a chat message. «Ярлык» for label,
Gmail's word in Russian -- a fifth answer to the same rule about using what the
reader will meet elsewhere.
A stray CJK character got typed into one Russian sentence during drafting and
was caught by sweeping the file for anything outside the expected scripts. Not
a mistake a spellcheck would find, and not one a reader would forgive.
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import { describe, expect, it, afterEach } from "vitest";
|
||||
import { plural, setCatalog } from "@/lib/i18n";
|
||||
import { catalog as ru } from "@/locales/ru";
|
||||
|
||||
/**
|
||||
* Russian is the first shipped catalogue that needs `few` and `many`, so this
|
||||
* checks the real entries rather than a fixture. English would have rendered
|
||||
* "5 письмо" for all of these, which is the kind of wrong that makes a
|
||||
* translation read as machine output however good the vocabulary is.
|
||||
*/
|
||||
const FORMS = { one: "{n} message", other: "{n} messages" };
|
||||
afterEach(() => setCatalog("en", { strings: {}, plurals: {} }));
|
||||
|
||||
describe("Russian plurals", () => {
|
||||
it("picks one, few and many by the language's own rule", () => {
|
||||
setCatalog("ru", ru);
|
||||
expect(plural(1, FORMS)).toBe("1 письмо"); // one
|
||||
expect(plural(2, FORMS)).toBe("2 письма"); // few
|
||||
expect(plural(3, FORMS)).toBe("3 письма");
|
||||
expect(plural(5, FORMS)).toBe("5 писем"); // many
|
||||
expect(plural(11, FORMS)).toBe("11 писем"); // 11-14 are many, not few
|
||||
expect(plural(21, FORMS)).toBe("21 письмо"); // 21 is one again
|
||||
expect(plural(22, FORMS)).toBe("22 письма");
|
||||
expect(plural(25, FORMS)).toBe("25 писем");
|
||||
expect(plural(0, FORMS)).toBe("0 писем");
|
||||
});
|
||||
|
||||
it("carries every form for each counted string it ships", () => {
|
||||
// A catalogue missing `few` silently falls back to `other`, which is
|
||||
// grammatical often enough to go unnoticed and wrong the rest of the time.
|
||||
for (const [key, forms] of Object.entries(ru.plurals)) {
|
||||
for (const cat of ["one", "few", "many", "other"] as const) {
|
||||
expect(forms[cat], `${key} is missing "${cat}"`).toBeTruthy();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user