@markuplint/i18n 4.6.1-dev.350 → 4.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/$schema.json +1 -0
- package/CHANGELOG.md +14 -0
- package/SKILL.md +73 -0
- package/cjs/translator.d.ts +22 -0
- package/cjs/translator.js +23 -2
- package/cjs/types.d.ts +50 -0
- package/docs/maintenance.ja.md +207 -0
- package/docs/maintenance.md +207 -0
- package/esm/translator.d.ts +22 -0
- package/esm/translator.mjs +23 -2
- package/esm/types.d.ts +50 -0
- package/locales/ja.json +1 -0
- package/package.json +6 -5
package/$schema.json
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [4.7.1](https://github.com/markuplint/markuplint/compare/@markuplint/i18n@4.7.0...@markuplint/i18n@4.7.1) (2026-02-10)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @markuplint/i18n
|
|
9
|
+
|
|
10
|
+
# [4.7.0](https://github.com/markuplint/markuplint/compare/@markuplint/i18n@4.6.0...@markuplint/i18n@4.7.0) (2025-08-13)
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
- ensure that each `clean` command correctly removes build files ([110b78e](https://github.com/markuplint/markuplint/commit/110b78e85379d29a84ca68325127344a87a570b6))
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
- **i18n:** add new sentence format pattern '{0} {1}' ([6b61b5b](https://github.com/markuplint/markuplint/commit/6b61b5b03ad441c253fbeb921e0604509b7d32e3))
|
|
19
|
+
|
|
6
20
|
# [4.6.0](https://github.com/markuplint/markuplint/compare/@markuplint/i18n@4.5.7...@markuplint/i18n@4.6.0) (2024-11-17)
|
|
7
21
|
|
|
8
22
|
### Features
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Maintenance tasks for @markuplint/i18n — internationalization for markuplint
|
|
3
|
+
globs:
|
|
4
|
+
- packages/@markuplint/i18n/src/**/*.ts
|
|
5
|
+
- packages/@markuplint/i18n/locales/*.json
|
|
6
|
+
- packages/@markuplint/i18n/$schema.json
|
|
7
|
+
alwaysApply: false
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# @markuplint/i18n Maintenance
|
|
11
|
+
|
|
12
|
+
You are maintaining `@markuplint/i18n`, the internationalization package for markuplint.
|
|
13
|
+
|
|
14
|
+
## Architecture
|
|
15
|
+
|
|
16
|
+
See [README.md](README.md) for the full API documentation including translator usage, placeholder syntax, and locale formatting.
|
|
17
|
+
|
|
18
|
+
For detailed maintenance procedures, see [docs/maintenance.md](docs/maintenance.md) ([Japanese](docs/maintenance.ja.md)).
|
|
19
|
+
|
|
20
|
+
## Key Files
|
|
21
|
+
|
|
22
|
+
| File | Role |
|
|
23
|
+
| ------------------- | ---------------------------------------------------------------------------------------------- |
|
|
24
|
+
| `locales/ja.json` | Japanese locale dictionary (keywords + sentences + listFormat) |
|
|
25
|
+
| `locales/en.json` | English locale dictionary (minimal; only entries needing capitalization or special formatting) |
|
|
26
|
+
| `$schema.json` | JSON Schema for locale files (`additionalProperties: false`) |
|
|
27
|
+
| `src/translator.ts` | Core translation logic |
|
|
28
|
+
| `src/types.ts` | `LocaleSet`, `ListFormat`, `Translator` types |
|
|
29
|
+
|
|
30
|
+
## Tasks
|
|
31
|
+
|
|
32
|
+
### add-keyword
|
|
33
|
+
|
|
34
|
+
Add a new keyword used in rule messages.
|
|
35
|
+
|
|
36
|
+
1. Add to `locales/ja.json` under `keywords` (alphabetical order, lowercase key)
|
|
37
|
+
- Normal keyword: `"tag name": "タグ名"`
|
|
38
|
+
- Complement keyword (for `:c` flag): `"c:deprecated": "は非推奨です"`
|
|
39
|
+
2. Add to `locales/en.json` under `keywords` only if capitalization or special formatting is needed
|
|
40
|
+
3. Add to `$schema.json` under `keywords.properties` as `{ "type": "string" }`
|
|
41
|
+
4. Test: `yarn test --scope @markuplint/i18n`
|
|
42
|
+
5. Build: `yarn build --scope @markuplint/i18n`
|
|
43
|
+
|
|
44
|
+
**Important**: `$schema.json` uses `additionalProperties: false`. A keyword not defined in the schema will cause validation errors. Always keep the three files in sync.
|
|
45
|
+
|
|
46
|
+
### add-sentence
|
|
47
|
+
|
|
48
|
+
Add a new sentence template for rule messages.
|
|
49
|
+
|
|
50
|
+
1. Design the English template as the key
|
|
51
|
+
- Placeholders: `{0}`, `{1}`, `{2}`...
|
|
52
|
+
- Complement flag: `{0:c}` (resolves to `c:` prefixed keyword in Japanese)
|
|
53
|
+
- No-translate mark: `{0*}` (skips translation for that placeholder)
|
|
54
|
+
2. Add to `locales/ja.json` under `sentences` (placeholder order may differ for natural Japanese)
|
|
55
|
+
3. Add to `$schema.json` under `sentences.properties` as `{ "type": "string" }`
|
|
56
|
+
4. `en.json` does not need a `sentences` entry (the English key itself serves as the template)
|
|
57
|
+
5. Test: `yarn test --scope @markuplint/i18n`
|
|
58
|
+
|
|
59
|
+
### add-language
|
|
60
|
+
|
|
61
|
+
Add support for a new language.
|
|
62
|
+
|
|
63
|
+
1. Create `locales/<lang>.json` using `ja.json` as a template
|
|
64
|
+
- `listFormat`: Define quote characters and separator for the language
|
|
65
|
+
- `keywords`: Translate all keywords
|
|
66
|
+
- `sentences`: Translate all sentence templates
|
|
67
|
+
2. Add an export entry in `package.json`:
|
|
68
|
+
```json
|
|
69
|
+
"./locales/<lang>.json": { "import": "./locales/<lang>.json", "require": "./locales/<lang>.json" }
|
|
70
|
+
```
|
|
71
|
+
3. `$schema.json` is shared across all languages (no changes needed)
|
|
72
|
+
4. Add test cases in `src/index.spec.ts`
|
|
73
|
+
5. Test: `yarn test --scope @markuplint/i18n`
|
package/cjs/translator.d.ts
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
import type { LocaleSet, Primitive, Translator } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a {@link Translator} function bound to the given locale set.
|
|
4
|
+
*
|
|
5
|
+
* The returned translator supports two call signatures:
|
|
6
|
+
* - **Message template**: `t("The {0} is {1}", keyword1, keyword2)` – interpolates keywords into
|
|
7
|
+
* a message template, looking up translations from the locale set's `sentences` and `keywords`.
|
|
8
|
+
* - **List formatting**: `t(["apple", "banana", "cherry"], true)` – formats an array of strings
|
|
9
|
+
* into a human-readable list (e.g. `"apple", "banana" and "cherry"`).
|
|
10
|
+
*
|
|
11
|
+
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
12
|
+
* @returns A translator function for producing localized messages
|
|
13
|
+
*/
|
|
2
14
|
export declare function translator(localeSet?: LocaleSet): Translator;
|
|
3
15
|
/**
|
|
16
|
+
* Creates a tagged template literal translator function.
|
|
17
|
+
*
|
|
18
|
+
* Allows using template literal syntax for translations:
|
|
19
|
+
* ```ts
|
|
20
|
+
* const tt = taggedTemplateTranslator(localeSet);
|
|
21
|
+
* const msg = tt`The ${name} is ${value}`;
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
4
24
|
* @experimental
|
|
25
|
+
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
26
|
+
* @returns A tagged template function that produces localized strings
|
|
5
27
|
*/
|
|
6
28
|
export declare function taggedTemplateTranslator(localeSet?: LocaleSet): (strings: Readonly<TemplateStringsArray>, ...keys: readonly Primitive[]) => string;
|
package/cjs/translator.js
CHANGED
|
@@ -8,9 +8,20 @@ const defaultListFormat = {
|
|
|
8
8
|
separator: ', ',
|
|
9
9
|
lastSeparator: ' and ',
|
|
10
10
|
};
|
|
11
|
+
/**
|
|
12
|
+
* Creates a {@link Translator} function bound to the given locale set.
|
|
13
|
+
*
|
|
14
|
+
* The returned translator supports two call signatures:
|
|
15
|
+
* - **Message template**: `t("The {0} is {1}", keyword1, keyword2)` – interpolates keywords into
|
|
16
|
+
* a message template, looking up translations from the locale set's `sentences` and `keywords`.
|
|
17
|
+
* - **List formatting**: `t(["apple", "banana", "cherry"], true)` – formats an array of strings
|
|
18
|
+
* into a human-readable list (e.g. `"apple", "banana" and "cherry"`).
|
|
19
|
+
*
|
|
20
|
+
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
21
|
+
* @returns A translator function for producing localized messages
|
|
22
|
+
*/
|
|
11
23
|
function translator(localeSet) {
|
|
12
24
|
return (messageTmpl, ...keywords) => {
|
|
13
|
-
let message = messageTmpl;
|
|
14
25
|
if (typeof messageTmpl !== 'string') {
|
|
15
26
|
if (messageTmpl.length === 0) {
|
|
16
27
|
return '';
|
|
@@ -40,7 +51,7 @@ function translator(localeSet) {
|
|
|
40
51
|
messageTmpl = sentence ?? key;
|
|
41
52
|
messageTmpl =
|
|
42
53
|
removeNoTranslateMark(input.toLowerCase()) === messageTmpl ? removeNoTranslateMark(input) : messageTmpl;
|
|
43
|
-
message = messageTmpl.replaceAll(
|
|
54
|
+
const message = messageTmpl.replaceAll(
|
|
44
55
|
// eslint-disable-next-line regexp/strict
|
|
45
56
|
/{(\d+)(?::(c))?}/g, ($0, number, flag) => {
|
|
46
57
|
const num = Number.parseInt(number);
|
|
@@ -58,7 +69,17 @@ function translator(localeSet) {
|
|
|
58
69
|
};
|
|
59
70
|
}
|
|
60
71
|
/**
|
|
72
|
+
* Creates a tagged template literal translator function.
|
|
73
|
+
*
|
|
74
|
+
* Allows using template literal syntax for translations:
|
|
75
|
+
* ```ts
|
|
76
|
+
* const tt = taggedTemplateTranslator(localeSet);
|
|
77
|
+
* const msg = tt`The ${name} is ${value}`;
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
61
80
|
* @experimental
|
|
81
|
+
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
82
|
+
* @returns A tagged template function that produces localized strings
|
|
62
83
|
*/
|
|
63
84
|
function taggedTemplateTranslator(localeSet) {
|
|
64
85
|
const t = translator(localeSet);
|
package/cjs/types.d.ts
CHANGED
|
@@ -1,21 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A function that translates message templates or formats keyword lists
|
|
3
|
+
* according to a bound locale set.
|
|
4
|
+
*
|
|
5
|
+
* Overloads:
|
|
6
|
+
* 1. Translate a message template with keyword interpolation.
|
|
7
|
+
* 2. Format a list of keywords into a human-readable string.
|
|
8
|
+
* 3. Combined signature accepting either form.
|
|
9
|
+
*/
|
|
1
10
|
export interface Translator {
|
|
11
|
+
/**
|
|
12
|
+
* Translates a message template by interpolating keywords.
|
|
13
|
+
*
|
|
14
|
+
* @param messageTmpl - The message template with `{0}`, `{1}`, ... placeholders
|
|
15
|
+
* @param keywords - Values to substitute into the template
|
|
16
|
+
* @returns The translated, interpolated message string
|
|
17
|
+
*/
|
|
2
18
|
(messageTmpl: string, ...keywords: readonly Primitive[]): string;
|
|
19
|
+
/**
|
|
20
|
+
* Formats a list of keywords into a localized, human-readable string.
|
|
21
|
+
*
|
|
22
|
+
* @param messageTmpl - An array of keywords to format as a list
|
|
23
|
+
* @param useLastSeparator - Whether to use the "last separator" (e.g. " and ") before the final item
|
|
24
|
+
* @returns The formatted list string
|
|
25
|
+
*/
|
|
3
26
|
(messageTmpl: readonly string[], useLastSeparator?: boolean): string;
|
|
27
|
+
/**
|
|
28
|
+
* Combined overload accepting either a message template string or a keyword list.
|
|
29
|
+
*
|
|
30
|
+
* @param messageTmpl - A message template string or an array of keywords
|
|
31
|
+
* @param keywords - Values to substitute (when a string template is provided)
|
|
32
|
+
* @returns The translated or formatted string
|
|
33
|
+
*/
|
|
4
34
|
(messageTmpl: string | readonly string[], ...keywords: readonly Primitive[]): string;
|
|
5
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Configuration for a specific locale, including translations and formatting rules.
|
|
38
|
+
*/
|
|
6
39
|
export type LocaleSet = {
|
|
40
|
+
/** The locale identifier (e.g. `"en"`, `"ja"`) */
|
|
7
41
|
readonly locale: string;
|
|
42
|
+
/** Formatting rules for rendering keyword lists */
|
|
8
43
|
readonly listFormat?: ListFormat;
|
|
44
|
+
/** A dictionary mapping lowercase keywords to their translations */
|
|
9
45
|
readonly keywords?: LocalesKeywords;
|
|
46
|
+
/** A dictionary mapping lowercase sentence templates to their translations */
|
|
10
47
|
readonly sentences?: LocalesKeywords;
|
|
11
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* Formatting rules for rendering a list of items as a human-readable string.
|
|
51
|
+
*/
|
|
12
52
|
export type ListFormat = {
|
|
53
|
+
/** Character(s) placed before each quoted item (e.g. `"`) */
|
|
13
54
|
readonly quoteStart: string;
|
|
55
|
+
/** Character(s) placed after each quoted item (e.g. `"`) */
|
|
14
56
|
readonly quoteEnd: string;
|
|
57
|
+
/** Separator between items (e.g. `", "`) */
|
|
15
58
|
readonly separator: string;
|
|
59
|
+
/** Separator before the last item (e.g. `" and "`); falls back to `separator` if omitted */
|
|
16
60
|
readonly lastSeparator?: string;
|
|
17
61
|
};
|
|
62
|
+
/**
|
|
63
|
+
* A primitive value type used as a keyword in translations.
|
|
64
|
+
*/
|
|
18
65
|
export type Primitive = string | number | boolean;
|
|
66
|
+
/**
|
|
67
|
+
* A dictionary mapping message IDs (lowercase) to their translated strings.
|
|
68
|
+
*/
|
|
19
69
|
export type LocalesKeywords = {
|
|
20
70
|
readonly [messageId: string]: string;
|
|
21
71
|
};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# @markuplint/i18n メンテナンスガイド
|
|
2
|
+
|
|
3
|
+
## 概要
|
|
4
|
+
|
|
5
|
+
`@markuplint/i18n` パッケージは、markuplint のルールメッセージの国際化を提供します。
|
|
6
|
+
|
|
7
|
+
- **ロケール辞書** (`locales/*.json`) — 言語ごとのキーワード、文テンプレート、リスト書式ルール
|
|
8
|
+
- **翻訳エンジン** (`src/translator.ts`) — テンプレートのキーワード置換、補語形式、リスト整形を処理
|
|
9
|
+
- **JSON Schema** (`$schema.json`) — 厳密なプロパティチェックでロケールファイルを検証
|
|
10
|
+
|
|
11
|
+
### ファイル構成
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
packages/@markuplint/i18n/
|
|
15
|
+
├── locales/
|
|
16
|
+
│ ├── ja.json # 日本語辞書(完全版)
|
|
17
|
+
│ └── en.json # 英語辞書(最小限のオーバーライド)
|
|
18
|
+
├── src/
|
|
19
|
+
│ ├── translator.ts # 翻訳コアロジック
|
|
20
|
+
│ ├── types.ts # LocaleSet, Translator 型定義
|
|
21
|
+
│ └── index.spec.ts # テストスイート
|
|
22
|
+
├── $schema.json # ロケール JSON Schema
|
|
23
|
+
└── package.json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 3ファイル同期ルール
|
|
27
|
+
|
|
28
|
+
キーワードや文テンプレートを追加する際、3つのファイルを同期する必要があります。
|
|
29
|
+
|
|
30
|
+
| ファイル | 役割 | 必須? |
|
|
31
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------- |
|
|
32
|
+
| `$schema.json` | 許可されるプロパティキーを定義。`additionalProperties: false` のため、ここに定義されていないキーはバリデーションエラーになる。 | **常に必須** |
|
|
33
|
+
| `locales/ja.json` | すべてのキーワードと文テンプレートの日本語翻訳。 | **常に必須** |
|
|
34
|
+
| `locales/en.json` | 英語のオーバーライド。大文字化や特殊な書式が必要な場合のみ(例: `"html elements"` → `"HTML elements"`)。 | 必要な場合のみ |
|
|
35
|
+
|
|
36
|
+
スキーマが有効なキーの定義元です。`ja.json` にキーワードを追加しても `$schema.json` に追加しなければ、ロケールファイルのスキーマ検証が失敗します。
|
|
37
|
+
|
|
38
|
+
## 単語を追加する
|
|
39
|
+
|
|
40
|
+
キーワードは、ルールメッセージの構成要素として使われる単語または短いフレーズです。ロケールファイルの `keywords` セクションに定義します。
|
|
41
|
+
|
|
42
|
+
### 手順
|
|
43
|
+
|
|
44
|
+
1. **`ja.json`** の `keywords` にアルファベット順で追加:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"keywords": {
|
|
49
|
+
"focusable": "フォーカス可能"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- キーは英語の小文字
|
|
55
|
+
- 値は日本語の翻訳
|
|
56
|
+
|
|
57
|
+
2. **`en.json`** の `keywords` には必要な場合のみ追加:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"keywords": {
|
|
62
|
+
"html elements": "HTML elements"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
ほとんどの英語キーワードはエントリ不要です。キーがそのまま使用されます。
|
|
68
|
+
|
|
69
|
+
3. **`$schema.json`** の `keywords.properties` に追加:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"keywords": {
|
|
74
|
+
"properties": {
|
|
75
|
+
"focusable": { "type": "string" }
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
4. **テスト**: `yarn test --scope @markuplint/i18n`
|
|
82
|
+
5. **ビルド**: `yarn build --scope @markuplint/i18n`
|
|
83
|
+
|
|
84
|
+
### 補語キーワード
|
|
85
|
+
|
|
86
|
+
補語キーワードは `c:` プレフィックスを使い、プレースホルダーに `:c` フラグ(例: `{0:c}`)が付いた場合に解決されます。日本語では主語に続く述語として機能します。
|
|
87
|
+
|
|
88
|
+
| ロケールのキー | テンプレートでの使用 | 出力例(ja) |
|
|
89
|
+
| ---------------------------------------- | -------------------------------------------- | ------------------------------ |
|
|
90
|
+
| `"c:deprecated": "は非推奨です"` | `"{0} is {1:c}"` + キーワード `"deprecated"` | `「要素」は非推奨です` |
|
|
91
|
+
| `"c:disallowed": "は許可されていません"` | `"{0} is {1:c}"` + キーワード `"disallowed"` | `「属性」は許可されていません` |
|
|
92
|
+
|
|
93
|
+
補語キーワードを追加する際:
|
|
94
|
+
|
|
95
|
+
1. `ja.json` の keywords に `"c:<word>"` を追加
|
|
96
|
+
2. `$schema.json` の keywords properties に `"c:<word>"` を追加
|
|
97
|
+
3. 補語なしバージョン(`c:` なし)も別のキーワードとして必要な場合がある
|
|
98
|
+
|
|
99
|
+
## フレーズを追加する
|
|
100
|
+
|
|
101
|
+
文テンプレートは、プレースホルダー付きのメッセージパターンを定義します。ロケールファイルの `sentences` セクションに定義します。
|
|
102
|
+
|
|
103
|
+
### 手順
|
|
104
|
+
|
|
105
|
+
1. **英語テンプレート**をキーとして設計:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
"{0} conflicts with {1}"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
プレースホルダー構文:
|
|
112
|
+
- `{0}`, `{1}`, `{2}` — 位置パラメータ、キーワードとして翻訳される
|
|
113
|
+
- `{0:c}` — 補語フラグ、日本語では `c:` プレフィックスキーワードに解決
|
|
114
|
+
- `{0*}` — 翻訳スキップ、値がキーワード検索なしでそのまま挿入される
|
|
115
|
+
|
|
116
|
+
2. **`ja.json`** の `sentences` に追加:
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"sentences": {
|
|
121
|
+
"{0} conflicts with {1}": "{0}は{1}と競合しています"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
日本語の自然な語順にするため、プレースホルダーの順序は英語と異なってもよい。
|
|
127
|
+
|
|
128
|
+
3. **`$schema.json`** の `sentences.properties` に追加:
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"sentences": {
|
|
133
|
+
"properties": {
|
|
134
|
+
"{0} conflicts with {1}": { "type": "string" }
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
4. **`en.json` に sentences エントリは不要**。英語のキー自体がテンプレートとして使用されます。翻訳が見つからない場合、translator はキーをそのまま使います。
|
|
141
|
+
|
|
142
|
+
5. **テスト**: `yarn test --scope @markuplint/i18n`
|
|
143
|
+
|
|
144
|
+
### プレースホルダーの並べ替え
|
|
145
|
+
|
|
146
|
+
日本語と英語では語順が異なります。文テンプレートを翻訳する際、プレースホルダーは自由に並べ替えできます:
|
|
147
|
+
|
|
148
|
+
- 英語: `"{0} is not allowed in {1}"`
|
|
149
|
+
- 日本語: `"{1}に{0}は許可されていません"`
|
|
150
|
+
|
|
151
|
+
プレースホルダーの番号は、translator に渡される引数の位置を指し、文字列内の位置ではありません。
|
|
152
|
+
|
|
153
|
+
## 新しい言語を追加する
|
|
154
|
+
|
|
155
|
+
まったく新しい言語のサポートを追加する手順です。
|
|
156
|
+
|
|
157
|
+
### 手順
|
|
158
|
+
|
|
159
|
+
1. **`locales/<lang>.json`** を `ja.json` をテンプレートにして作成:
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"$schema": "../$schema.json",
|
|
164
|
+
"listFormat": {
|
|
165
|
+
"quoteStart": "\"",
|
|
166
|
+
"quoteEnd": "\"",
|
|
167
|
+
"separator": ", "
|
|
168
|
+
},
|
|
169
|
+
"keywords": {
|
|
170
|
+
"attribute": "<翻訳>",
|
|
171
|
+
"element": "<翻訳>"
|
|
172
|
+
},
|
|
173
|
+
"sentences": {
|
|
174
|
+
"{0} is {1}": "<翻訳テンプレート>"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
- `listFormat`: 言語に適した引用符と区切り文字を定義
|
|
180
|
+
- `keywords`: `ja.json` のすべてのキーワードを翻訳
|
|
181
|
+
- `sentences`: `ja.json` のすべての文テンプレートを翻訳
|
|
182
|
+
|
|
183
|
+
2. **`package.json`** にエクスポートエントリを追加:
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"exports": {
|
|
188
|
+
"./locales/<lang>.json": {
|
|
189
|
+
"import": "./locales/<lang>.json",
|
|
190
|
+
"require": "./locales/<lang>.json"
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
3. **`$schema.json` の変更は不要** — スキーマは全言語で共有されます。
|
|
197
|
+
|
|
198
|
+
4. **`src/index.spec.ts`** に新しいロケールのテストケースを追加。
|
|
199
|
+
|
|
200
|
+
5. **テスト**: `yarn test --scope @markuplint/i18n`
|
|
201
|
+
|
|
202
|
+
## コマンドリファレンス
|
|
203
|
+
|
|
204
|
+
| コマンド | 説明 |
|
|
205
|
+
| ------------------------------------- | ------------------ |
|
|
206
|
+
| `yarn test --scope @markuplint/i18n` | テスト実行 |
|
|
207
|
+
| `yarn build --scope @markuplint/i18n` | パッケージのビルド |
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# @markuplint/i18n Maintenance Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The `@markuplint/i18n` package provides internationalization for markuplint rule messages. It consists of:
|
|
6
|
+
|
|
7
|
+
- **Locale dictionaries** (`locales/*.json`) — keywords, sentence templates, and list formatting rules per language
|
|
8
|
+
- **Translator engine** (`src/translator.ts`) — resolves templates with keyword substitution, complement forms, and list formatting
|
|
9
|
+
- **JSON Schema** (`$schema.json`) — validates locale files with strict property checking
|
|
10
|
+
|
|
11
|
+
### File Structure
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
packages/@markuplint/i18n/
|
|
15
|
+
├── locales/
|
|
16
|
+
│ ├── ja.json # Japanese dictionary (complete)
|
|
17
|
+
│ └── en.json # English dictionary (minimal overrides)
|
|
18
|
+
├── src/
|
|
19
|
+
│ ├── translator.ts # Core translation logic
|
|
20
|
+
│ ├── types.ts # LocaleSet, Translator types
|
|
21
|
+
│ └── index.spec.ts # Test suite
|
|
22
|
+
├── $schema.json # Locale JSON Schema
|
|
23
|
+
└── package.json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Three-File Synchronization Rule
|
|
27
|
+
|
|
28
|
+
When adding keywords or sentences, three files must be kept in sync:
|
|
29
|
+
|
|
30
|
+
| File | Role | Required? |
|
|
31
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | -------------- |
|
|
32
|
+
| `$schema.json` | Defines allowed property keys. Uses `additionalProperties: false`, so any key not listed here will cause a validation error. | **Always** |
|
|
33
|
+
| `locales/ja.json` | Complete Japanese translations for all keywords and sentences. | **Always** |
|
|
34
|
+
| `locales/en.json` | English overrides. Only needed when a keyword requires capitalization or special formatting (e.g., `"html elements"` → `"HTML elements"`). | Only if needed |
|
|
35
|
+
|
|
36
|
+
The schema is the source of truth for which keys are valid. If you add a keyword to `ja.json` without adding it to `$schema.json`, the locale file will fail schema validation.
|
|
37
|
+
|
|
38
|
+
## Adding a Keyword
|
|
39
|
+
|
|
40
|
+
Keywords are single words or short phrases used as building blocks in rule messages. They appear in the `keywords` section of locale files.
|
|
41
|
+
|
|
42
|
+
### Steps
|
|
43
|
+
|
|
44
|
+
1. **Add to `ja.json`** under `keywords` in alphabetical order:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"keywords": {
|
|
49
|
+
"focusable": "フォーカス可能"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- Keys must be lowercase English
|
|
55
|
+
- Values are the Japanese translations
|
|
56
|
+
|
|
57
|
+
2. **Add to `en.json`** under `keywords` only if needed:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"keywords": {
|
|
62
|
+
"html elements": "HTML elements"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Most English keywords do not need an entry because the key itself is used as-is.
|
|
68
|
+
|
|
69
|
+
3. **Add to `$schema.json`** under `keywords.properties`:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"keywords": {
|
|
74
|
+
"properties": {
|
|
75
|
+
"focusable": { "type": "string" }
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
4. **Test**: `yarn test --scope @markuplint/i18n`
|
|
82
|
+
5. **Build**: `yarn build --scope @markuplint/i18n`
|
|
83
|
+
|
|
84
|
+
### Complement Keywords
|
|
85
|
+
|
|
86
|
+
Complement keywords use the `c:` prefix and are resolved when a placeholder has the `:c` flag (e.g., `{0:c}`). They form a predicate that attaches to the preceding subject in Japanese.
|
|
87
|
+
|
|
88
|
+
| Key in locale | Usage in template | Example output (ja) |
|
|
89
|
+
| ---------------------------------------- | -------------------------------------------- | ------------------------------ |
|
|
90
|
+
| `"c:deprecated": "は非推奨です"` | `"{0} is {1:c}"` with keyword `"deprecated"` | `「要素」は非推奨です` |
|
|
91
|
+
| `"c:disallowed": "は許可されていません"` | `"{0} is {1:c}"` with keyword `"disallowed"` | `「属性」は許可されていません` |
|
|
92
|
+
|
|
93
|
+
When adding a complement keyword:
|
|
94
|
+
|
|
95
|
+
1. Add `"c:<word>"` to `ja.json` keywords
|
|
96
|
+
2. Add `"c:<word>"` to `$schema.json` keywords properties
|
|
97
|
+
3. The non-complement version (without `c:`) may also be needed as a separate keyword
|
|
98
|
+
|
|
99
|
+
## Adding a Sentence Template
|
|
100
|
+
|
|
101
|
+
Sentence templates define message patterns with placeholders. They appear in the `sentences` section of locale files.
|
|
102
|
+
|
|
103
|
+
### Steps
|
|
104
|
+
|
|
105
|
+
1. **Design the English template** as the key:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
"{0} conflicts with {1}"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Placeholder syntax:
|
|
112
|
+
- `{0}`, `{1}`, `{2}` — positional placeholders, translated as keywords
|
|
113
|
+
- `{0:c}` — complement flag, resolves to `c:` prefixed keyword in Japanese
|
|
114
|
+
- `{0*}` — no-translate mark, the value is inserted as-is without keyword lookup
|
|
115
|
+
|
|
116
|
+
2. **Add to `ja.json`** under `sentences`:
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"sentences": {
|
|
121
|
+
"{0} conflicts with {1}": "{0}は{1}と競合しています"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Placeholder order may differ from English to produce natural Japanese.
|
|
127
|
+
|
|
128
|
+
3. **Add to `$schema.json`** under `sentences.properties`:
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"sentences": {
|
|
133
|
+
"properties": {
|
|
134
|
+
"{0} conflicts with {1}": { "type": "string" }
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
4. **`en.json` does not need a sentences entry**. The English key itself serves as the template. The translator uses the key directly when no translation is found.
|
|
141
|
+
|
|
142
|
+
5. **Test**: `yarn test --scope @markuplint/i18n`
|
|
143
|
+
|
|
144
|
+
### Placeholder Reordering
|
|
145
|
+
|
|
146
|
+
Japanese word order differs from English. When translating sentence templates, you can freely reorder placeholders:
|
|
147
|
+
|
|
148
|
+
- English: `"{0} is not allowed in {1}"`
|
|
149
|
+
- Japanese: `"{1}に{0}は許可されていません"`
|
|
150
|
+
|
|
151
|
+
The placeholder numbers refer to the arguments passed to the translator, not their position in the string.
|
|
152
|
+
|
|
153
|
+
## Adding a New Language
|
|
154
|
+
|
|
155
|
+
To add support for an entirely new language:
|
|
156
|
+
|
|
157
|
+
### Steps
|
|
158
|
+
|
|
159
|
+
1. **Create `locales/<lang>.json`** using `ja.json` as a template:
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"$schema": "../$schema.json",
|
|
164
|
+
"listFormat": {
|
|
165
|
+
"quoteStart": "\"",
|
|
166
|
+
"quoteEnd": "\"",
|
|
167
|
+
"separator": ", "
|
|
168
|
+
},
|
|
169
|
+
"keywords": {
|
|
170
|
+
"attribute": "<translated>",
|
|
171
|
+
"element": "<translated>"
|
|
172
|
+
},
|
|
173
|
+
"sentences": {
|
|
174
|
+
"{0} is {1}": "<translated template>"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
- `listFormat`: Define the quote characters and separators appropriate for the language
|
|
180
|
+
- `keywords`: Translate all keywords from `ja.json`
|
|
181
|
+
- `sentences`: Translate all sentence templates from `ja.json`
|
|
182
|
+
|
|
183
|
+
2. **Add export entry in `package.json`**:
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"exports": {
|
|
188
|
+
"./locales/<lang>.json": {
|
|
189
|
+
"import": "./locales/<lang>.json",
|
|
190
|
+
"require": "./locales/<lang>.json"
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
3. **`$schema.json` requires no changes** — the schema is shared across all languages.
|
|
197
|
+
|
|
198
|
+
4. **Add test cases** in `src/index.spec.ts` to verify the new locale works correctly with the translator.
|
|
199
|
+
|
|
200
|
+
5. **Test**: `yarn test --scope @markuplint/i18n`
|
|
201
|
+
|
|
202
|
+
## Command Reference
|
|
203
|
+
|
|
204
|
+
| Command | Description |
|
|
205
|
+
| ------------------------------------- | ----------------- |
|
|
206
|
+
| `yarn test --scope @markuplint/i18n` | Run tests |
|
|
207
|
+
| `yarn build --scope @markuplint/i18n` | Build the package |
|
package/esm/translator.d.ts
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
import type { LocaleSet, Primitive, Translator } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a {@link Translator} function bound to the given locale set.
|
|
4
|
+
*
|
|
5
|
+
* The returned translator supports two call signatures:
|
|
6
|
+
* - **Message template**: `t("The {0} is {1}", keyword1, keyword2)` – interpolates keywords into
|
|
7
|
+
* a message template, looking up translations from the locale set's `sentences` and `keywords`.
|
|
8
|
+
* - **List formatting**: `t(["apple", "banana", "cherry"], true)` – formats an array of strings
|
|
9
|
+
* into a human-readable list (e.g. `"apple", "banana" and "cherry"`).
|
|
10
|
+
*
|
|
11
|
+
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
12
|
+
* @returns A translator function for producing localized messages
|
|
13
|
+
*/
|
|
2
14
|
export declare function translator(localeSet?: LocaleSet): Translator;
|
|
3
15
|
/**
|
|
16
|
+
* Creates a tagged template literal translator function.
|
|
17
|
+
*
|
|
18
|
+
* Allows using template literal syntax for translations:
|
|
19
|
+
* ```ts
|
|
20
|
+
* const tt = taggedTemplateTranslator(localeSet);
|
|
21
|
+
* const msg = tt`The ${name} is ${value}`;
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
4
24
|
* @experimental
|
|
25
|
+
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
26
|
+
* @returns A tagged template function that produces localized strings
|
|
5
27
|
*/
|
|
6
28
|
export declare function taggedTemplateTranslator(localeSet?: LocaleSet): (strings: Readonly<TemplateStringsArray>, ...keys: readonly Primitive[]) => string;
|
package/esm/translator.mjs
CHANGED
|
@@ -4,9 +4,20 @@ const defaultListFormat = {
|
|
|
4
4
|
separator: ', ',
|
|
5
5
|
lastSeparator: ' and ',
|
|
6
6
|
};
|
|
7
|
+
/**
|
|
8
|
+
* Creates a {@link Translator} function bound to the given locale set.
|
|
9
|
+
*
|
|
10
|
+
* The returned translator supports two call signatures:
|
|
11
|
+
* - **Message template**: `t("The {0} is {1}", keyword1, keyword2)` – interpolates keywords into
|
|
12
|
+
* a message template, looking up translations from the locale set's `sentences` and `keywords`.
|
|
13
|
+
* - **List formatting**: `t(["apple", "banana", "cherry"], true)` – formats an array of strings
|
|
14
|
+
* into a human-readable list (e.g. `"apple", "banana" and "cherry"`).
|
|
15
|
+
*
|
|
16
|
+
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
17
|
+
* @returns A translator function for producing localized messages
|
|
18
|
+
*/
|
|
7
19
|
export function translator(localeSet) {
|
|
8
20
|
return (messageTmpl, ...keywords) => {
|
|
9
|
-
let message = messageTmpl;
|
|
10
21
|
if (typeof messageTmpl !== 'string') {
|
|
11
22
|
if (messageTmpl.length === 0) {
|
|
12
23
|
return '';
|
|
@@ -36,7 +47,7 @@ export function translator(localeSet) {
|
|
|
36
47
|
messageTmpl = sentence ?? key;
|
|
37
48
|
messageTmpl =
|
|
38
49
|
removeNoTranslateMark(input.toLowerCase()) === messageTmpl ? removeNoTranslateMark(input) : messageTmpl;
|
|
39
|
-
message = messageTmpl.replaceAll(
|
|
50
|
+
const message = messageTmpl.replaceAll(
|
|
40
51
|
// eslint-disable-next-line regexp/strict
|
|
41
52
|
/{(\d+)(?::(c))?}/g, ($0, number, flag) => {
|
|
42
53
|
const num = Number.parseInt(number);
|
|
@@ -54,7 +65,17 @@ export function translator(localeSet) {
|
|
|
54
65
|
};
|
|
55
66
|
}
|
|
56
67
|
/**
|
|
68
|
+
* Creates a tagged template literal translator function.
|
|
69
|
+
*
|
|
70
|
+
* Allows using template literal syntax for translations:
|
|
71
|
+
* ```ts
|
|
72
|
+
* const tt = taggedTemplateTranslator(localeSet);
|
|
73
|
+
* const msg = tt`The ${name} is ${value}`;
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
57
76
|
* @experimental
|
|
77
|
+
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
78
|
+
* @returns A tagged template function that produces localized strings
|
|
58
79
|
*/
|
|
59
80
|
export function taggedTemplateTranslator(localeSet) {
|
|
60
81
|
const t = translator(localeSet);
|
package/esm/types.d.ts
CHANGED
|
@@ -1,21 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A function that translates message templates or formats keyword lists
|
|
3
|
+
* according to a bound locale set.
|
|
4
|
+
*
|
|
5
|
+
* Overloads:
|
|
6
|
+
* 1. Translate a message template with keyword interpolation.
|
|
7
|
+
* 2. Format a list of keywords into a human-readable string.
|
|
8
|
+
* 3. Combined signature accepting either form.
|
|
9
|
+
*/
|
|
1
10
|
export interface Translator {
|
|
11
|
+
/**
|
|
12
|
+
* Translates a message template by interpolating keywords.
|
|
13
|
+
*
|
|
14
|
+
* @param messageTmpl - The message template with `{0}`, `{1}`, ... placeholders
|
|
15
|
+
* @param keywords - Values to substitute into the template
|
|
16
|
+
* @returns The translated, interpolated message string
|
|
17
|
+
*/
|
|
2
18
|
(messageTmpl: string, ...keywords: readonly Primitive[]): string;
|
|
19
|
+
/**
|
|
20
|
+
* Formats a list of keywords into a localized, human-readable string.
|
|
21
|
+
*
|
|
22
|
+
* @param messageTmpl - An array of keywords to format as a list
|
|
23
|
+
* @param useLastSeparator - Whether to use the "last separator" (e.g. " and ") before the final item
|
|
24
|
+
* @returns The formatted list string
|
|
25
|
+
*/
|
|
3
26
|
(messageTmpl: readonly string[], useLastSeparator?: boolean): string;
|
|
27
|
+
/**
|
|
28
|
+
* Combined overload accepting either a message template string or a keyword list.
|
|
29
|
+
*
|
|
30
|
+
* @param messageTmpl - A message template string or an array of keywords
|
|
31
|
+
* @param keywords - Values to substitute (when a string template is provided)
|
|
32
|
+
* @returns The translated or formatted string
|
|
33
|
+
*/
|
|
4
34
|
(messageTmpl: string | readonly string[], ...keywords: readonly Primitive[]): string;
|
|
5
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Configuration for a specific locale, including translations and formatting rules.
|
|
38
|
+
*/
|
|
6
39
|
export type LocaleSet = {
|
|
40
|
+
/** The locale identifier (e.g. `"en"`, `"ja"`) */
|
|
7
41
|
readonly locale: string;
|
|
42
|
+
/** Formatting rules for rendering keyword lists */
|
|
8
43
|
readonly listFormat?: ListFormat;
|
|
44
|
+
/** A dictionary mapping lowercase keywords to their translations */
|
|
9
45
|
readonly keywords?: LocalesKeywords;
|
|
46
|
+
/** A dictionary mapping lowercase sentence templates to their translations */
|
|
10
47
|
readonly sentences?: LocalesKeywords;
|
|
11
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* Formatting rules for rendering a list of items as a human-readable string.
|
|
51
|
+
*/
|
|
12
52
|
export type ListFormat = {
|
|
53
|
+
/** Character(s) placed before each quoted item (e.g. `"`) */
|
|
13
54
|
readonly quoteStart: string;
|
|
55
|
+
/** Character(s) placed after each quoted item (e.g. `"`) */
|
|
14
56
|
readonly quoteEnd: string;
|
|
57
|
+
/** Separator between items (e.g. `", "`) */
|
|
15
58
|
readonly separator: string;
|
|
59
|
+
/** Separator before the last item (e.g. `" and "`); falls back to `separator` if omitted */
|
|
16
60
|
readonly lastSeparator?: string;
|
|
17
61
|
};
|
|
62
|
+
/**
|
|
63
|
+
* A primitive value type used as a keyword in translations.
|
|
64
|
+
*/
|
|
18
65
|
export type Primitive = string | number | boolean;
|
|
66
|
+
/**
|
|
67
|
+
* A dictionary mapping message IDs (lowercase) to their translated strings.
|
|
68
|
+
*/
|
|
19
69
|
export type LocalesKeywords = {
|
|
20
70
|
readonly [messageId: string]: string;
|
|
21
71
|
};
|
package/locales/ja.json
CHANGED
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/i18n",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.7.1",
|
|
4
4
|
"description": "Internationalization for markuplint",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
7
7
|
"license": "MIT",
|
|
8
|
-
"private": false,
|
|
9
8
|
"main": "./cjs/index.js",
|
|
10
9
|
"types": "./cjs/index.d.ts",
|
|
11
10
|
"exports": {
|
|
@@ -32,10 +31,12 @@
|
|
|
32
31
|
"entryPoint": "./src/index.ts"
|
|
33
32
|
},
|
|
34
33
|
"scripts": {
|
|
35
|
-
"build": "yarn build:esm
|
|
34
|
+
"build": "yarn build:esm && yarn build:cjs && node ./esm.mjs",
|
|
36
35
|
"build:esm": "tsc --project tsconfig.build.json",
|
|
37
36
|
"build:cjs": "tsc --project tsconfig.build-cjs.json",
|
|
38
|
-
"clean": "
|
|
37
|
+
"clean": "yarn clean:esm && yarn clean:cjs",
|
|
38
|
+
"clean:esm": "tsc --build --clean tsconfig.build.json",
|
|
39
|
+
"clean:cjs": "tsc --build --clean tsconfig.build-cjs.json"
|
|
39
40
|
},
|
|
40
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "193ee7c1262bbed95424e38efdf1a8e56ff049f4"
|
|
41
42
|
}
|