From df6f276ee3f44f204116fddf217bc7ac352ff663 Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Thu, 18 Nov 2021 16:16:22 +0900 Subject: [PATCH 1/3] feat: support `localePattern` option for locale structured with directory --- docs/started.md | 28 ++++++++-- lib/types/settings.ts | 14 ++++- lib/utils/casing.ts | 2 +- lib/utils/index.ts | 10 ++-- lib/utils/locale-messages.ts | 36 ++++++++++--- .../path-locales/locales/en/message.json | 10 ++++ .../path-locales/locales/ja/message.yaml | 7 +++ .../valid/path-locales/src/App.vue | 17 +++++++ .../valid/path-locales/src/main.js | 2 + .../utils/locale-messages/locales/en.yaml | 1 + .../locale-messages/locales/en/message.json | 3 ++ .../locale-messages/locales/message.json5 | 8 +++ tests/lib/rules/no-unused-keys.ts | 17 +++++++ tests/lib/utils/locale-messages.ts | 51 +++++++++++++++++++ 14 files changed, 189 insertions(+), 17 deletions(-) create mode 100644 tests/fixtures/no-unused-keys/valid/path-locales/locales/en/message.json create mode 100644 tests/fixtures/no-unused-keys/valid/path-locales/locales/ja/message.yaml create mode 100644 tests/fixtures/no-unused-keys/valid/path-locales/src/App.vue create mode 100644 tests/fixtures/no-unused-keys/valid/path-locales/src/main.js create mode 100644 tests/fixtures/utils/locale-messages/locales/en.yaml create mode 100644 tests/fixtures/utils/locale-messages/locales/en/message.json create mode 100644 tests/fixtures/utils/locale-messages/locales/message.json5 create mode 100644 tests/lib/utils/locale-messages.ts diff --git a/docs/started.md b/docs/started.md index 5002895e..cdc7fe56 100644 --- a/docs/started.md +++ b/docs/started.md @@ -44,17 +44,25 @@ module.export = { // or // localeDir: { // pattern: './path/to/locales/*.{json,json5,yaml,yml}', // extension is glob formatting! - // localeKey: 'file' // or 'key' + // localeKey: 'file' // or 'path' or 'key' // } // or // localeDir: [ // { + // // 'file' case // pattern: './path/to/locales1/*.{json,json5,yaml,yml}', - // localeKey: 'file' // or 'key' + // localeKey: 'file' // }, // { + // // 'path' case // pattern: './path/to/locales2/*.{json,json5,yaml,yml}', - // localeKey: 'file' // or 'key' + // localePattern: /^.*\/(?[A-Za-z0-9-_]+)\/.*\.(json5?|ya?ml)$/, + // localeKey: 'path' + // }, + // { + // // 'key' case + // pattern: './path/to/locales3/*.{json,json5,yaml,yml}', + // localeKey: 'key' // }, // ] @@ -71,15 +79,25 @@ See [the rule list](../rules/) ### `settings['vue-i18n']` - `localeDir` ... You can specify a string or an object or an array. + - String option ... A glob for specifying files that store localization messages of project. - Object option - `pattern` (`string`) ... A glob for specifying files that store localization messages of project. - - `localeKey` (`'file' | 'key'`) ... Specifies how to determine the locale for localization messages. + - `localeKey` (`'file' | 'path' | 'key'`) ... Specifies how to determine the locale for localization messages. - `'file'` ... Determine the locale name from the filename. The resource file should only contain messages for that locale. Use this option if you use `vue-cli-plugin-i18n`. This option is also used when String option is specified. + - `'path'` ... Determine the locale name from the path. In this case, the locale must be had structured with your rule on the path. It can be captured with the regular expression named capture. The resource file should only contain messages for that locale. - `'key'` ... Determine the locale name from the root key name of the file contents. The value of that key should only contain messages for that locale. Used when the resource file is in the format given to the `messages` option of the `VueI18n` constructor option. - - Array option ... An array of String option and Object option. Useful if you have multiple locale directories. + - `localePattern` ... Specifies how to determine pattern the locale for localization messages. This option means, when `localeKey` is `'path'`, you will need to capture the locale using a regular expression. You need to use the locale capture as a named capture `?`, so it’s be able to capture from the path of the locale resources. If you omit it, it will be captured from the resource path with the same regular expression pattern as `vue-cli-plugin-i18n`. + +- Array option ... An array of String option and Object option. Useful if you have multiple locale directories. - `messageSyntaxVersion` (Optional) ... Specify the version of `vue-i18n` you are using. If not specified, the message will be parsed twice. Also, some rules require this setting. +::: warn NOTE + +The `localePattern` options does not support SFC i18n custom blocks (`src` attribute), only for resources of files to import when specified in VueI18n's `messages` options (VueI18n v9 and later, `messages` specified in `createI18n`) for resources of files to import. + +::: + ### Running ESLint from command line If you want to run `eslint` from command line, make sure you include the `.vue`, `.json`, `.json5`, `.yaml` and `.yml` extension using [the `--ext` option](https://eslint.org/docs/user-guide/configuring#specifying-file-extensions-to-lint) or a glob pattern because ESLint targets only `.js` files by default. diff --git a/lib/types/settings.ts b/lib/types/settings.ts index 4554b494..4a510ff5 100644 --- a/lib/types/settings.ts +++ b/lib/types/settings.ts @@ -2,10 +2,12 @@ * How to determine the locale for localization messages. * - `'file'` ... Determine the locale name from the filename. The resource file should only contain messages for that locale. * Use this option if you use `vue-cli-plugin-i18n`. This method is also used when String option is specified. - * - `'key'` ... Determine the locale name from the root key name of the file contents. The value of that key should only contain messages for that locale. + * - `'path'` ... Determine the locale name from the path of resource. In this case, the locale must be had structured with your rule on the path. + * It can be captured with the regular expression named capture. The resource file should only contain messages for that locale. + * - `'key'` ... Determine the locale name from the root key name of the file contents. The value of that key should only contain messages for that locale. * Used when the resource file is in the format given to the `messages` option of the `VueI18n` constructor option. */ -export type LocaleKeyType = 'file' | 'key' +export type LocaleKeyType = 'file' | 'path' | 'key' /** * Type of `settings['vue-i18n'].localeDir` */ @@ -29,4 +31,12 @@ export interface SettingsVueI18nLocaleDirObject { * Specifies how to determine the locale for localization messages. */ localeKey: LocaleKeyType + /** + * Specifies how to determine pattern the locale for localization messages. + * + * This option means, when `localeKey` is `'path'`, you will need to capture the locale using a regular expression. + * You need to use the locale capture as a named capture `?`, so it’s be able to capture from the path of the locale resources. + * If you omit it, it will be captured from the resource path with the same regular expression pattern as `vue-cli-plugin-i18n`. + */ + localePattern?: RegExp } diff --git a/lib/utils/casing.ts b/lib/utils/casing.ts index c81fe316..efec7aa8 100644 --- a/lib/utils/casing.ts +++ b/lib/utils/casing.ts @@ -111,7 +111,7 @@ const checkersMap = { /** * Convert text to camelCase */ -export function camelCase(str: string) { +export function camelCase(str: string): string { if (isPascalCase(str)) { return str.charAt(0).toLowerCase() + str.slice(1) } diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 4f2f51c6..42d3a055 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -29,6 +29,7 @@ import { getCwd } from './get-cwd' interface LocaleFiles { files: string[] localeKey: LocaleKeyType + localePattern?: RegExp } const UNEXPECTED_ERROR_LOCATION = { line: 1, column: 0 } /** @@ -112,7 +113,7 @@ function loadLocaleMessages( ): FileLocaleMessage[] { const results: FileLocaleMessage[] = [] const checkDupeMap: { [file: string]: LocaleKeyType[] } = {} - for (const { files, localeKey } of localeFilesList) { + for (const { files, localeKey, localePattern } of localeFilesList) { for (const file of files) { const localeKeys = checkDupeMap[file] || (checkDupeMap[file] = []) if (localeKeys.includes(localeKey)) { @@ -120,7 +121,9 @@ function loadLocaleMessages( } localeKeys.push(localeKey) const fullpath = resolve(cwd, file) - results.push(new FileLocaleMessage({ fullpath, localeKey })) + results.push( + new FileLocaleMessage({ fullpath, localeKey, localePattern }) + ) } } return results @@ -225,7 +228,8 @@ class LocaleDirLocaleMessagesCache { } else { return { files: targetFilesLoader.get(localeDir.pattern, cwd), - localeKey: String(localeDir.localeKey ?? 'file') as LocaleKeyType + localeKey: String(localeDir.localeKey ?? 'file') as LocaleKeyType, + localePattern: localeDir.localePattern } } } diff --git a/lib/utils/locale-messages.ts b/lib/utils/locale-messages.ts index 5b6af96d..49036679 100644 --- a/lib/utils/locale-messages.ts +++ b/lib/utils/locale-messages.ts @@ -20,6 +20,17 @@ import JSON5 from 'json5' import yaml from 'js-yaml' import { joinPath, parsePath } from './key-path' +// see https://github.com/kazupon/vue-cli-plugin-i18n/blob/e9519235a454db52fdafcd0517ce6607821ef0b4/generator/templates/js/src/i18n.js#L10 +const DEFAULT_LOCALE_PATTERN = '[A-Za-z0-9-_]+' +const DEFAULT_LOCALE_FIELNAME_REGEX = new RegExp( + `(${DEFAULT_LOCALE_PATTERN})\.`, + 'i' +) +const DEFAULT_LOCALE_CAPTURE_REGEX = new RegExp( + `^.*\/(?${DEFAULT_LOCALE_PATTERN})\.(json5?|ya?ml)$`, + 'i' +) + /** * The localization message class */ @@ -27,27 +38,32 @@ export abstract class LocaleMessage { public readonly fullpath: string public readonly localeKey: LocaleKeyType public readonly file: string + public readonly localePattern: RegExp private _locales: string[] | undefined /** * @param {object} arg * @param {string} arg.fullpath Absolute path. * @param {string[]} [arg.locales] The locales. * @param {LocaleKeyType} arg.localeKey Specifies how to determine the locale for localization messages. + * @param {RegExp} args.localePattern Specifies how to determin the regular expression pattern for how to get the locale. */ constructor({ fullpath, locales, - localeKey + localeKey, + localePattern }: { fullpath: string locales?: string[] localeKey: LocaleKeyType + localePattern?: RegExp }) { this.fullpath = fullpath /** @type {LocaleKeyType} Specifies how to determine the locale for localization messages. */ this.localeKey = localeKey /** @type {string} The localization messages file name. */ this.file = fullpath.replace(/^.*(\\|\/|:)/, '') + this.localePattern = localePattern || DEFAULT_LOCALE_CAPTURE_REGEX this._locales = locales } @@ -71,9 +87,13 @@ export abstract class LocaleMessage { return this._locales } if (this.localeKey === 'file') { - // see https://github.com/kazupon/vue-cli-plugin-i18n/blob/e9519235a454db52fdafcd0517ce6607821ef0b4/generator/templates/js/src/i18n.js#L10 - const matched = this.file.match(/([A-Za-z0-9-_]+)\./i) + const matched = this.file.match(DEFAULT_LOCALE_FIELNAME_REGEX) return (this._locales = [(matched && matched[1]) || this.file]) + } else if (this.localeKey === 'path') { + const matched = this.fullpath.match(this.localePattern) + return (this._locales = [ + (matched && matched.groups?.locale) || this.fullpath + ]) } else if (this.localeKey === 'key') { return (this._locales = Object.keys(this.messages)) } @@ -84,7 +104,7 @@ export abstract class LocaleMessage { * Gets messages for the given locale. */ getMessagesFromLocale(locale: string): I18nLocaleMessageDictionary { - if (this.localeKey === 'file') { + if (this.localeKey === 'file' || this.localeKey === 'path') { if (!this.locales.includes(locale)) { return {} } @@ -158,20 +178,24 @@ export class FileLocaleMessage extends LocaleMessage { * @param {string} arg.fullpath Absolute path. * @param {string[]} [arg.locales] The locales. * @param {LocaleKeyType} arg.localeKey Specifies how to determine the locale for localization messages. + * @param {RegExp} args.localePattern Specifies how to determin the regular expression pattern for how to get the locale. */ constructor({ fullpath, locales, - localeKey + localeKey, + localePattern }: { fullpath: string locales?: string[] localeKey: LocaleKeyType + localePattern?: RegExp }) { super({ fullpath, locales, - localeKey + localeKey, + localePattern }) this._resource = new ResourceLoader(fullpath, fileName => { const ext = extname(fileName).toLowerCase() diff --git a/tests/fixtures/no-unused-keys/valid/path-locales/locales/en/message.json b/tests/fixtures/no-unused-keys/valid/path-locales/locales/en/message.json new file mode 100644 index 00000000..c1f057ef --- /dev/null +++ b/tests/fixtures/no-unused-keys/valid/path-locales/locales/en/message.json @@ -0,0 +1,10 @@ +{ + "hello": "hello world", + "messages": { + "hello": "hi DIO!", + "link": "@:messages.hello" + }, + "hello_dio": "hello underscore DIO!", + "hello {name}": "hello {name}!", + "term": "I accept xxx {0}." +} diff --git a/tests/fixtures/no-unused-keys/valid/path-locales/locales/ja/message.yaml b/tests/fixtures/no-unused-keys/valid/path-locales/locales/ja/message.yaml new file mode 100644 index 00000000..0c1a3e2d --- /dev/null +++ b/tests/fixtures/no-unused-keys/valid/path-locales/locales/ja/message.yaml @@ -0,0 +1,7 @@ +hello: "ハローワールド" +messages: + hello: "こんにちは、DIO!" + link: "@:messages.hello" +hello_dio: "こんにちは、アンダースコア DIO!" +"hello {name}": "こんにちは、{name}!" +term: "私は xxx の{0}に同意します。" diff --git a/tests/fixtures/no-unused-keys/valid/path-locales/src/App.vue b/tests/fixtures/no-unused-keys/valid/path-locales/src/App.vue new file mode 100644 index 00000000..78970ba0 --- /dev/null +++ b/tests/fixtures/no-unused-keys/valid/path-locales/src/App.vue @@ -0,0 +1,17 @@ + + + diff --git a/tests/fixtures/no-unused-keys/valid/path-locales/src/main.js b/tests/fixtures/no-unused-keys/valid/path-locales/src/main.js new file mode 100644 index 00000000..8140aeca --- /dev/null +++ b/tests/fixtures/no-unused-keys/valid/path-locales/src/main.js @@ -0,0 +1,2 @@ +const $t = () => {} +$t('hello') diff --git a/tests/fixtures/utils/locale-messages/locales/en.yaml b/tests/fixtures/utils/locale-messages/locales/en.yaml new file mode 100644 index 00000000..0d8e794f --- /dev/null +++ b/tests/fixtures/utils/locale-messages/locales/en.yaml @@ -0,0 +1 @@ +hello: world \ No newline at end of file diff --git a/tests/fixtures/utils/locale-messages/locales/en/message.json b/tests/fixtures/utils/locale-messages/locales/en/message.json new file mode 100644 index 00000000..eeedd400 --- /dev/null +++ b/tests/fixtures/utils/locale-messages/locales/en/message.json @@ -0,0 +1,3 @@ +{ + "hello": "world" +} \ No newline at end of file diff --git a/tests/fixtures/utils/locale-messages/locales/message.json5 b/tests/fixtures/utils/locale-messages/locales/message.json5 new file mode 100644 index 00000000..fe20db3e --- /dev/null +++ b/tests/fixtures/utils/locale-messages/locales/message.json5 @@ -0,0 +1,8 @@ +{ + en: { + hello: "world" + }, + ja: { + hello: "ワールド" + } +} \ No newline at end of file diff --git a/tests/lib/rules/no-unused-keys.ts b/tests/lib/rules/no-unused-keys.ts index 3b7fa08b..44877046 100644 --- a/tests/lib/rules/no-unused-keys.ts +++ b/tests/lib/rules/no-unused-keys.ts @@ -146,6 +146,19 @@ new RuleTester({ src: '.' } ] + }), + ...getTestCasesFromFixtures({ + cwd: join(cwdRoot, './valid/path-locales'), + localeDir: { + pattern: `./locales/**/*.{json,yaml,yml}`, + localeKey: 'path', + localePattern: /^.*\/(?[A-Za-z0-9-_]+)\/.*\.(json5?|ya?ml)$/ + }, + options: [ + { + src: '.' + } + ] }) ] : []), @@ -1021,6 +1034,10 @@ ${' '.repeat(6)} 'constructor-option-format/src/main.js': true, 'multiple-locales/src/App.vue': true, 'multiple-locales/src/main.js': true, + 'path-locales/locales/en/message.json': true, + 'path-locales/locales/ja/message.yaml': true, + 'path-locales/src/App.vue': true, + 'path-locales/src/main.js': true, 'vue-cli-format/src/App.vue': true, 'vue-cli-format/src/main.js': true, 'constructor-option-format/locales/index.json': { diff --git a/tests/lib/utils/locale-messages.ts b/tests/lib/utils/locale-messages.ts new file mode 100644 index 00000000..0a29dc85 --- /dev/null +++ b/tests/lib/utils/locale-messages.ts @@ -0,0 +1,51 @@ +/** + * @author Kazuya Kawaguchi + */ +import path from 'path' +import assert from 'assert' +import { FileLocaleMessage } from '../../../lib/utils/locale-messages' + +describe('FileLocaleMessage', () => { + describe('localeKey: "file"', () => { + it('locales should be resolved', () => { + const testFilePath = path.resolve( + __dirname, + '../../fixtures/utils/locale-messages/locales/en.yaml' + ) + const messages = new FileLocaleMessage({ + fullpath: testFilePath, + localeKey: 'file' + }) + assert.deepStrictEqual(messages.locales, ['en']) + }) + }) + + describe('localeKey: "path"', () => { + it('locales should be resolved', () => { + const testFilePath = path.resolve( + __dirname, + '../../fixtures/utils/locale-messages/locales/en/message.json' + ) + const messages = new FileLocaleMessage({ + fullpath: testFilePath, + localeKey: 'path', + localePattern: /^.*\/(?[A-Za-z0-9-_]+)\/.*\.(json5?|ya?ml)$/ + }) + assert.deepStrictEqual(messages.locales, ['en']) + }) + }) + + describe('localeKey: "key"', () => { + it('locales should be resolved', () => { + const testFilePath = path.resolve( + __dirname, + '../../fixtures/utils/locale-messages/locales/message.json5' + ) + const messages = new FileLocaleMessage({ + fullpath: testFilePath, + localeKey: 'key' + }) + assert.deepStrictEqual(messages.locales, ['en', 'ja']) + }) + }) +}) From 1138c0c7c504a42a06a52cead0105d5e7b248b5e Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Thu, 18 Nov 2021 17:47:21 +0900 Subject: [PATCH 2/3] fix: support string value --- lib/types/settings.ts | 2 +- lib/utils/index.ts | 2 +- lib/utils/locale-messages.ts | 22 ++++++++++++++++++---- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/lib/types/settings.ts b/lib/types/settings.ts index 4a510ff5..897f3dcc 100644 --- a/lib/types/settings.ts +++ b/lib/types/settings.ts @@ -38,5 +38,5 @@ export interface SettingsVueI18nLocaleDirObject { * You need to use the locale capture as a named capture `?`, so it’s be able to capture from the path of the locale resources. * If you omit it, it will be captured from the resource path with the same regular expression pattern as `vue-cli-plugin-i18n`. */ - localePattern?: RegExp + localePattern?: string | RegExp } diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 42d3a055..68737471 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -29,7 +29,7 @@ import { getCwd } from './get-cwd' interface LocaleFiles { files: string[] localeKey: LocaleKeyType - localePattern?: RegExp + localePattern?: string | RegExp } const UNEXPECTED_ERROR_LOCATION = { line: 1, column: 0 } /** diff --git a/lib/utils/locale-messages.ts b/lib/utils/locale-messages.ts index 49036679..0faff64e 100644 --- a/lib/utils/locale-messages.ts +++ b/lib/utils/locale-messages.ts @@ -56,14 +56,14 @@ export abstract class LocaleMessage { fullpath: string locales?: string[] localeKey: LocaleKeyType - localePattern?: RegExp + localePattern?: string | RegExp }) { this.fullpath = fullpath /** @type {LocaleKeyType} Specifies how to determine the locale for localization messages. */ this.localeKey = localeKey /** @type {string} The localization messages file name. */ this.file = fullpath.replace(/^.*(\\|\/|:)/, '') - this.localePattern = localePattern || DEFAULT_LOCALE_CAPTURE_REGEX + this.localePattern = this.getLocalePatternWithRegex(localePattern) this._locales = locales } @@ -73,6 +73,20 @@ export abstract class LocaleMessage { */ abstract getMessagesInternal(): I18nLocaleMessageDictionary + /** + * Get locale pattern with regular expression + */ + getLocalePatternWithRegex(localePattern?: string | RegExp): RegExp { + // prettier-ignore + return localePattern != null + ? typeof localePattern === 'string' + ? new RegExp(localePattern, 'i') + : Object.prototype.toString.call(localePattern) === '[object RegExp]' + ? localePattern + : DEFAULT_LOCALE_CAPTURE_REGEX + : DEFAULT_LOCALE_CAPTURE_REGEX + } + /** * @returns {object} The localization messages object. */ @@ -178,7 +192,7 @@ export class FileLocaleMessage extends LocaleMessage { * @param {string} arg.fullpath Absolute path. * @param {string[]} [arg.locales] The locales. * @param {LocaleKeyType} arg.localeKey Specifies how to determine the locale for localization messages. - * @param {RegExp} args.localePattern Specifies how to determin the regular expression pattern for how to get the locale. + * @param {string | RegExp} args.localePattern Specifies how to determin the regular expression pattern for how to get the locale. */ constructor({ fullpath, @@ -189,7 +203,7 @@ export class FileLocaleMessage extends LocaleMessage { fullpath: string locales?: string[] localeKey: LocaleKeyType - localePattern?: RegExp + localePattern?: string | RegExp }) { super({ fullpath, From c079457c9c62bbfa70a132110936f69c35ef1e70 Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Thu, 18 Nov 2021 13:34:16 +0000 Subject: [PATCH 3/3] Replace judgment of localeKey with common method --- lib/rules/key-format-style.ts | 4 ++-- lib/rules/no-duplicate-keys-in-locale.ts | 2 +- lib/rules/no-missing-keys-in-other-locales.ts | 2 +- lib/utils/locale-messages.ts | 6 +++++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/rules/key-format-style.ts b/lib/rules/key-format-style.ts index 1d6ebf18..d5f9f377 100644 --- a/lib/rules/key-format-style.ts +++ b/lib/rules/key-format-style.ts @@ -63,7 +63,7 @@ function create(context: RuleContext): RuleListener { upper?: KeyStack } let keyStack: KeyStack = { - inLocale: targetLocaleMessage.localeKey === 'file' + inLocale: targetLocaleMessage.isResolvedLocaleByFileName() } return { JSONProperty(node: JSONAST.JSONProperty) { @@ -110,7 +110,7 @@ function create(context: RuleContext): RuleListener { upper?: KeyStack } let keyStack: KeyStack = { - inLocale: targetLocaleMessage.localeKey === 'file' + inLocale: targetLocaleMessage.isResolvedLocaleByFileName() } function withinKey(node: YAMLAST.YAMLNode) { for (const keyNode of yamlKeyNodes) { diff --git a/lib/rules/no-duplicate-keys-in-locale.ts b/lib/rules/no-duplicate-keys-in-locale.ts index 83711a40..a938768f 100644 --- a/lib/rules/no-duplicate-keys-in-locale.ts +++ b/lib/rules/no-duplicate-keys-in-locale.ts @@ -47,7 +47,7 @@ function create(context: RuleContext): RuleListener { targetLocaleMessage: LocaleMessage, otherLocaleMessages: LocaleMessage[] ): PathStack { - if (targetLocaleMessage.localeKey === 'file') { + if (targetLocaleMessage.isResolvedLocaleByFileName()) { const locale = targetLocaleMessage.locales[0] return createInitLocalePathStack(locale, otherLocaleMessages) } else { diff --git a/lib/rules/no-missing-keys-in-other-locales.ts b/lib/rules/no-missing-keys-in-other-locales.ts index 223a3f35..e3baffa6 100644 --- a/lib/rules/no-missing-keys-in-other-locales.ts +++ b/lib/rules/no-missing-keys-in-other-locales.ts @@ -115,7 +115,7 @@ function create(context: RuleContext): RuleListener { }[] } let keyStack: KeyStack - if (targetLocaleMessage.localeKey === 'file') { + if (targetLocaleMessage.isResolvedLocaleByFileName()) { const locale = targetLocaleMessage.locales[0] keyStack = { locale, diff --git a/lib/utils/locale-messages.ts b/lib/utils/locale-messages.ts index 0faff64e..b6f8c67c 100644 --- a/lib/utils/locale-messages.ts +++ b/lib/utils/locale-messages.ts @@ -114,11 +114,15 @@ export abstract class LocaleMessage { return (this._locales = []) } + isResolvedLocaleByFileName() { + return this.localeKey === 'file' || this.localeKey === 'path' + } + /** * Gets messages for the given locale. */ getMessagesFromLocale(locale: string): I18nLocaleMessageDictionary { - if (this.localeKey === 'file' || this.localeKey === 'path') { + if (this.isResolvedLocaleByFileName()) { if (!this.locales.includes(locale)) { return {} }