govuk-frontend
Version:
GOV.UK Frontend contains the code you need to start building a user interface for government platforms and services.
196 lines (194 loc) • 5.68 kB
JavaScript
class I18n {
constructor(translations = {}, config = {}) {
var _config$locale;
this.translations = void 0;
this.locale = void 0;
this.translations = translations;
this.locale = (_config$locale = config.locale) != null ? _config$locale : document.documentElement.lang || 'en';
}
t(lookupKey, options) {
if (!lookupKey) {
throw new Error('i18n: lookup key missing');
}
let translation = this.translations[lookupKey];
if (typeof (options == null ? void 0 : options.count) === 'number' && typeof translation === 'object') {
const translationPluralForm = translation[this.getPluralSuffix(lookupKey, options.count)];
if (translationPluralForm) {
translation = translationPluralForm;
}
}
if (typeof translation === 'string') {
if (translation.match(/%{(.\S+)}/)) {
if (!options) {
throw new Error('i18n: cannot replace placeholders in string if no option data provided');
}
return this.replacePlaceholders(translation, options);
}
return translation;
}
return lookupKey;
}
replacePlaceholders(translationString, options) {
const formatter = Intl.NumberFormat.supportedLocalesOf(this.locale).length ? new Intl.NumberFormat(this.locale) : undefined;
return translationString.replace(/%{(.\S+)}/g, function (placeholderWithBraces, placeholderKey) {
if (Object.prototype.hasOwnProperty.call(options, placeholderKey)) {
const placeholderValue = options[placeholderKey];
if (placeholderValue === false || typeof placeholderValue !== 'number' && typeof placeholderValue !== 'string') {
return '';
}
if (typeof placeholderValue === 'number') {
return formatter ? formatter.format(placeholderValue) : `${placeholderValue}`;
}
return placeholderValue;
}
throw new Error(`i18n: no data found to replace ${placeholderWithBraces} placeholder in string`);
});
}
hasIntlPluralRulesSupport() {
return Boolean('PluralRules' in window.Intl && Intl.PluralRules.supportedLocalesOf(this.locale).length);
}
getPluralSuffix(lookupKey, count) {
count = Number(count);
if (!isFinite(count)) {
return 'other';
}
const translation = this.translations[lookupKey];
const preferredForm = this.hasIntlPluralRulesSupport() ? new Intl.PluralRules(this.locale).select(count) : this.selectPluralFormUsingFallbackRules(count);
if (typeof translation === 'object') {
if (preferredForm in translation) {
return preferredForm;
} else if ('other' in translation) {
console.warn(`i18n: Missing plural form ".${preferredForm}" for "${this.locale}" locale. Falling back to ".other".`);
return 'other';
}
}
throw new Error(`i18n: Plural form ".other" is required for "${this.locale}" locale`);
}
selectPluralFormUsingFallbackRules(count) {
count = Math.abs(Math.floor(count));
const ruleset = this.getPluralRulesForLocale();
if (ruleset) {
return I18n.pluralRules[ruleset](count);
}
return 'other';
}
getPluralRulesForLocale() {
const localeShort = this.locale.split('-')[0];
for (const pluralRule in I18n.pluralRulesMap) {
const languages = I18n.pluralRulesMap[pluralRule];
if (languages.includes(this.locale) || languages.includes(localeShort)) {
return pluralRule;
}
}
}
}
I18n.pluralRulesMap = {
arabic: ['ar'],
chinese: ['my', 'zh', 'id', 'ja', 'jv', 'ko', 'ms', 'th', 'vi'],
french: ['hy', 'bn', 'fr', 'gu', 'hi', 'fa', 'pa', 'zu'],
german: ['af', 'sq', 'az', 'eu', 'bg', 'ca', 'da', 'nl', 'en', 'et', 'fi', 'ka', 'de', 'el', 'hu', 'lb', 'no', 'so', 'sw', 'sv', 'ta', 'te', 'tr', 'ur'],
irish: ['ga'],
russian: ['ru', 'uk'],
scottish: ['gd'],
spanish: ['pt-PT', 'it', 'es'],
welsh: ['cy']
};
I18n.pluralRules = {
arabic(n) {
if (n === 0) {
return 'zero';
}
if (n === 1) {
return 'one';
}
if (n === 2) {
return 'two';
}
if (n % 100 >= 3 && n % 100 <= 10) {
return 'few';
}
if (n % 100 >= 11 && n % 100 <= 99) {
return 'many';
}
return 'other';
},
chinese() {
return 'other';
},
french(n) {
return n === 0 || n === 1 ? 'one' : 'other';
},
german(n) {
return n === 1 ? 'one' : 'other';
},
irish(n) {
if (n === 1) {
return 'one';
}
if (n === 2) {
return 'two';
}
if (n >= 3 && n <= 6) {
return 'few';
}
if (n >= 7 && n <= 10) {
return 'many';
}
return 'other';
},
russian(n) {
const lastTwo = n % 100;
const last = lastTwo % 10;
if (last === 1 && lastTwo !== 11) {
return 'one';
}
if (last >= 2 && last <= 4 && !(lastTwo >= 12 && lastTwo <= 14)) {
return 'few';
}
if (last === 0 || last >= 5 && last <= 9 || lastTwo >= 11 && lastTwo <= 14) {
return 'many';
}
return 'other';
},
scottish(n) {
if (n === 1 || n === 11) {
return 'one';
}
if (n === 2 || n === 12) {
return 'two';
}
if (n >= 3 && n <= 10 || n >= 13 && n <= 19) {
return 'few';
}
return 'other';
},
spanish(n) {
if (n === 1) {
return 'one';
}
if (n % 1000000 === 0 && n !== 0) {
return 'many';
}
return 'other';
},
welsh(n) {
if (n === 0) {
return 'zero';
}
if (n === 1) {
return 'one';
}
if (n === 2) {
return 'two';
}
if (n === 3) {
return 'few';
}
if (n === 6) {
return 'many';
}
return 'other';
}
};
export { I18n };
//# sourceMappingURL=i18n.mjs.map