diff --git a/.eslintrc b/.eslintrc index aeaedff..ba9bdd1 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,7 +5,8 @@ "jest": true }, "rules": { - "@typescript-eslint/no-explicit-any": "off" + "@typescript-eslint/no-explicit-any": "off", + "line-comment-position": "off" }, "overrides": [ { diff --git a/package.json b/package.json index 30c42ed..69edf12 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,6 @@ }, "dependencies": { "deepmerge": "^4.2.2", - "dlv": "^1.1.3", "estree-walker": "^2.0.1", "intl-messageformat": "^9.3.15", "sade": "^1.7.4", diff --git a/src/cli/extract.ts b/src/cli/extract.ts index c7a39e8..7a1f730 100644 --- a/src/cli/extract.ts +++ b/src/cli/extract.ts @@ -10,11 +10,11 @@ import type { import { walk } from 'estree-walker'; import type { Ast } from 'svelte/types/compiler/interfaces'; import { parse } from 'svelte/compiler'; -import dlv from 'dlv'; import { deepSet } from './includes/deepSet'; import { getObjFromExpression } from './includes/getObjFromExpression'; import type { Message } from './types'; +import { delve } from '../shared/delve'; const LIB_NAME = 'svelte-i18n'; const DEFINE_MESSAGES_METHOD_NAME = 'defineMessages'; @@ -189,7 +189,7 @@ export function extractMessages( } else { if ( overwrite === false && - typeof dlv(accumulator, messageObj.id) !== 'undefined' + typeof delve(accumulator, messageObj.id) !== 'undefined' ) { return; } diff --git a/src/runtime/stores/dictionary.ts b/src/runtime/stores/dictionary.ts index ce52e01..a762dbe 100644 --- a/src/runtime/stores/dictionary.ts +++ b/src/runtime/stores/dictionary.ts @@ -1,9 +1,9 @@ import { writable, derived } from 'svelte/store'; import deepmerge from 'deepmerge'; -import dlv from 'dlv'; import type { LocaleDictionary, LocalesDictionary } from '../types/index'; import { getFallbackOf } from './locale'; +import { delve } from '../../shared/delve'; let dictionary: LocalesDictionary; const $dictionary = writable({}); @@ -27,13 +27,7 @@ export function getMessageFromDictionary(locale: string, id: string) { const localeDictionary = getLocaleDictionary(locale); - // flat ids - if (id in localeDictionary) { - return localeDictionary[id]; - } - - // deep ids - const match = dlv(localeDictionary, id); + const match = delve(localeDictionary, id); return match; } diff --git a/src/shared/delve.ts b/src/shared/delve.ts new file mode 100644 index 0000000..6089426 --- /dev/null +++ b/src/shared/delve.ts @@ -0,0 +1,27 @@ +export function delve(obj: Record, fullKey: string) { + if (fullKey in obj) { + return obj[fullKey]; + } + + const keys = fullKey.split('.'); + let result: any = obj; + + for (let p = 0; p < keys.length; p++) { + if (typeof result === 'object') { + if (p > 0) { + const partialKey = keys.slice(p, keys.length).join('.'); + + if (partialKey in result) { + result = result[partialKey]; + break; + } + } + + result = result[keys[p]]; + } else { + result = undefined; + } + } + + return result; +} diff --git a/test/runtime/stores/dictionary.test.ts b/test/runtime/stores/dictionary.test.ts index f6c2289..ea7fa2d 100644 --- a/test/runtime/stores/dictionary.test.ts +++ b/test/runtime/stores/dictionary.test.ts @@ -97,7 +97,7 @@ describe('getting messages', () => { expect(getMessageFromDictionary('en', 'messages.1')).toBe('Other message'); }); - it('accepts english in dictionary keys', () => { + it('gets a shallow message keyed with dots', () => { addMessages('pt', { 'Hey man. How are you today?': 'E ai cara, como vocĂȘ vai hoje?', }); @@ -106,8 +106,34 @@ describe('getting messages', () => { ); }); + it('gets a deep message keyed with dots', () => { + addMessages('pt', { + WCAG: { + SUCCESS_CRITERION: { + '1.1.1': '1.1.1', + '1.2.1': '1.2.1', + '1.3.1': '1.3.1', + not: null, + }, + }, + }); + + expect(getMessageFromDictionary('pt', 'WCAG.SUCCESS_CRITERION.1.3.1')).toBe( + '1.3.1', + ); + expect( + getMessageFromDictionary('pt', 'WCAG.SUCCESS_CRITERION.not'), + ).toBeNull(); + expect( + getMessageFromDictionary( + 'pt', + 'WCAG.SUCCESS_CRITERION.1.3.1.not.existing', + ), + ).toBeUndefined(); + }); + it('returns undefined for missing messages', () => { addMessages('en', {}); - expect(getMessageFromDictionary('en', 'foo')).toBeUndefined(); + expect(getMessageFromDictionary('en', 'foo.potato')).toBeUndefined(); }); }); diff --git a/test/runtime/stores/formatters.test.ts b/test/runtime/stores/formatters.test.ts index 7dfbfb2..5f7a7e7 100644 --- a/test/runtime/stores/formatters.test.ts +++ b/test/runtime/stores/formatters.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable line-comment-position */ import { get } from 'svelte/store'; import type { diff --git a/yarn.lock b/yarn.lock index e2b2603..6cd623a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2450,11 +2450,6 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -dlv@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" - integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== - doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"