diff --git a/i18n.js b/i18n.js index 9507405..d94f178 100644 --- a/i18n.js +++ b/i18n.js @@ -16,7 +16,7 @@ const debug = require('debug')('i18n:debug') const warn = require('debug')('i18n:warn') const error = require('debug')('i18n:error') const Mustache = require('mustache') -const Messageformat = require('@messageformat/core') +const IntlMessageFormat = require('intl-messageformat').default const MakePlural = require('make-plural') const parseInterval = require('math-interval-parser').default @@ -27,7 +27,7 @@ const escapeRegExp = (string) => string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') / * create constructor function */ const i18n = function I18n(_OPTS = false) { - const MessageformatInstanceForLocale = {} + const messageFormatCacheForLocale = new Map() const PluralsForLocale = {} let locales = {} const api = { @@ -300,7 +300,7 @@ const i18n = function I18n(_OPTS = false) { } i18n.__mf = function i18nMessageformat(phrase) { - let msg, mf, f + let msg, compiledFunctions, f let targetLocale = defaultLocale const argv = parseArgv(arguments) const namedValues = argv[0] @@ -328,21 +328,20 @@ const i18n = function I18n(_OPTS = false) { // now head over to Messageformat // and try to cache instance - if (MessageformatInstanceForLocale[targetLocale]) { - mf = MessageformatInstanceForLocale[targetLocale] + if (messageFormatCacheForLocale.has(targetLocale)) { + compiledFunctions = messageFormatCacheForLocale.get(targetLocale) } else { - mf = new Messageformat(targetLocale) - - mf.compiledFunctions = {} - MessageformatInstanceForLocale[targetLocale] = mf + compiledFunctions = new Map() + messageFormatCacheForLocale.set(targetLocale, compiledFunctions) } // let's try to cache that function - if (mf.compiledFunctions[msg]) { - f = mf.compiledFunctions[msg] + if (compiledFunctions.has(msg)) { + f = compiledFunctions.get(msg) } else { - f = mf.compile(msg) - mf.compiledFunctions[msg] = f + const format = new IntlMessageFormat(msg, targetLocale) + f = format.format.bind(format) + compiledFunctions.set(msg, f) } return postProcess(f(namedValues), namedValues, args) diff --git a/package.json b/package.json index e59ee4f..f087371 100644 --- a/package.json +++ b/package.json @@ -26,9 +26,9 @@ "lib": "." }, "dependencies": { - "@messageformat/core": "^3.4.0", "debug": "^4.4.3", "fast-printf": "^1.6.10", + "intl-messageformat": "^10.7.18", "make-plural": "^7.4.0", "math-interval-parser": "^2.0.1", "mustache": "^4.2.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index efa6716..76dfb3a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,15 +8,15 @@ importers: .: dependencies: - '@messageformat/core': - specifier: ^3.4.0 - version: 3.4.0 debug: specifier: ^4.4.3 version: 4.4.3(supports-color@8.1.1) fast-printf: specifier: ^1.6.10 version: 1.6.10 + intl-messageformat: + specifier: ^10.7.18 + version: 10.7.18 make-plural: specifier: ^7.4.0 version: 7.4.0 @@ -175,6 +175,21 @@ packages: resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@formatjs/ecma402-abstract@2.3.6': + resolution: {integrity: sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw==} + + '@formatjs/fast-memoize@2.2.7': + resolution: {integrity: sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==} + + '@formatjs/icu-messageformat-parser@2.11.4': + resolution: {integrity: sha512-7kR78cRrPNB4fjGFZg3Rmj5aah8rQj9KPzuLsmcSn4ipLXQvC04keycTI1F7kJYDwIXtT2+7IDEto842CfZBtw==} + + '@formatjs/icu-skeleton-parser@1.8.16': + resolution: {integrity: sha512-H13E9Xl+PxBd8D5/6TVUluSpxGNvFSlN/b3coUp0e0JpuWXXnQDiavIpY3NnvSp4xhEMoXyyBvVfdFX8jglOHQ==} + + '@formatjs/intl-localematcher@0.6.2': + resolution: {integrity: sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==} + '@humanwhocodes/config-array@0.13.0': resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} @@ -212,21 +227,6 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@messageformat/core@3.4.0': - resolution: {integrity: sha512-NgCFubFFIdMWJGN5WuQhHCNmzk7QgiVfrViFxcS99j7F5dDS5EP6raR54I+2ydhe4+5/XTn/YIEppFaqqVWHsw==} - - '@messageformat/date-skeleton@1.1.0': - resolution: {integrity: sha512-rmGAfB1tIPER+gh3p/RgA+PVeRE/gxuQ2w4snFWPF5xtb5mbWR7Cbw7wCOftcUypbD6HVoxrVdyyghPm3WzP5A==} - - '@messageformat/number-skeleton@1.2.0': - resolution: {integrity: sha512-xsgwcL7J7WhlHJ3RNbaVgssaIwcEyFkBqxHdcdaiJzwTZAWEOD8BuUFxnxV9k5S0qHN3v/KzUpq0IUpjH1seRg==} - - '@messageformat/parser@5.1.1': - resolution: {integrity: sha512-3p0YRGCcTUCYvBKLIxtDDyrJ0YijGIwrTRu1DT8gIviIDZru8H23+FkY6MJBzM1n9n20CiM4VeDYuBsrrwnLjg==} - - '@messageformat/runtime@3.0.2': - resolution: {integrity: sha512-dkIPDCjXcfhSHgNE1/qV6TeczQZR59Yx0xXeafVKgK3QVWoxc38ljwpksUpnzCGvN151KUbCJTDZVmahtf1YZw==} - '@noble/hashes@1.8.0': resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} engines: {node: ^14.21.3 || >=16} @@ -599,6 +599,9 @@ packages: resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} engines: {node: '>=10'} + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -1124,6 +1127,9 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} + intl-messageformat@10.7.18: + resolution: {integrity: sha512-m3Ofv/X/tV8Y3tHXLohcuVuhWKo7BBq62cqY15etqmLxg2DZ34AGGgQDeR+SCta2+zICb1NX83af0GJmbQ1++g==} + ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} @@ -1466,9 +1472,6 @@ packages: engines: {node: '>= 14.0.0'} hasBin: true - moo@0.5.2: - resolution: {integrity: sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==} - ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -1752,9 +1755,6 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - safe-identifier@0.4.2: - resolution: {integrity: sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==} - safe-push-apply@1.0.0: resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} engines: {node: '>= 0.4'} @@ -2271,6 +2271,32 @@ snapshots: '@eslint/js@8.57.1': {} + '@formatjs/ecma402-abstract@2.3.6': + dependencies: + '@formatjs/fast-memoize': 2.2.7 + '@formatjs/intl-localematcher': 0.6.2 + decimal.js: 10.6.0 + tslib: 2.8.1 + + '@formatjs/fast-memoize@2.2.7': + dependencies: + tslib: 2.8.1 + + '@formatjs/icu-messageformat-parser@2.11.4': + dependencies: + '@formatjs/ecma402-abstract': 2.3.6 + '@formatjs/icu-skeleton-parser': 1.8.16 + tslib: 2.8.1 + + '@formatjs/icu-skeleton-parser@1.8.16': + dependencies: + '@formatjs/ecma402-abstract': 2.3.6 + tslib: 2.8.1 + + '@formatjs/intl-localematcher@0.6.2': + dependencies: + tslib: 2.8.1 + '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 @@ -2312,27 +2338,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@messageformat/core@3.4.0': - dependencies: - '@messageformat/date-skeleton': 1.1.0 - '@messageformat/number-skeleton': 1.2.0 - '@messageformat/parser': 5.1.1 - '@messageformat/runtime': 3.0.2 - make-plural: 7.4.0 - safe-identifier: 0.4.2 - - '@messageformat/date-skeleton@1.1.0': {} - - '@messageformat/number-skeleton@1.2.0': {} - - '@messageformat/parser@5.1.1': - dependencies: - moo: 0.5.2 - - '@messageformat/runtime@3.0.2': - dependencies: - make-plural: 7.4.0 - '@noble/hashes@1.8.0': {} '@nodelib/fs.scandir@2.1.5': @@ -2733,6 +2738,8 @@ snapshots: decamelize@4.0.0: {} + decimal.js@10.6.0: {} + deep-is@0.1.4: {} default-require-extensions@3.0.1: @@ -3381,6 +3388,13 @@ snapshots: hasown: 2.0.2 side-channel: 1.1.0 + intl-messageformat@10.7.18: + dependencies: + '@formatjs/ecma402-abstract': 2.3.6 + '@formatjs/fast-memoize': 2.2.7 + '@formatjs/icu-messageformat-parser': 2.11.4 + tslib: 2.8.1 + ipaddr.js@1.9.1: {} is-array-buffer@3.0.5: @@ -3732,8 +3746,6 @@ snapshots: yargs-parser: 20.2.9 yargs-unparser: 2.0.0 - moo@0.5.2: {} - ms@2.0.0: {} ms@2.1.3: {} @@ -4038,8 +4050,6 @@ snapshots: safe-buffer@5.2.1: {} - safe-identifier@0.4.2: {} - safe-push-apply@1.0.0: dependencies: es-errors: 1.3.0 diff --git a/test/i18n.writenewPhrase.js b/test/i18n.writenewPhrase.js index e2db187..96561bc 100644 --- a/test/i18n.writenewPhrase.js +++ b/test/i18n.writenewPhrase.js @@ -158,7 +158,7 @@ describe('when i18n gets a new phrase', () => { msg += 'other{others for #}}' // this should just add that string - TestScope.__mf(msg, { N: 1 }) + TestScope.__mf(msg, { language: '', N: 1 }) should.deepEqual(getJson('en')[msg], msg) should.deepEqual(getJson('de')[msg], msg)