Skip to content

Commit

Permalink
feat: support autoDetectI18nConfig option
Browse files Browse the repository at this point in the history
1. autoDetectI18nConfig is enable default. If enable, plugin will find up vscode settings until reach `stopAt` dir.
2. deprecate `dotVscodePath` because it seems useless. Now use `root` instead of `dotVscodePath`
  • Loading branch information
hemengke1997 committed Dec 18, 2023
1 parent cabd91d commit 9ccaa91
Show file tree
Hide file tree
Showing 12 changed files with 137 additions and 96 deletions.
16 changes: 8 additions & 8 deletions README-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ pnpm add vite-plugin-i18n-detector -D

**如果已配置i18n.ally,插件会默认读取配置**

| 参数 | 类型 | 默认值 | 描述 |
| ------------- | ----------------- | ------------------------------------------------------------ | ----------------------------------------------- |
| localesPaths | `string[]` | `i18n-ally.localesPaths \|\| ['./src/locales', './locales']` | 存放语言资源的目录地址 |
| root | `string` | `process.cwd()` | 存放语言资源的根目录地址,相对于 `localesPaths` |
| namespace | `boolean` | `i18n-ally.namespace \|\| false` | 是否启用命名空间 |
| pathMatcher | `string` | 自动探测 | 资源文件匹配规则 |
| parserPlugins | `ParserPlugin[]` | `[jsonParser, json5Parser, yamlParser]` | 资源文件解析插件 |
| dotVscodePath | `string | false` | `process.cwd()` | vscode配置文件路径,用于自动探测配置 |
| 参数 | 类型 | 默认值 | 描述 |
| -------------------- | --------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------- |
| localesPaths | `string[]` | `i18n-ally.localesPaths \|\| ['./src/locales', './locales']` | 存放语言资源的目录地址,相对于 `root` |
| root | `string` | `process.cwd()` | 项目根路径 |
| namespace | `boolean` | `i18n-ally.namespace \|\| false` | 是否启用命名空间 |
| pathMatcher | `string` | 自动探测 | 资源文件匹配规则 |
| parserPlugins | `ParserPlugin[]` | `[jsonParser, json5Parser, yamlParser]` | 资源文件解析插件 |
| autoDetectI18nConfig | `boolean \| { stopAt: string }` | `true` | 是否自动探测i18n配置项,如果传入stopAt,则会在指定的目录停止探测 |

## 配置参考

Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ pnpm add vite-plugin-i18n-detector -D

**If `i18n.ally` is configured, the plugin will read the configuration by default**

| Option | Type | Default | Description |
| ------------- | ----------------- | ------------------------------------------------------------ | ------------------------------------------------------------------ |
| localesPaths | `string[]` | `i18n-ally.localesPaths \|\| ['./src/locales', './locales']` | The directory of language resources |
| root | `string` | `process.cwd()` | The root directory of language resources |
| namespace | `boolean` | `i18n-ally.namespace \|\| false` | Enable namespace |
| pathMatcher | `string` | auto detected by structure | Resource file matching rule |
| parserPlugins | `ParserPlugin[]` | `[jsonParser, json5Parser, yamlParser]` | Resource file parsing plugin |
| dotVscodePath | `string | false` | `process.cwd()` | vscode configuration file path, used for auto detect configuration |
| Option | Type | Default | Description |
| -------------------- | --------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| localesPaths | `string[]` | `i18n-ally.localesPaths \|\| ['./src/locales', './locales']` | The directory of language resources, relative to `root` |
| root | `string` | `process.cwd()` | The project root path |
| namespace | `boolean` | `i18n-ally.namespace \|\| false` | Enable namespace |
| pathMatcher | `string` | auto detected by structure | Resource file matching rule |
| parserPlugins | `ParserPlugin[]` | `[jsonParser, json5Parser, yamlParser]` | Resource file parsing plugin |
| autoDetectI18nConfig | `boolean \| { stopAt: string }` | `true` | Whether to automatically detect i18n-ally configuration, if stopAt is passed in, it will stop detecting in the specified directory |

## Config Reference

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"clone-deep": "^4.0.1",
"debug": "^4.3.4",
"fast-glob": "^3.3.1",
"find-up": "^7.0.0",
"js-yaml": "^4.1.0",
"json5": "^2.2.3",
"language-tags": "^1.0.9",
Expand Down
2 changes: 1 addition & 1 deletion playground/spa/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default defineConfig({
localesPaths: ['./src/locales'],
namespace: true,
pathMatcher: '{locale}/{namespace}.{ext}',
dotVscodePath: false,
autoDetectI18nConfig: false,
}),
],
})
2 changes: 1 addition & 1 deletion playground/vscode-setting/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default defineConfig({
react(),
i18nDetector({
root: __dirname,
dotVscodePath: __dirname,
autoDetectI18nConfig: true,
}),
],
})
22 changes: 17 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 17 additions & 4 deletions src/plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ export type ParserPlugin = ParserConstructor | undefined
export interface I18nDetectorOptions {
/**
* @description locales directory paths
*
* localesPaths are relative to root
* @default
* ```js
* ['./src/locales', './locales']
* ```
*/
localesPaths?: string[]
/**
* @description localesPaths's root path
* localesPaths are relative to root
* @description root path
* @default process.cwd()
*/
root?: string
Expand Down Expand Up @@ -63,13 +64,25 @@ export interface I18nDetectorOptions {
* @description i18n-ally config root path
* @default process.cwd()
*
* if dotVscodePath is process.cwd()
* if dotVscodePath is truly,
* i18n-ally config path is
* path.resolve(process.cwd(), './vscode/settings.json') by default
* path.resolve(process.cwd(), './vscode/settings.json')
*
* if false, will not detect i18n-ally config
*
* @deprecated
* use `root` instead
*/
dotVscodePath?: string | false
/**
* @description auto detect config of vscode extension `i18n-ally`
* @default true
*/
autoDetectI18nConfig?:
| boolean
| {
stopAt: string
}
}

export async function i18nDetector(opts?: I18nDetectorOptions): Promise<any> {
Expand Down
2 changes: 1 addition & 1 deletion src/plugin/locale-detector/LocaleDetector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { PKGNAME, VIRTUAL } from '../utils/constant'
import { debug } from '../utils/debugger'
import { logger } from '../utils/logger'

export type Config = Omit<Required<I18nDetectorOptions>, 'dotVscodePath'>
export type Config = Omit<Required<I18nDetectorOptions>, 'dotVscodePath' | 'autoDetectI18nConfig'>

type PathMatcherType = RegExp

Expand Down
68 changes: 68 additions & 0 deletions src/plugin/utils/I18nAllyVscodeSetting.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { findUpSync } from 'find-up'
import JSON5 from 'json5'
import fs from 'node:fs'
import path from 'node:path'
import { debug } from './debugger'

export class I18nAllyVscodeSetting {
static I18N_ALLY_KEY = 'i18n-ally.'
static SETTING_FILE = '.vscode/settings.json'
public i18nConfig: Record<string, any> | undefined

constructor(
private readonly _root: string,
private readonly _stopAt: string = _root,
) {
debug('I18nAllyVscodeSetting - root:', _root)
debug('I18nAllyVscodeSetting - stopAt:', _stopAt)
}

findUp() {
const settingFile = findUpSync(I18nAllyVscodeSetting.SETTING_FILE, {
type: 'file',
cwd: this._root,
stopAt: this._stopAt,
})

debug('findup - settingFile:', settingFile)
return settingFile
}

init() {
const settings = this.readJsonFile(this.findUp())

if (settings) {
const removePrefix = (key: string) => key.replace(I18nAllyVscodeSetting.I18N_ALLY_KEY, '')
const filteredConfig = Object.keys(settings)
.filter((key) => key.startsWith(I18nAllyVscodeSetting.I18N_ALLY_KEY))
.reduce(
(obj, key) => {
if (key === `${I18nAllyVscodeSetting.I18N_ALLY_KEY}localesPaths`) {
if (Array.isArray(settings[key])) {
obj[removePrefix(key)] = settings[key].map((p: string) => path.resolve(this._root, p))
}
} else {
obj[removePrefix(key)] = settings[key]
}
return obj
},
{} as Record<string, any>,
)
if (Object.keys(filteredConfig).length) {
this.i18nConfig = filteredConfig
}
}
return this.i18nConfig
}

readJsonFile(filePath: string | undefined) {
if (filePath) {
try {
return JSON5.parse(fs.readFileSync(filePath, { encoding: 'utf-8' }))
} catch {
return ''
}
}
return ''
}
}
24 changes: 14 additions & 10 deletions src/plugin/utils/init-options.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
import { type I18nDetectorOptions } from '..'
import { getI18nAllyConfigByKey, readI18nAllyConfig } from './vscode-settings'
import { I18nAllyVscodeSetting } from './I18nAllyVscodeSetting'
import { debug } from './debugger'

const DEFAULT_OPTIONS: I18nDetectorOptions = {
localesPaths: ['./src/locales', './locales'],
root: process.cwd(),
namespace: false,
dotVscodePath: process.cwd(),
autoDetectI18nConfig: true,
}

function getDefaultOptions(options?: I18nDetectorOptions): I18nDetectorOptions {
let i18AllyConfig: Record<string, any> | undefined = undefined
if (options?.dotVscodePath !== false) {
// detect vscode settings of i18n-ally
i18AllyConfig = readI18nAllyConfig(options?.dotVscodePath || (DEFAULT_OPTIONS.dotVscodePath as string))
if (options?.dotVscodePath !== undefined) {
console.warn(`dotVscodePath is deprecated, please use 'root' instead`)
}

if (i18AllyConfig) {
if (options?.autoDetectI18nConfig) {
const stopAt = typeof options.autoDetectI18nConfig === 'object' ? options.autoDetectI18nConfig.stopAt : undefined
const i18nAlly = new I18nAllyVscodeSetting(options?.root || (DEFAULT_OPTIONS.root as string), stopAt).init()

debug('i18n-ally config:', i18nAlly)

return {
localesPaths: getI18nAllyConfigByKey(i18AllyConfig, 'localesPaths') ?? DEFAULT_OPTIONS.localesPaths,
pathMatcher: getI18nAllyConfigByKey(i18AllyConfig, 'pathMatcher'),
namespace: getI18nAllyConfigByKey(i18AllyConfig, 'namespace') ?? DEFAULT_OPTIONS.namespace,
...DEFAULT_OPTIONS,
localesPaths: i18nAlly?.['localesPaths'] ?? DEFAULT_OPTIONS.localesPaths,
pathMatcher: i18nAlly?.['pathMatcher'] ?? DEFAULT_OPTIONS.pathMatcher,
namespace: i18nAlly?.['namespace'] ?? DEFAULT_OPTIONS.namespace,
}
}

Expand Down
57 changes: 0 additions & 57 deletions src/plugin/utils/vscode-settings.ts

This file was deleted.

2 changes: 1 addition & 1 deletion tests/LocaleDetector.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('LocaleDetector - Dir mode', () => {
root: path.resolve(__dirname, './fixtures/'),
localesPaths: [path.resolve(__dirname, './fixtures/locales/')],
namespace: true,
dotVscodePath: false,
autoDetectI18nConfig: false,
})

localeDetector = new LocaleDetector(options)
Expand Down

0 comments on commit 9ccaa91

Please sign in to comment.