diff --git a/.eslintrc.json b/.eslintrc.json index 0d51ff7..c4fee71 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -11,5 +11,11 @@ "rules": { "no-console": 0 } + }, + { + "files": "./lang/*.js", + "rules": { + "quotes": 0 + } }] } diff --git a/README.md b/README.md index 17d4d1f..b8a80c9 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ## Overview -This library consists of APIs to format and parse numbers, dates, times and file sizes for use in D2L Brightspace. +This library consists of APIs to format and parse numbers, dates, times and file sizes for use in D2L Brightspace. It also provides localization for common terms. > Looking for the older `d2l-intl` library? It's still here [in the `v2.x` branch](https://github.com/BrightspaceUI/intl/tree/v2.x). @@ -28,7 +28,9 @@ import { formatNumber, formatPercent } from '@brightspace-ui/intl/lib/number.js' All of the APIs will automatically detect the document's language via the `lang` attribute on the `` element. They'll also look for various `data-` attributes that will be present in Brightspace pages to access override and timezone information. -## Number Formatting +## Numbers + +### Number Formatting Integer and decimal numbers can be formatted in the user's locale using `formatNumber`. Percentages can be formatted using `formatPercent`. Use the optional `options` parameter for rounding. @@ -65,7 +67,7 @@ const value = formatPercent(0.333, { }); // -> '33.30 %' in en-US ``` -## Number Parsing +### Number Parsing The `parseNumber` method can be used to parse an integer or decimal number written in the user's locale. @@ -75,7 +77,9 @@ import { parseNumber } from '@brightspace-ui/intl/lib/number.js'; const value = parseNumber('-8 942,39'); // -> -8942.39 in fr-CA ``` -## Date/Time Formatting +## Dates & Times + +### Date & Time Formatting Dates and times can be formatted in the user's locale using `formatDate`, `formatTime`, `formatDateTime`, and `formatRelativeDateTime`. @@ -183,7 +187,7 @@ const relativeDateTime = formatRelativeDateTime( ); // If today is 2024-08-22, -> 'last week' in en-US ``` -## Date Parsing +### Date Parsing To parse a date written in the user's locale, use `parseDate`: @@ -196,7 +200,7 @@ date.getMonth(); // -> 8 (months are 0-11) date.getDate(); // -> 23 ``` -## Time Parsing +### Time Parsing To parse a time written in the user's locale, use `parseTime`: @@ -208,7 +212,7 @@ date.getHours(); // -> 14 date.getMinutes(); // -> 5 ``` -## Date/Time Conversion based on user timezone +### Date/Time Conversion based on user timezone To convert an object containing a UTC date to an object containing a local date corresponding to the `data-timezone` attribute: ```javascript @@ -372,7 +376,41 @@ In addition to the Basic Formatting elements, these additional elements may also * `` * `` +### Common Resources + +Some localization resources are common and shared across D2L applications. To use these resources, set the `loadCommon` option: + +```javascript +import { Localize } from '@brightspace-ui/intl/lib/localize.js'; + +const localizer = new Localize({ + loadCommon: true +}); +``` + +#### localizeCharacter + +The localized value of the following characters can be accessed using `localizeCharacter(char)`: +* `'` (apostrophe) +* `&` (ampersand) +* `*` (asterisk) +* `\` (backslash) +* `:` (colon) +* `,` (comma) +* `>` (greater-than sign) +* `<` (less-than sign) +* `#` (number sign) +* `%` (percent sign) +* `|` (pipe) +* `?` (question mark) +* `"` (quotation mark) + +```javascript +const value = localizer.localizeCharacter('&'); // -> 'ampersand' in en-US +``` + ### `onResourcesChange` + Provide an `onResourcesChange` callback function to perform tasks when the document language is changed and updated resources are available: ```javascript diff --git a/intl.serge.json b/intl.serge.json new file mode 100644 index 0000000..ab49bc6 --- /dev/null +++ b/intl.serge.json @@ -0,0 +1,9 @@ +{ + "name": "intl", + "parser_plugin": { + "plugin": "parse_js" + }, + "source_match": "en\\.js$", + "source_dir": "lang", + "output_file_path": "lang/%LANG%.js" + } \ No newline at end of file diff --git a/lang/ar.js b/lang/ar.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/ar.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/cy.js b/lang/cy.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/cy.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/da.js b/lang/da.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/da.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/de.js b/lang/de.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/de.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/en-gb.js b/lang/en-gb.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/en-gb.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/en.js b/lang/en.js new file mode 100644 index 0000000..55af08c --- /dev/null +++ b/lang/en.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", // short name or description of the "'" character + "intl-common:characters:ampersand": "ampersand", // short name or description of the "&" character + "intl-common:characters:asterisk": "asterisk", // short name or description of the "*" character + "intl-common:characters:backslash": "backslash", // short name or description of the "\" character + "intl-common:characters:colon": "colon", // short name or description of the ":" character + "intl-common:characters:comma": "comma", // short name or description of the "," character + "intl-common:characters:greaterThan": "greater-than sign", // short name or description of the ">" character + "intl-common:characters:lessThan": "less-than sign", // short name or description of the "<" character + "intl-common:characters:numberSign": "number sign", // short name or description of the "#" character + "intl-common:characters:percentSign": "percent sign", // short name or description of the "%" character + "intl-common:characters:pipe": "pipe", // short name or description of the "|" character + "intl-common:characters:questionMark": "question mark", // short name or description of the "?" character + "intl-common:characters:quotationMark": "quotation mark", // short name or description of the '"' character +}; diff --git a/lang/es-es.js b/lang/es-es.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/es-es.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/es.js b/lang/es.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/es.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/fr-fr.js b/lang/fr-fr.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/fr-fr.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/fr.js b/lang/fr.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/fr.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/hi.js b/lang/hi.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/hi.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/ja.js b/lang/ja.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/ja.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/ko.js b/lang/ko.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/ko.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/nl.js b/lang/nl.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/nl.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/pt.js b/lang/pt.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/pt.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/sv.js b/lang/sv.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/sv.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/tr.js b/lang/tr.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/tr.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/zh-cn.js b/lang/zh-cn.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/zh-cn.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lang/zh-tw.js b/lang/zh-tw.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/zh-tw.js @@ -0,0 +1,15 @@ +export default { + "intl-common:characters:apostrophe": "apostrophe", + "intl-common:characters:ampersand": "ampersand", + "intl-common:characters:asterisk": "asterisk", + "intl-common:characters:backslash": "backslash", + "intl-common:characters:colon": "colon", + "intl-common:characters:comma": "comma", + "intl-common:characters:greaterThan": "greater-than sign", + "intl-common:characters:lessThan": "less-than sign", + "intl-common:characters:numberSign": "number sign", + "intl-common:characters:percentSign": "percent sign", + "intl-common:characters:pipe": "pipe", + "intl-common:characters:questionMark": "question mark", + "intl-common:characters:quotationMark": "quotation mark", +}; diff --git a/lib/localize.js b/lib/localize.js index c27ae88..e0a9cbc 100644 --- a/lib/localize.js +++ b/lib/localize.js @@ -5,6 +5,24 @@ import IntlMessageFormat from 'intl-messageformat'; export const allowedTags = Object.freeze(['d2l-link', 'd2l-tooltip-help', 'p', 'br', 'b', 'strong', 'i', 'em', 'button']); +const characterMap = new Map([ + ['\'', 'apostrophe'], + ['&', 'ampersand'], + ['*', 'asterisk'], + ['\\', 'backslash'], + [':', 'colon'], + [',', 'comma'], + ['>', 'greaterThan'], + ['<', 'lessThan'], + ['#', 'numberSign'], + ['%', 'percentSign'], + ['|', 'pipe'], + ['?', 'questionMark'], + ['"', 'quotationMark'] +]); +const commonResources = new Map(); +export let commonResourcesImportCount = 0; + const getDisallowedTagsRegex = allowedTags => { const validTerminators = '([>\\s/]|$)'; const allowedAfterTriangleBracket = `/?(${allowedTags.join('|')})?${validTerminators}`; @@ -68,6 +86,17 @@ export const getLocalizeClass = (superclass = class {}) => class LocalizeClass e return formattedMessage; } + localizeCharacter(char) { + if (!characterMap.has(char)) { + throw new Error(`localizeCharacter() does not support character: "${char}"`); + } + const value = this.localize(`intl-common:characters:${characterMap.get(char)}`); + if (value.length === 0) { + throw new Error('localizeCharacter() cannot be used unless loadCommon in localizeConfig is enabled'); + } + return value; + } + localizeHTML(name, replacements = {}) { const { language, value } = this.localize.resources?.[name] ?? {}; @@ -129,12 +158,25 @@ export const getLocalizeClass = (superclass = class {}) => class LocalizeClass e const possibleLanguages = this._generatePossibleLanguages(config); const resourcesPromise = this.getLocalizeResources(possibleLanguages, config); resourcesLoadedPromises.push(resourcesPromise); + if (config?.loadCommon) { + resourcesLoadedPromises.push(this.getLocalizeResources(possibleLanguages, { + importFunc: async(lang) => { + if (commonResources.has(lang)) return commonResources.get(lang); + const resources = (await import(`../lang/${lang}.js`)).default; + commonResourcesImportCount++; + commonResources.set(lang, resources); + return resources; + } + })); + } } return Promise.all(resourcesLoadedPromises); } static async _getLocalizeResources(langs, { importFunc, osloCollection, useBrowserLangs }) { + if (importFunc === undefined) return; + // in dev, don't request unsupported langpacks if (!importFunc.toString().includes('switch') && !useBrowserLangs) { langs = langs.filter(lang => supportedLangpacks.includes(lang)); @@ -171,12 +213,15 @@ export const getLocalizeClass = (superclass = class {}) => class LocalizeClass e const resourcesPromise = this.constructor._getAllLocalizeResources(this.config); this.#resourcesPromise = resourcesPromise; - const localizeResources = (await resourcesPromise).flat(Infinity); + const localizeResources = (await resourcesPromise) + .flat(Infinity) + .filter(e => e); // If the locale changed while resources were being fetched, abort if (this.#resourcesPromise !== resourcesPromise) return; const allResources = {}; const resolvedLocales = new Set(); + for (const { language, resources } of localizeResources) { for (const [name, value] of Object.entries(resources)) { allResources[name] = { language, value }; diff --git a/package.json b/package.json index 83621ef..95d7eae 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "test": "npm run lint && npm run test:unit" }, "files": [ + "/lang", "/lib", "/helpers" ], diff --git a/test/localize.test.js b/test/localize.test.js index dba6933..3aea21a 100644 --- a/test/localize.test.js +++ b/test/localize.test.js @@ -1,5 +1,5 @@ +import { commonResourcesImportCount, Localize, localizeMarkup } from '../lib/localize.js'; import { expect, fixture } from '@brightspace-ui/testing'; -import { Localize, localizeMarkup } from '../lib/localize.js'; const resources = { en: { @@ -71,6 +71,28 @@ describe('Localize', () => { expect(localizer.localize.resources).to.deep.equal(localizer2.localize.resources); }); + it('should handle static resources with no importFunc', async() => { + class StaticLocalizer extends Localize { + static async getLocalizeResources(langs) { + for (let i = 0; i < langs.length; i++) { + if (resources[langs[i]]) { + return { + language: langs[i], + resources: resources[langs[i]] + }; + } + } + } + constructor() { + super({}); + } + } + const staticLocalizer = new StaticLocalizer(); + await staticLocalizer.ready; + const localized = staticLocalizer.localize('basic', { employerName: 'D2L' }); + expect(localized).to.equal('D2L is my employer'); + }); + describe('onResourcesChange', () => { it('runs when the document locale changes', async() => { @@ -118,6 +140,49 @@ describe('Localize', () => { }); + describe('common', () => { + + let localizerCommon; + beforeEach(async() => { + localizerCommon = new Localize({ + loadCommon: true + }); + await localizerCommon.ready; + }); + + afterEach(() => localizerCommon.disconnect()); + + it('should only load common resources once', async() => { + const localizer1 = new Localize({ loadCommon: true }); + const localizer2 = new Localize({ loadCommon: true }); + await Promise.all([localizer1.ready, localizer2.ready]); + expect(commonResourcesImportCount).to.equal(1); + localizer1.disconnect(); + localizer2.disconnect(); + }); + + describe('localizeCharacter', () => { + + it('should localize "&"', async() => { + const localized = localizerCommon.localizeCharacter('&'); + expect(localized).to.equal('ampersand'); + }); + + it('should throw an error for unknown characters', async() => { + expect(() => localizerCommon.localizeCharacter('$')) + .to.throw('localizeCharacter() does not support character: "$"'); + }); + + it('should throw an error if common resources are not loaded', async() => { + await localizer.ready; + expect(() => localizer.localizeCharacter(':')) + .to.throw('localizeCharacter() cannot be used unless loadCommon in localizeConfig is enabled'); + }); + + }); + + }); + describe('localizeHTML()', () => { it('should localize, replacing tags with HTML', async() => {