UNPKG

i18n-ai-translate

Version:

AI-powered localization CLI, Node library, and GitHub Action. Translate i18next JSON, Gettext PO, Java .properties, and iOS .strings with ChatGPT, Claude, Gemini, or local Ollama models.

112 lines (107 loc) 3.33 kB
/** * Minimal table of Gettext Plural-Forms rules keyed by ISO-639-1 code. * The `categories` array is the CLDR plural-category name for each * index `i` in `msgstr[i]`. The `forms` string is the literal value * for the `Plural-Forms:` header on write. * * Covers the common languages a first-pass user is likely to target. * Unknown codes fall back to 2-form English-style via `DEFAULT_RULE`. * Expanding coverage is additive — it doesn't require touching the * adapter logic. * * Source: GNU gettext manual & Mozilla Localization plural rules. */ export type PluralRule = { /** Number of msgstr slots for a plural entry in this language. */ nplurals: number; /** CLDR category name at each msgstr index. */ categories: readonly PluralCategory[]; /** Value to write into the `Plural-Forms:` header. */ forms: string; }; export type PluralCategory = | "zero" | "one" | "two" | "few" | "many" | "other"; export const DEFAULT_RULE: PluralRule = { categories: ["one", "other"], forms: "nplurals=2; plural=(n != 1);", nplurals: 2, }; export const PLURAL_RULES: Record<string, PluralRule> = { ar: { categories: ["zero", "one", "two", "few", "many", "other"], forms: "nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5);", nplurals: 6, }, cs: { categories: ["one", "few", "other"], forms: "nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2);", nplurals: 3, }, de: DEFAULT_RULE, en: DEFAULT_RULE, es: DEFAULT_RULE, fr: { categories: ["one", "other"], forms: "nplurals=2; plural=(n > 1);", nplurals: 2, }, it: DEFAULT_RULE, ja: { categories: ["other"], forms: "nplurals=1; plural=0;", nplurals: 1, }, ko: { categories: ["other"], forms: "nplurals=1; plural=0;", nplurals: 1, }, nl: DEFAULT_RULE, pl: { categories: ["one", "few", "many"], forms: "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);", nplurals: 3, }, pt: { categories: ["one", "other"], forms: "nplurals=2; plural=(n != 1);", nplurals: 2, }, ru: { categories: ["one", "few", "many"], forms: "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);", nplurals: 3, }, tr: { categories: ["one", "other"], forms: "nplurals=2; plural=(n > 1);", nplurals: 2, }, uk: { categories: ["one", "few", "many"], forms: "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);", nplurals: 3, }, vi: { categories: ["other"], forms: "nplurals=1; plural=0;", nplurals: 1, }, zh: { categories: ["other"], forms: "nplurals=1; plural=0;", nplurals: 1, }, }; /** * @param languageCode - ISO-639-1 code (case-insensitive) * @returns the plural rule for the language, or `DEFAULT_RULE` */ export function getPluralRule(languageCode: string): PluralRule { return PLURAL_RULES[languageCode.toLowerCase()] ?? DEFAULT_RULE; }