define(["require", "exports", "tslib", "../StringUtil"], function (require, exports, tslib_1, StringUtil) {
"use strict";
StringUtil = tslib_1.__importStar(StringUtil);
- const PLURAL_FEW = "few";
- const PLURAL_MANY = "many";
- const PLURAL_ONE = "one";
- const PLURAL_OTHER = "other";
- const PLURAL_TWO = "two";
- const PLURAL_ZERO = "zero";
- const Plural = {
- /**
- * Returns the plural category for the given value.
- */
- getCategory(value, languageCode) {
- if (!languageCode) {
- languageCode = document.documentElement.lang;
- }
- // Fallback: handle unknown languages as English
- if (typeof Plural[languageCode] !== "function") {
- languageCode = "en";
- }
- const category = Plural[languageCode](value);
- if (category) {
- return category;
- }
- return PLURAL_OTHER;
- },
- /**
- * Returns the value for a `plural` element used in the template.
- *
- * @see wcf\system\template\plugin\PluralFunctionTemplatePlugin::execute()
- */
- getCategoryFromTemplateParameters(parameters) {
- if (!parameters["value"]) {
- throw new Error("Missing parameter value");
- }
- if (!parameters["other"]) {
- throw new Error("Missing parameter other");
- }
- let value = parameters["value"];
- if (Array.isArray(value)) {
- value = value.length;
- }
- // handle numeric attributes
- const numericAttribute = Object.keys(parameters).find((key) => {
- return key.toString() === (~~key).toString() && key == value;
- });
- if (numericAttribute) {
- return numericAttribute;
- }
- let category = Plural.getCategory(value);
- if (!parameters[category]) {
- category = PLURAL_OTHER;
- }
- const string = parameters[category];
- if (string.indexOf("#") !== -1) {
- return string.replace("#", StringUtil.formatNumeric(value));
- }
- return string;
- },
- /**
- * `f` is the fractional number as a whole number (1.234 yields 234)
- */
- getF(n) {
- const tmp = n.toString();
- const pos = tmp.indexOf(".");
- if (pos === -1) {
- return 0;
- }
- return parseInt(tmp.substr(pos + 1), 10);
- },
- /**
- * `v` represents the number of digits of the fractional part (1.234 yields 3)
- */
- getV(n) {
- return n.toString().replace(/^[^.]*\.?/, "").length;
- },
+ const Languages = {
// Afrikaans
af(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Amharic
am(n) {
const i = Math.floor(Math.abs(n));
if (n == 1 || i === 0) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Arabic
ar(n) {
if (n == 0) {
- return PLURAL_ZERO;
+ return "zero" /* Zero */;
}
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
if (n == 2) {
- return PLURAL_TWO;
+ return "two" /* Two */;
}
const mod100 = n % 100;
if (mod100 >= 3 && mod100 <= 10) {
- return PLURAL_FEW;
+ return "few" /* Few */;
}
if (mod100 >= 11 && mod100 <= 99) {
- return PLURAL_MANY;
+ return "many" /* Many */;
}
},
// Assamese
as(n) {
const i = Math.floor(Math.abs(n));
if (n == 1 || i === 0) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Azerbaijani
az(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Belarusian
const mod10 = n % 10;
const mod100 = n % 100;
if (mod10 == 1 && mod100 != 11) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
if (mod10 >= 2 && mod10 <= 4 && !(mod100 >= 12 && mod100 <= 14)) {
- return PLURAL_FEW;
+ return "few" /* Few */;
}
if (mod10 == 0 || (mod10 >= 5 && mod10 <= 9) || (mod100 >= 11 && mod100 <= 14)) {
- return PLURAL_MANY;
+ return "many" /* Many */;
}
},
// Bulgarian
bg(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Bengali
bn(n) {
const i = Math.floor(Math.abs(n));
if (n == 1 || i === 0) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Tibetan
const fMod10 = f % 10;
const fMod100 = f % 100;
if ((v == 0 && mod10 == 1 && mod100 != 11) || (fMod10 == 1 && fMod100 != 11)) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
if ((v == 0 && mod10 >= 2 && mod10 <= 4 && mod100 >= 12 && mod100 <= 14) ||
(fMod10 >= 2 && fMod10 <= 4 && fMod100 >= 12 && fMod100 <= 14)) {
- return PLURAL_FEW;
+ return "few" /* Few */;
}
},
// Czech
cs(n) {
const v = Plural.getV(n);
if (n == 1 && v === 0) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
if (n >= 2 && n <= 4 && v === 0) {
- return PLURAL_FEW;
+ return "few" /* Few */;
}
if (v === 0) {
- return PLURAL_MANY;
+ return "many" /* Many */;
}
},
// Welsh
cy(n) {
if (n == 0) {
- return PLURAL_ZERO;
+ return "zero" /* Zero */;
}
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
if (n == 2) {
- return PLURAL_TWO;
+ return "two" /* Two */;
}
if (n == 3) {
- return PLURAL_FEW;
+ return "few" /* Few */;
}
if (n == 6) {
- return PLURAL_MANY;
+ return "many" /* Many */;
}
},
// Danish
da(n) {
if (n > 0 && n < 2) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Greek
el(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Catalan (ca)
// Urdu (ur)
en(n) {
if (n == 1 && Plural.getV(n) === 0) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Spanish
es(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Basque
eu(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Persian
fa(n) {
if (n >= 0 && n <= 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// French
fr(n) {
if (n >= 0 && n < 2) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Irish
ga(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
if (n == 2) {
- return PLURAL_TWO;
+ return "two" /* Two */;
}
if (n == 3 || n == 4 || n == 5 || n == 6) {
- return PLURAL_FEW;
+ return "few" /* Few */;
}
if (n == 7 || n == 8 || n == 9 || n == 10) {
- return PLURAL_MANY;
+ return "many" /* Many */;
}
},
// Gujarati
gu(n) {
if (n >= 0 && n <= 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Hebrew
he(n) {
const v = Plural.getV(n);
if (n == 1 && v === 0) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
if (n == 2 && v === 0) {
- return PLURAL_TWO;
+ return "two" /* Two */;
}
if (n > 10 && v === 0 && n % 10 == 0) {
- return PLURAL_MANY;
+ return "many" /* Many */;
}
},
// Hindi
hi(n) {
if (n >= 0 && n <= 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Croatian
// Hungarian
hu(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Armenian
hy(n) {
if (n >= 0 && n < 2) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Indonesian
is(n) {
const f = Plural.getF(n);
if ((f === 0 && n % 10 === 1 && !(n % 100 === 11)) || !(f === 0)) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Japanese
// Georgian
ka(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Kazakh
kk(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Khmer
// Kannada
kn(n) {
if (n >= 0 && n <= 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Korean
// Kurdish
ku(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Kyrgyz
ky(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Luxembourgish
lb(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Lao
const mod10 = n % 10;
const mod100 = n % 100;
if (mod10 == 1 && !(mod100 >= 11 && mod100 <= 19)) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
if (mod10 >= 2 && mod10 <= 9 && !(mod100 >= 11 && mod100 <= 19)) {
- return PLURAL_FEW;
+ return "few" /* Few */;
}
if (Plural.getF(n) != 0) {
- return PLURAL_MANY;
+ return "many" /* Many */;
}
},
// Latvian
const fMod10 = f % 10;
const fMod100 = f % 100;
if (mod10 == 0 || (mod100 >= 11 && mod100 <= 19) || (v == 2 && fMod100 >= 11 && fMod100 <= 19)) {
- return PLURAL_ZERO;
+ return "zero" /* Zero */;
}
if ((mod10 == 1 && mod100 != 11) || (v == 2 && fMod10 == 1 && fMod100 != 11) || (v != 2 && fMod10 == 1)) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Macedonian
// Malayalam
ml(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Mongolian
mn(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Marathi
mr(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Malay
mt(n) {
const mod100 = n % 100;
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
if (n == 0 || (mod100 >= 2 && mod100 <= 10)) {
- return PLURAL_FEW;
+ return "few" /* Few */;
}
if (mod100 >= 11 && mod100 <= 19) {
- return PLURAL_MANY;
+ return "many" /* Many */;
}
},
// Burmese
// Norwegian
no(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Nepali
ne(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Odia
or(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Punjabi
pa(n) {
if (n == 1 || n == 0) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Polish
const mod10 = n % 10;
const mod100 = n % 100;
if (n == 1 && v == 0) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
if (v == 0 && mod10 >= 2 && mod10 <= 4 && !(mod100 >= 12 && mod100 <= 14)) {
- return PLURAL_FEW;
+ return "few" /* Few */;
}
if (v == 0 &&
((n != 1 && mod10 >= 0 && mod10 <= 1) || (mod10 >= 5 && mod10 <= 9) || (mod100 >= 12 && mod100 <= 14))) {
- return PLURAL_MANY;
+ return "many" /* Many */;
}
},
// Pashto
ps(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Portuguese
pt(n) {
if (n >= 0 && n < 2) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Romanian
const v = Plural.getV(n);
const mod100 = n % 100;
if (n == 1 && v === 0) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
if (v != 0 || n == 0 || (mod100 >= 2 && mod100 <= 19)) {
- return PLURAL_FEW;
+ return "few" /* Few */;
}
},
// Russian
const mod100 = n % 100;
if (Plural.getV(n) == 0) {
if (mod10 == 1 && mod100 != 11) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
if (mod10 >= 2 && mod10 <= 4 && !(mod100 >= 12 && mod100 <= 14)) {
- return PLURAL_FEW;
+ return "few" /* Few */;
}
if (mod10 == 0 || (mod10 >= 5 && mod10 <= 9) || (mod100 >= 11 && mod100 <= 14)) {
- return PLURAL_MANY;
+ return "many" /* Many */;
}
}
},
// Sindhi
sd(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Sinhala
si(n) {
if (n == 0 || n == 1 || (Math.floor(n) == 0 && Plural.getF(n) == 1)) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Slovak
const v = Plural.getV(n);
const mod100 = n % 100;
if (v == 0 && mod100 == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
if (v == 0 && mod100 == 2) {
- return PLURAL_TWO;
+ return "two" /* Two */;
}
if ((v == 0 && (mod100 == 3 || mod100 == 4)) || v != 0) {
- return PLURAL_FEW;
+ return "few" /* Few */;
}
},
// Albanian
sq(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Serbian
// Tamil
ta(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Telugu
te(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Tajik
// Turkmen
tk(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Turkish
tr(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Uyghur
ug(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Ukrainian
// Uzbek
uz(n) {
if (n == 1) {
- return PLURAL_ONE;
+ return "one" /* One */;
}
},
// Vietnamese
return undefined;
},
};
+ const Plural = Object.assign({
+ /**
+ * Returns the plural category for the given value.
+ */
+ getCategory(value, languageCode) {
+ if (!languageCode) {
+ languageCode = document.documentElement.lang;
+ }
+ // Fallback: handle unknown languages as English
+ if (typeof Plural[languageCode] !== "function") {
+ languageCode = "en";
+ }
+ const category = Plural[languageCode](value);
+ if (category) {
+ return category;
+ }
+ return "other" /* Other */;
+ },
+ /**
+ * Returns the value for a `plural` element used in the template.
+ *
+ * @see wcf\system\template\plugin\PluralFunctionTemplatePlugin::execute()
+ */
+ getCategoryFromTemplateParameters(parameters) {
+ if (!parameters["value"]) {
+ throw new Error("Missing parameter value");
+ }
+ if (!parameters["other"]) {
+ throw new Error("Missing parameter other");
+ }
+ let value = parameters["value"];
+ if (Array.isArray(value)) {
+ value = value.length;
+ }
+ // handle numeric attributes
+ const numericAttribute = Object.keys(parameters).find((key) => {
+ return key.toString() === (~~key).toString() && key.toString() === value.toString();
+ });
+ if (numericAttribute) {
+ return numericAttribute;
+ }
+ let category = Plural.getCategory(value);
+ if (!parameters[category]) {
+ category = "other" /* Other */;
+ }
+ const string = parameters[category];
+ if (string.indexOf("#") !== -1) {
+ return string.replace("#", StringUtil.formatNumeric(value));
+ }
+ return string;
+ },
+ /**
+ * `f` is the fractional number as a whole number (1.234 yields 234)
+ */
+ getF(n) {
+ const tmp = n.toString();
+ const pos = tmp.indexOf(".");
+ if (pos === -1) {
+ return 0;
+ }
+ return parseInt(tmp.substr(pos + 1), 10);
+ },
+ /**
+ * `v` represents the number of digits of the fractional part (1.234 yields 3)
+ */
+ getV(n) {
+ return n.toString().replace(/^[^.]*\.?/, "").length;
+ } }, Languages);
return Plural;
});
import * as StringUtil from "../StringUtil";
-const PLURAL_FEW = "few";
-const PLURAL_MANY = "many";
-const PLURAL_ONE = "one";
-const PLURAL_OTHER = "other";
-const PLURAL_TWO = "two";
-const PLURAL_ZERO = "zero";
-
-const Plural = {
- /**
- * Returns the plural category for the given value.
- */
- getCategory(value: number, languageCode?: string): string {
- if (!languageCode) {
- languageCode = document.documentElement.lang;
- }
-
- // Fallback: handle unknown languages as English
- if (typeof Plural[languageCode] !== "function") {
- languageCode = "en";
- }
-
- const category = Plural[languageCode](value);
- if (category) {
- return category;
- }
-
- return PLURAL_OTHER;
- },
-
- /**
- * Returns the value for a `plural` element used in the template.
- *
- * @see wcf\system\template\plugin\PluralFunctionTemplatePlugin::execute()
- */
- getCategoryFromTemplateParameters(parameters: object): string {
- if (!parameters["value"]) {
- throw new Error("Missing parameter value");
- }
- if (!parameters["other"]) {
- throw new Error("Missing parameter other");
- }
-
- let value = parameters["value"];
- if (Array.isArray(value)) {
- value = value.length;
- }
-
- // handle numeric attributes
- const numericAttribute = Object.keys(parameters).find((key) => {
- return key.toString() === (~~key).toString() && key == value;
- });
-
- if (numericAttribute) {
- return numericAttribute;
- }
-
- let category = Plural.getCategory(value);
- if (!parameters[category]) {
- category = PLURAL_OTHER;
- }
-
- const string = parameters[category];
- if (string.indexOf("#") !== -1) {
- return string.replace("#", StringUtil.formatNumeric(value));
- }
-
- return string;
- },
-
- /**
- * `f` is the fractional number as a whole number (1.234 yields 234)
- */
- getF(n: number): number {
- const tmp = n.toString();
- const pos = tmp.indexOf(".");
- if (pos === -1) {
- return 0;
- }
-
- return parseInt(tmp.substr(pos + 1), 10);
- },
-
- /**
- * `v` represents the number of digits of the fractional part (1.234 yields 3)
- */
- getV(n: number): number {
- return n.toString().replace(/^[^.]*\.?/, "").length;
- },
-
+const enum Category {
+ Few = "few",
+ Many = "many",
+ One = "one",
+ Other = "other",
+ Two = "two",
+ Zero = "zero",
+}
+
+const Languages = {
// Afrikaans
- af(n: number): string | undefined {
+ af(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Amharic
- am(n: number): string | undefined {
+ am(n: number): Category | undefined {
const i = Math.floor(Math.abs(n));
if (n == 1 || i === 0) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Arabic
- ar(n: number): string | undefined {
+ ar(n: number): Category | undefined {
if (n == 0) {
- return PLURAL_ZERO;
+ return Category.Zero;
}
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
if (n == 2) {
- return PLURAL_TWO;
+ return Category.Two;
}
const mod100 = n % 100;
if (mod100 >= 3 && mod100 <= 10) {
- return PLURAL_FEW;
+ return Category.Few;
}
if (mod100 >= 11 && mod100 <= 99) {
- return PLURAL_MANY;
+ return Category.Many;
}
},
// Assamese
- as(n: number): string | undefined {
+ as(n: number): Category | undefined {
const i = Math.floor(Math.abs(n));
if (n == 1 || i === 0) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Azerbaijani
- az(n: number): string | undefined {
+ az(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Belarusian
- be(n: number): string | undefined {
+ be(n: number): Category | undefined {
const mod10 = n % 10;
const mod100 = n % 100;
if (mod10 == 1 && mod100 != 11) {
- return PLURAL_ONE;
+ return Category.One;
}
if (mod10 >= 2 && mod10 <= 4 && !(mod100 >= 12 && mod100 <= 14)) {
- return PLURAL_FEW;
+ return Category.Few;
}
if (mod10 == 0 || (mod10 >= 5 && mod10 <= 9) || (mod100 >= 11 && mod100 <= 14)) {
- return PLURAL_MANY;
+ return Category.Many;
}
},
// Bulgarian
- bg(n: number): string | undefined {
+ bg(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Bengali
- bn(n: number): string | undefined {
+ bn(n: number): Category | undefined {
const i = Math.floor(Math.abs(n));
if (n == 1 || i === 0) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Tibetan
- bo(_n: number): string | undefined {
+ bo(_n: number): Category | undefined {
return undefined;
},
// Bosnian
- bs(n: number): string | undefined {
+ bs(n: number): Category | undefined {
const v = Plural.getV(n);
const f = Plural.getF(n);
const mod10 = n % 10;
const fMod100 = f % 100;
if ((v == 0 && mod10 == 1 && mod100 != 11) || (fMod10 == 1 && fMod100 != 11)) {
- return PLURAL_ONE;
+ return Category.One;
}
if (
(v == 0 && mod10 >= 2 && mod10 <= 4 && mod100 >= 12 && mod100 <= 14) ||
(fMod10 >= 2 && fMod10 <= 4 && fMod100 >= 12 && fMod100 <= 14)
) {
- return PLURAL_FEW;
+ return Category.Few;
}
},
// Czech
- cs(n: number): string | undefined {
+ cs(n: number): Category | undefined {
const v = Plural.getV(n);
if (n == 1 && v === 0) {
- return PLURAL_ONE;
+ return Category.One;
}
if (n >= 2 && n <= 4 && v === 0) {
- return PLURAL_FEW;
+ return Category.Few;
}
if (v === 0) {
- return PLURAL_MANY;
+ return Category.Many;
}
},
// Welsh
- cy(n: number): string | undefined {
+ cy(n: number): Category | undefined {
if (n == 0) {
- return PLURAL_ZERO;
+ return Category.Zero;
}
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
if (n == 2) {
- return PLURAL_TWO;
+ return Category.Two;
}
if (n == 3) {
- return PLURAL_FEW;
+ return Category.Few;
}
if (n == 6) {
- return PLURAL_MANY;
+ return Category.Many;
}
},
// Danish
- da(n: number): string | undefined {
+ da(n: number): Category | undefined {
if (n > 0 && n < 2) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Greek
- el(n: number): string | undefined {
+ el(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Swedish (sv)
// Swahili (sw)
// Urdu (ur)
- en(n: number): string | undefined {
+ en(n: number): Category | undefined {
if (n == 1 && Plural.getV(n) === 0) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Spanish
- es(n: number): string | undefined {
+ es(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Basque
- eu(n: number): string | undefined {
+ eu(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Persian
- fa(n: number): string | undefined {
+ fa(n: number): Category | undefined {
if (n >= 0 && n <= 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// French
- fr(n: number): string | undefined {
+ fr(n: number): Category | undefined {
if (n >= 0 && n < 2) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Irish
- ga(n: number): string | undefined {
+ ga(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
if (n == 2) {
- return PLURAL_TWO;
+ return Category.Two;
}
if (n == 3 || n == 4 || n == 5 || n == 6) {
- return PLURAL_FEW;
+ return Category.Few;
}
if (n == 7 || n == 8 || n == 9 || n == 10) {
- return PLURAL_MANY;
+ return Category.Many;
}
},
// Gujarati
- gu(n: number): string | undefined {
+ gu(n: number): Category | undefined {
if (n >= 0 && n <= 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Hebrew
- he(n: number): string | undefined {
+ he(n: number): Category | undefined {
const v = Plural.getV(n);
if (n == 1 && v === 0) {
- return PLURAL_ONE;
+ return Category.One;
}
if (n == 2 && v === 0) {
- return PLURAL_TWO;
+ return Category.Two;
}
if (n > 10 && v === 0 && n % 10 == 0) {
- return PLURAL_MANY;
+ return Category.Many;
}
},
// Hindi
- hi(n: number): string | undefined {
+ hi(n: number): Category | undefined {
if (n >= 0 && n <= 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Croatian
- hr(n: number): string | undefined {
+ hr(n: number): Category | undefined {
// same as Bosnian
return Plural.bs(n);
},
// Hungarian
- hu(n: number): string | undefined {
+ hu(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Armenian
- hy(n: number): string | undefined {
+ hy(n: number): Category | undefined {
if (n >= 0 && n < 2) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Indonesian
- id(_n: number): string | undefined {
+ id(_n: number): Category | undefined {
return undefined;
},
// Icelandic
- is(n: number): string | undefined {
+ is(n: number): Category | undefined {
const f = Plural.getF(n);
if ((f === 0 && n % 10 === 1 && !(n % 100 === 11)) || !(f === 0)) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Japanese
- ja(_n: number): string | undefined {
+ ja(_n: number): Category | undefined {
return undefined;
},
// Javanese
- jv(_n: number): string | undefined {
+ jv(_n: number): Category | undefined {
return undefined;
},
// Georgian
- ka(n: number): string | undefined {
+ ka(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Kazakh
- kk(n: number): string | undefined {
+ kk(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Khmer
- km(_n: number): string | undefined {
+ km(_n: number): Category | undefined {
return undefined;
},
// Kannada
- kn(n: number): string | undefined {
+ kn(n: number): Category | undefined {
if (n >= 0 && n <= 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Korean
- ko(_n: number): string | undefined {
+ ko(_n: number): Category | undefined {
return undefined;
},
// Kurdish
- ku(n: number): string | undefined {
+ ku(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Kyrgyz
- ky(n: number): string | undefined {
+ ky(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Luxembourgish
- lb(n: number): string | undefined {
+ lb(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Lao
- lo(_n: number): string | undefined {
+ lo(_n: number): Category | undefined {
return undefined;
},
// Lithuanian
- lt(n: number): string | undefined {
+ lt(n: number): Category | undefined {
const mod10 = n % 10;
const mod100 = n % 100;
if (mod10 == 1 && !(mod100 >= 11 && mod100 <= 19)) {
- return PLURAL_ONE;
+ return Category.One;
}
if (mod10 >= 2 && mod10 <= 9 && !(mod100 >= 11 && mod100 <= 19)) {
- return PLURAL_FEW;
+ return Category.Few;
}
if (Plural.getF(n) != 0) {
- return PLURAL_MANY;
+ return Category.Many;
}
},
// Latvian
- lv(n: number): string | undefined {
+ lv(n: number): Category | undefined {
const mod10 = n % 10;
const mod100 = n % 100;
const v = Plural.getV(n);
const fMod100 = f % 100;
if (mod10 == 0 || (mod100 >= 11 && mod100 <= 19) || (v == 2 && fMod100 >= 11 && fMod100 <= 19)) {
- return PLURAL_ZERO;
+ return Category.Zero;
}
if ((mod10 == 1 && mod100 != 11) || (v == 2 && fMod10 == 1 && fMod100 != 11) || (v != 2 && fMod10 == 1)) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Macedonian
- mk(n: number): string | undefined {
+ mk(n: number): Category | undefined {
return Plural.bs(n);
},
// Malayalam
- ml(n: number): string | undefined {
+ ml(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Mongolian
- mn(n: number): string | undefined {
+ mn(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Marathi
- mr(n: number): string | undefined {
+ mr(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Malay
- ms(_n: number): string | undefined {
+ ms(_n: number): Category | undefined {
return undefined;
},
// Maltese
- mt(n: number): string | undefined {
+ mt(n: number): Category | undefined {
const mod100 = n % 100;
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
if (n == 0 || (mod100 >= 2 && mod100 <= 10)) {
- return PLURAL_FEW;
+ return Category.Few;
}
if (mod100 >= 11 && mod100 <= 19) {
- return PLURAL_MANY;
+ return Category.Many;
}
},
// Burmese
- my(_n: number): string | undefined {
+ my(_n: number): Category | undefined {
return undefined;
},
// Norwegian
- no(n: number): string | undefined {
+ no(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Nepali
- ne(n: number): string | undefined {
+ ne(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Odia
- or(n: number): string | undefined {
+ or(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Punjabi
- pa(n: number): string | undefined {
+ pa(n: number): Category | undefined {
if (n == 1 || n == 0) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Polish
- pl(n: number): string | undefined {
+ pl(n: number): Category | undefined {
const v = Plural.getV(n);
const mod10 = n % 10;
const mod100 = n % 100;
if (n == 1 && v == 0) {
- return PLURAL_ONE;
+ return Category.One;
}
if (v == 0 && mod10 >= 2 && mod10 <= 4 && !(mod100 >= 12 && mod100 <= 14)) {
- return PLURAL_FEW;
+ return Category.Few;
}
if (
v == 0 &&
((n != 1 && mod10 >= 0 && mod10 <= 1) || (mod10 >= 5 && mod10 <= 9) || (mod100 >= 12 && mod100 <= 14))
) {
- return PLURAL_MANY;
+ return Category.Many;
}
},
// Pashto
- ps(n: number): string | undefined {
+ ps(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Portuguese
- pt(n: number): string | undefined {
+ pt(n: number): Category | undefined {
if (n >= 0 && n < 2) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Romanian
- ro(n: number): string | undefined {
+ ro(n: number): Category | undefined {
const v = Plural.getV(n);
const mod100 = n % 100;
if (n == 1 && v === 0) {
- return PLURAL_ONE;
+ return Category.One;
}
if (v != 0 || n == 0 || (mod100 >= 2 && mod100 <= 19)) {
- return PLURAL_FEW;
+ return Category.Few;
}
},
// Russian
- ru(n: number): string | undefined {
+ ru(n: number): Category | undefined {
const mod10 = n % 10;
const mod100 = n % 100;
if (Plural.getV(n) == 0) {
if (mod10 == 1 && mod100 != 11) {
- return PLURAL_ONE;
+ return Category.One;
}
if (mod10 >= 2 && mod10 <= 4 && !(mod100 >= 12 && mod100 <= 14)) {
- return PLURAL_FEW;
+ return Category.Few;
}
if (mod10 == 0 || (mod10 >= 5 && mod10 <= 9) || (mod100 >= 11 && mod100 <= 14)) {
- return PLURAL_MANY;
+ return Category.Many;
}
}
},
// Sindhi
- sd(n: number): string | undefined {
+ sd(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Sinhala
- si(n: number): string | undefined {
+ si(n: number): Category | undefined {
if (n == 0 || n == 1 || (Math.floor(n) == 0 && Plural.getF(n) == 1)) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Slovak
- sk(n: number): string | undefined {
+ sk(n: number): Category | undefined {
// same as Czech
return Plural.cs(n);
},
// Slovenian
- sl(n: number): string | undefined {
+ sl(n: number): Category | undefined {
const v = Plural.getV(n);
const mod100 = n % 100;
if (v == 0 && mod100 == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
if (v == 0 && mod100 == 2) {
- return PLURAL_TWO;
+ return Category.Two;
}
if ((v == 0 && (mod100 == 3 || mod100 == 4)) || v != 0) {
- return PLURAL_FEW;
+ return Category.Few;
}
},
// Albanian
- sq(n: number): string | undefined {
+ sq(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Serbian
- sr(n: number): string | undefined {
+ sr(n: number): Category | undefined {
// same as Bosnian
return Plural.bs(n);
},
// Tamil
- ta(n: number): string | undefined {
+ ta(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Telugu
- te(n: number): string | undefined {
+ te(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Tajik
- tg(_n: number): string | undefined {
+ tg(_n: number): Category | undefined {
return undefined;
},
// Thai
- th(_n: number): string | undefined {
+ th(_n: number): Category | undefined {
return undefined;
},
// Turkmen
- tk(n: number): string | undefined {
+ tk(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Turkish
- tr(n: number): string | undefined {
+ tr(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Uyghur
- ug(n: number): string | undefined {
+ ug(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Ukrainian
- uk(n: number): string | undefined {
+ uk(n: number): Category | undefined {
// same as Russian
return Plural.ru(n);
},
// Uzbek
- uz(n: number): string | undefined {
+ uz(n: number): Category | undefined {
if (n == 1) {
- return PLURAL_ONE;
+ return Category.One;
}
},
// Vietnamese
- vi(_n: number): string | undefined {
+ vi(_n: number): Category | undefined {
return undefined;
},
// Chinese
- zh(_n: number): string | undefined {
+ zh(_n: number): Category | undefined {
return undefined;
},
};
+type ValidLanguage = keyof typeof Languages;
+
+// Note: This cannot be an interface due to the computed property.
+type Parameters = {
+ value: number;
+ other: string;
+} & {
+ [category in Category]?: string;
+} & {
+ [number: number]: string;
+ };
+
+const Plural = {
+ /**
+ * Returns the plural category for the given value.
+ */
+ getCategory(value: number, languageCode?: ValidLanguage): Category {
+ if (!languageCode) {
+ languageCode = document.documentElement.lang as ValidLanguage;
+ }
+
+ // Fallback: handle unknown languages as English
+ if (typeof Plural[languageCode] !== "function") {
+ languageCode = "en";
+ }
+
+ const category = Plural[languageCode](value);
+ if (category) {
+ return category;
+ }
+
+ return Category.Other;
+ },
+
+ /**
+ * Returns the value for a `plural` element used in the template.
+ *
+ * @see wcf\system\template\plugin\PluralFunctionTemplatePlugin::execute()
+ */
+ getCategoryFromTemplateParameters(parameters: Parameters): string {
+ if (!parameters["value"]) {
+ throw new Error("Missing parameter value");
+ }
+ if (!parameters["other"]) {
+ throw new Error("Missing parameter other");
+ }
+
+ let value = parameters["value"];
+ if (Array.isArray(value)) {
+ value = value.length;
+ }
+
+ // handle numeric attributes
+ const numericAttribute = Object.keys(parameters).find((key) => {
+ return key.toString() === (~~key).toString() && key.toString() === value.toString();
+ });
+
+ if (numericAttribute) {
+ return numericAttribute;
+ }
+
+ let category = Plural.getCategory(value);
+ if (!parameters[category]) {
+ category = Category.Other;
+ }
+
+ const string = parameters[category]!;
+ if (string.indexOf("#") !== -1) {
+ return string.replace("#", StringUtil.formatNumeric(value));
+ }
+
+ return string;
+ },
+
+ /**
+ * `f` is the fractional number as a whole number (1.234 yields 234)
+ */
+ getF(n: number): number {
+ const tmp = n.toString();
+ const pos = tmp.indexOf(".");
+ if (pos === -1) {
+ return 0;
+ }
+
+ return parseInt(tmp.substr(pos + 1), 10);
+ },
+
+ /**
+ * `v` represents the number of digits of the fractional part (1.234 yields 3)
+ */
+ getV(n: number): number {
+ return n.toString().replace(/^[^.]*\.?/, "").length;
+ },
+
+ ...Languages,
+};
+
export = Plural;