govuk-frontend
Version:
GOV.UK Frontend contains the code you need to start building a user interface for government platforms and services.
1 lines • 23.6 kB
Source Map (JSON)
{"version":3,"file":"i18n.mjs","sources":["../../src/govuk/i18n.mjs"],"sourcesContent":["/**\n * Internal support for selecting messages to render, with placeholder\n * interpolation and locale-aware number formatting and pluralisation\n *\n * @internal\n */\nexport class I18n {\n translations\n locale\n\n /**\n * @internal\n * @param {{ [key: string]: string | TranslationPluralForms }} translations - Key-value pairs of the translation strings to use.\n * @param {object} [config] - Configuration options for the function.\n * @param {string | null} [config.locale] - An overriding locale for the PluralRules functionality.\n */\n constructor(translations = {}, config = {}) {\n // Make list of translations available throughout function\n this.translations = translations\n\n // The locale to use for PluralRules and NumberFormat\n this.locale = config.locale ?? (document.documentElement.lang || 'en')\n }\n\n /**\n * The most used function - takes the key for a given piece of UI text and\n * returns the appropriate string.\n *\n * @internal\n * @param {string} lookupKey - The lookup key of the string to use.\n * @param {{ [key: string]: unknown }} [options] - Any options passed with the translation string, e.g: for string interpolation.\n * @returns {string} The appropriate translation string.\n * @throws {Error} Lookup key required\n * @throws {Error} Options required for `${}` placeholders\n */\n t(lookupKey, options) {\n if (!lookupKey) {\n // Print a console error if no lookup key has been provided\n throw new Error('i18n: lookup key missing')\n }\n\n // Fetch the translation for that lookup key\n let translation = this.translations[lookupKey]\n\n // If the `count` option is set, determine which plural suffix is needed and\n // change the lookupKey to match. We check to see if it's numeric instead of\n // falsy, as this could legitimately be 0.\n if (typeof options?.count === 'number' && typeof translation === 'object') {\n const translationPluralForm =\n translation[this.getPluralSuffix(lookupKey, options.count)]\n\n // Update translation with plural suffix\n if (translationPluralForm) {\n translation = translationPluralForm\n }\n }\n\n if (typeof translation === 'string') {\n // Check for ${} placeholders in the translation string\n if (translation.match(/%{(.\\S+)}/)) {\n if (!options) {\n throw new Error(\n 'i18n: cannot replace placeholders in string if no option data provided'\n )\n }\n\n return this.replacePlaceholders(translation, options)\n }\n\n return translation\n }\n\n // If the key wasn't found in our translations object,\n // return the lookup key itself as the fallback\n return lookupKey\n }\n\n /**\n * Takes a translation string with placeholders, and replaces the placeholders\n * with the provided data\n *\n * @internal\n * @param {string} translationString - The translation string\n * @param {{ [key: string]: unknown }} options - Any options passed with the translation string, e.g: for string interpolation.\n * @returns {string} The translation string to output, with $\\{\\} placeholders replaced\n */\n replacePlaceholders(translationString, options) {\n const formatter = Intl.NumberFormat.supportedLocalesOf(this.locale).length\n ? new Intl.NumberFormat(this.locale)\n : undefined\n\n return translationString.replace(\n /%{(.\\S+)}/g,\n\n /**\n * Replace translation string placeholders\n *\n * @internal\n * @param {string} placeholderWithBraces - Placeholder with braces\n * @param {string} placeholderKey - Placeholder key\n * @returns {string} Placeholder value\n */\n function (placeholderWithBraces, placeholderKey) {\n if (Object.prototype.hasOwnProperty.call(options, placeholderKey)) {\n const placeholderValue = options[placeholderKey]\n\n // If a user has passed `false` as the value for the placeholder\n // treat it as though the value should not be displayed\n if (\n placeholderValue === false ||\n (typeof placeholderValue !== 'number' &&\n typeof placeholderValue !== 'string')\n ) {\n return ''\n }\n\n // If the placeholder's value is a number, localise the number formatting\n if (typeof placeholderValue === 'number') {\n return formatter\n ? formatter.format(placeholderValue)\n : `${placeholderValue}`\n }\n\n return placeholderValue\n }\n\n throw new Error(\n `i18n: no data found to replace ${placeholderWithBraces} placeholder in string`\n )\n }\n )\n }\n\n /**\n * Check to see if the browser supports Intl.PluralRules\n *\n * It requires all conditions to be met in order to be supported:\n * - The implementation of Intl supports PluralRules (NOT true in Safari 10–12)\n * - The browser/OS has plural rules for the current locale (browser dependent)\n *\n * {@link https://browsersl.ist/#q=supports+es6-module+and+not+supports+intl-pluralrules}\n *\n * @internal\n * @returns {boolean} Returns true if all conditions are met. Returns false otherwise.\n */\n hasIntlPluralRulesSupport() {\n return Boolean(\n 'PluralRules' in window.Intl &&\n Intl.PluralRules.supportedLocalesOf(this.locale).length\n )\n }\n\n /**\n * Get the appropriate suffix for the plural form.\n *\n * Uses Intl.PluralRules (or our own fallback implementation) to get the\n * 'preferred' form to use for the given count.\n *\n * Checks that a translation has been provided for that plural form – if it\n * hasn't, it'll fall back to the 'other' plural form (unless that doesn't exist\n * either, in which case an error will be thrown)\n *\n * @internal\n * @param {string} lookupKey - The lookup key of the string to use.\n * @param {number} count - Number used to determine which pluralisation to use.\n * @returns {PluralRule} The suffix associated with the correct pluralisation for this locale.\n * @throws {Error} Plural form `.other` required when preferred plural form is missing\n */\n getPluralSuffix(lookupKey, count) {\n // Validate that the number is actually a number.\n //\n // Number(count) will turn anything that can't be converted to a Number type\n // into 'NaN'. isFinite filters out NaN, as it isn't a finite number.\n count = Number(count)\n if (!isFinite(count)) {\n return 'other'\n }\n\n // Fetch the translation for that lookup key\n const translation = this.translations[lookupKey]\n\n // Check to verify that all the requirements for Intl.PluralRules are met.\n // If so, we can use that instead of our custom implementation. Otherwise,\n // use the hardcoded fallback.\n const preferredForm = this.hasIntlPluralRulesSupport()\n ? new Intl.PluralRules(this.locale).select(count)\n : this.selectPluralFormUsingFallbackRules(count)\n\n // Use the correct plural form if provided\n if (typeof translation === 'object') {\n if (preferredForm in translation) {\n return preferredForm\n // Fall back to `other` if the plural form is missing, but log a warning\n // to the console\n } else if ('other' in translation) {\n console.warn(\n `i18n: Missing plural form \".${preferredForm}\" for \"${this.locale}\" locale. Falling back to \".other\".`\n )\n\n return 'other'\n }\n }\n\n // If the required `other` plural form is missing, all we can do is error\n throw new Error(\n `i18n: Plural form \".other\" is required for \"${this.locale}\" locale`\n )\n }\n\n /**\n * Get the plural form using our fallback implementation\n *\n * This is split out into a separate function to make it easier to test the\n * fallback behaviour in an environment where Intl.PluralRules exists.\n *\n * @internal\n * @param {number} count - Number used to determine which pluralisation to use.\n * @returns {PluralRule} The pluralisation form for count in this locale.\n */\n selectPluralFormUsingFallbackRules(count) {\n // Currently our custom code can only handle positive integers, so let's\n // make sure our number is one of those.\n count = Math.abs(Math.floor(count))\n\n const ruleset = this.getPluralRulesForLocale()\n\n if (ruleset) {\n return I18n.pluralRules[ruleset](count)\n }\n\n return 'other'\n }\n\n /**\n * Work out which pluralisation rules to use for the current locale\n *\n * The locale may include a regional indicator (such as en-GB), but we don't\n * usually care about this part, as pluralisation rules are usually the same\n * regardless of region. There are exceptions, however, (e.g. Portuguese) so\n * this searches by both the full and shortened locale codes, just to be sure.\n *\n * @internal\n * @returns {string | undefined} The name of the pluralisation rule to use (a key for one\n * of the functions in this.pluralRules)\n */\n getPluralRulesForLocale() {\n const localeShort = this.locale.split('-')[0]\n\n // Look through the plural rules map to find which `pluralRule` is\n // appropriate for our current `locale`.\n for (const pluralRule in I18n.pluralRulesMap) {\n const languages = I18n.pluralRulesMap[pluralRule]\n if (languages.includes(this.locale) || languages.includes(localeShort)) {\n return pluralRule\n }\n }\n }\n\n /**\n * Map of plural rules to languages where those rules apply.\n *\n * Note: These groups are named for the most dominant or recognisable language\n * that uses each system. The groupings do not imply that the languages are\n * related to one another. Many languages have evolved the same systems\n * independently of one another.\n *\n * Code to support more languages can be found in the i18n spike:\n * {@link https://github.com/alphagov/govuk-frontend/blob/spike-i18n-support/src/govuk/i18n.mjs}\n *\n * Languages currently supported:\n *\n * Arabic: Arabic (ar)\n * Chinese: Burmese (my), Chinese (zh), Indonesian (id), Japanese (ja),\n * Javanese (jv), Korean (ko), Malay (ms), Thai (th), Vietnamese (vi)\n * French: Armenian (hy), Bangla (bn), French (fr), Gujarati (gu), Hindi (hi),\n * Persian Farsi (fa), Punjabi (pa), Zulu (zu)\n * German: Afrikaans (af), Albanian (sq), Azerbaijani (az), Basque (eu),\n * Bulgarian (bg), Catalan (ca), Danish (da), Dutch (nl), English (en),\n * Estonian (et), Finnish (fi), Georgian (ka), German (de), Greek (el),\n * Hungarian (hu), Luxembourgish (lb), Norwegian (no), Somali (so),\n * Swahili (sw), Swedish (sv), Tamil (ta), Telugu (te), Turkish (tr),\n * Urdu (ur)\n * Irish: Irish Gaelic (ga)\n * Russian: Russian (ru), Ukrainian (uk)\n * Scottish: Scottish Gaelic (gd)\n * Spanish: European Portuguese (pt-PT), Italian (it), Spanish (es)\n * Welsh: Welsh (cy)\n *\n * @internal\n * @type {{ [key: string]: string[] }}\n */\n static pluralRulesMap = {\n arabic: ['ar'],\n chinese: ['my', 'zh', 'id', 'ja', 'jv', 'ko', 'ms', 'th', 'vi'],\n french: ['hy', 'bn', 'fr', 'gu', 'hi', 'fa', 'pa', 'zu'],\n german: [\n 'af',\n 'sq',\n 'az',\n 'eu',\n 'bg',\n 'ca',\n 'da',\n 'nl',\n 'en',\n 'et',\n 'fi',\n 'ka',\n 'de',\n 'el',\n 'hu',\n 'lb',\n 'no',\n 'so',\n 'sw',\n 'sv',\n 'ta',\n 'te',\n 'tr',\n 'ur'\n ],\n irish: ['ga'],\n russian: ['ru', 'uk'],\n scottish: ['gd'],\n spanish: ['pt-PT', 'it', 'es'],\n welsh: ['cy']\n }\n\n /**\n * Different pluralisation rule sets\n *\n * Returns the appropriate suffix for the plural form associated with `n`.\n * Possible suffixes: 'zero', 'one', 'two', 'few', 'many', 'other' (the actual\n * meaning of each differs per locale). 'other' should always exist, even in\n * languages without plurals, such as Chinese.\n * {@link https://cldr.unicode.org/index/cldr-spec/plural-rules}\n *\n * The count must be a positive integer. Negative numbers and decimals aren't accounted for\n *\n * @internal\n * @type {{ [key: string]: (count: number) => PluralRule }}\n */\n static pluralRules = {\n arabic(n) {\n if (n === 0) {\n return 'zero'\n }\n if (n === 1) {\n return 'one'\n }\n if (n === 2) {\n return 'two'\n }\n if (n % 100 >= 3 && n % 100 <= 10) {\n return 'few'\n }\n if (n % 100 >= 11 && n % 100 <= 99) {\n return 'many'\n }\n return 'other'\n },\n chinese() {\n return 'other'\n },\n french(n) {\n return n === 0 || n === 1 ? 'one' : 'other'\n },\n german(n) {\n return n === 1 ? 'one' : 'other'\n },\n irish(n) {\n if (n === 1) {\n return 'one'\n }\n if (n === 2) {\n return 'two'\n }\n if (n >= 3 && n <= 6) {\n return 'few'\n }\n if (n >= 7 && n <= 10) {\n return 'many'\n }\n return 'other'\n },\n russian(n) {\n const lastTwo = n % 100\n const last = lastTwo % 10\n if (last === 1 && lastTwo !== 11) {\n return 'one'\n }\n if (last >= 2 && last <= 4 && !(lastTwo >= 12 && lastTwo <= 14)) {\n return 'few'\n }\n if (\n last === 0 ||\n (last >= 5 && last <= 9) ||\n (lastTwo >= 11 && lastTwo <= 14)\n ) {\n return 'many'\n }\n // Note: The 'other' suffix is only used by decimal numbers in Russian.\n // We don't anticipate it being used, but it's here for consistency.\n return 'other'\n },\n scottish(n) {\n if (n === 1 || n === 11) {\n return 'one'\n }\n if (n === 2 || n === 12) {\n return 'two'\n }\n if ((n >= 3 && n <= 10) || (n >= 13 && n <= 19)) {\n return 'few'\n }\n return 'other'\n },\n spanish(n) {\n if (n === 1) {\n return 'one'\n }\n if (n % 1000000 === 0 && n !== 0) {\n return 'many'\n }\n return 'other'\n },\n welsh(n) {\n if (n === 0) {\n return 'zero'\n }\n if (n === 1) {\n return 'one'\n }\n if (n === 2) {\n return 'two'\n }\n if (n === 3) {\n return 'few'\n }\n if (n === 6) {\n return 'many'\n }\n return 'other'\n }\n }\n}\n\n/**\n * Plural rule category mnemonic tags\n *\n * @internal\n * @typedef {'zero' | 'one' | 'two' | 'few' | 'many' | 'other'} PluralRule\n */\n\n/**\n * Translated message by plural rule they correspond to.\n *\n * Allows to group pluralised messages under a single key when passing\n * translations to a component's constructor\n *\n * @internal\n * @typedef {object} TranslationPluralForms\n * @property {string} [other] - General plural form\n * @property {string} [zero] - Plural form used with 0\n * @property {string} [one] - Plural form used with 1\n * @property {string} [two] - Plural form used with 2\n * @property {string} [few] - Plural form used for a few\n * @property {string} [many] - Plural form used for many\n */\n"],"names":["I18n","constructor","translations","config","_config$locale","locale","document","documentElement","lang","t","lookupKey","options","Error","translation","count","translationPluralForm","getPluralSuffix","match","replacePlaceholders","translationString","formatter","Intl","NumberFormat","supportedLocalesOf","length","undefined","replace","placeholderWithBraces","placeholderKey","Object","prototype","hasOwnProperty","call","placeholderValue","format","hasIntlPluralRulesSupport","Boolean","window","PluralRules","Number","isFinite","preferredForm","select","selectPluralFormUsingFallbackRules","console","warn","Math","abs","floor","ruleset","getPluralRulesForLocale","pluralRules","localeShort","split","pluralRule","pluralRulesMap","languages","includes","arabic","chinese","french","german","irish","russian","scottish","spanish","welsh","n","lastTwo","last"],"mappings":"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"}