diff --git a/.eslintrc.json b/.eslintrc.json index 0d51ff7..652b0bb 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -11,5 +11,11 @@ "rules": { "no-console": 0 } - }] + }, + { + "files": "./lang/*.js", + "rules": { + "quotes": 0 + } + }] } 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/en.js b/lang/en.js new file mode 100644 index 0000000..fd1c3d1 --- /dev/null +++ b/lang/en.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 2b42e48..2a35262 100644 --- a/lib/localize.js +++ b/lib/localize.js @@ -5,6 +5,22 @@ 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 getDisallowedTagsRegex = allowedTags => { const validTerminators = '([>\\s/]|$)'; const allowedAfterTriangleBracket = `/?(${allowedTags.join('|')})?${validTerminators}`; @@ -112,6 +128,13 @@ 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}"`); + } + return this.localize(`intl-common:characters:${characterMap.get(char)}`); + } + localizeHTML(name, replacements = {}) { const { language, value } = this.localize.resources?.[name] ?? {}; @@ -166,6 +189,9 @@ export const getLocalizeClass = (superclass = class {}) => class LocalizeClass e const possibleLanguages = this._generatePossibleLanguages(config); const resourcesPromise = this.getLocalizeResources(possibleLanguages, config); resourcesLoadedPromises.push(resourcesPromise); + resourcesLoadedPromises.push(this.getLocalizeResources(possibleLanguages, { + importFunc: async lang => (await import(`../lang/${lang}.js`)).default + })); } return Promise.all(resourcesLoadedPromises); } diff --git a/package.json b/package.json index 8e4f98c..0ed7a8c 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 a45d0be..feaf939 100644 --- a/test/localize.test.js +++ b/test/localize.test.js @@ -103,6 +103,22 @@ describe('Localize', () => { }); + describe('localizeCharacter', () => { + + it('should localize "&"', async() => { + await localizer.ready; + const localized = localizer.localizeCharacter('&'); + expect(localized).to.equal('ampersand'); + }); + + it('should throw an error for unknown characters', async() => { + await localizer.ready; + expect(() => localizer.localizeCharacter('$')) + .to.throw('localizeCharacter() does not support character: "$"'); + }); + + }); + describe('localizeHTML()', () => { it('should localize, replacing tags with HTML', async() => {