@markuplint/i18n 5.0.0-rc.2 → 5.0.0-rc.5
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 +2 -1
- package/CHANGELOG.md +22 -0
- package/CLAUDE.md +13 -0
- package/cjs/index.d.ts +22 -0
- package/cjs/index.js +22 -0
- package/cjs/translator.d.ts +5 -5
- package/cjs/translator.js +15 -5
- package/esm/index.d.ts +22 -0
- package/esm/index.mjs +22 -0
- package/esm/translator.d.ts +5 -5
- package/esm/translator.mjs +15 -5
- package/locales/ja.json +2 -1
- package/package.json +3 -3
- package/SKILL.md +0 -73
- package/docs/maintenance.ja.md +0 -208
- package/docs/maintenance.md +0 -208
package/$schema.json
CHANGED
|
@@ -186,13 +186,14 @@
|
|
|
186
186
|
"additionalProperties": false,
|
|
187
187
|
"properties": {
|
|
188
188
|
"{0} {1}": { "type": "string" },
|
|
189
|
+
"{0} {1} has no cells beginning in it": { "type": "string" },
|
|
190
|
+
"{0} {1} have no cells beginning in them": { "type": "string" },
|
|
189
191
|
"{0:c} and {1:c}": { "type": "string" },
|
|
190
192
|
"{0:c} on {1}": { "type": "string" },
|
|
191
193
|
"{0} ({1})": { "type": "string" },
|
|
192
194
|
"{0} according to {1}": { "type": "string" },
|
|
193
195
|
"{0} are causing {1}": { "type": "string" },
|
|
194
196
|
"{0} as {1}": { "type": "string" },
|
|
195
|
-
"{0} associates only {1}": { "type": "string" },
|
|
196
197
|
"{0} behaves the same as {1} if {2}": { "type": "string" },
|
|
197
198
|
"{0} chars": { "type": "string" },
|
|
198
199
|
"{0} contradicts {1}": { "type": "string" },
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,28 @@
|
|
|
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
|
+
# [5.0.0-rc.5](https://github.com/markuplint/markuplint/compare/v5.0.0-rc.4...v5.0.0-rc.5) (2026-08-28)
|
|
7
|
+
|
|
8
|
+
### Code Refactoring
|
|
9
|
+
|
|
10
|
+
- **rules:** redesign v5 rule system — naming, splits, specConformance ([#3989](https://github.com/markuplint/markuplint/issues/3989)) ([e925565](https://github.com/markuplint/markuplint/commit/e925565ce537848d7d1573369723cbce724a841b)), closes [#4](https://github.com/markuplint/markuplint/issues/4) [#aside-conditional-role-mapping-aria-13](https://github.com/markuplint/markuplint/issues/aside-conditional-role-mapping-aria-13)
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
- **rules:** report HTML LS table model errors in table-row-column-alignment ([#3953](https://github.com/markuplint/markuplint/issues/3953)) ([bacdcd6](https://github.com/markuplint/markuplint/commit/bacdcd697f76300153388f5b1cabaa8504f08d1f)), closes [#3916](https://github.com/markuplint/markuplint/issues/3916) [#3915](https://github.com/markuplint/markuplint/issues/3915) [#3916](https://github.com/markuplint/markuplint/issues/3916) [#3915](https://github.com/markuplint/markuplint/issues/3915)
|
|
15
|
+
|
|
16
|
+
### BREAKING CHANGES
|
|
17
|
+
|
|
18
|
+
- **rules:** with no alias coverage.
|
|
19
|
+
|
|
20
|
+
# [5.0.0-rc.4](https://github.com/markuplint/markuplint/compare/v5.0.0-rc.3...v5.0.0-rc.4) (2026-04-19)
|
|
21
|
+
|
|
22
|
+
**Note:** Version bump only for package @markuplint/i18n
|
|
23
|
+
|
|
24
|
+
# [5.0.0-rc.3](https://github.com/markuplint/markuplint/compare/v5.0.0-rc.2...v5.0.0-rc.3) (2026-04-19)
|
|
25
|
+
|
|
26
|
+
**Note:** Version bump only for package @markuplint/i18n
|
|
27
|
+
|
|
6
28
|
# [5.0.0-rc.2](https://github.com/markuplint/markuplint/compare/v5.0.0-rc.1...v5.0.0-rc.2) (2026-04-15)
|
|
7
29
|
|
|
8
30
|
### Features
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @markuplint/i18n
|
|
2
|
+
|
|
3
|
+
Constraints not derivable from code:
|
|
4
|
+
|
|
5
|
+
- `$schema.json` is maintained **by hand** and uses `additionalProperties: false`.
|
|
6
|
+
Every keyword or sentence added to a locale file MUST also be added to
|
|
7
|
+
`$schema.json`, or the locale fails schema validation. Keep the files in sync.
|
|
8
|
+
- `en.json` is intentionally minimal: the English sentence key itself serves as
|
|
9
|
+
the template, so `en.json` only carries entries that need capitalization or
|
|
10
|
+
special formatting. Do NOT mirror every `ja.json` entry into `en.json`.
|
|
11
|
+
|
|
12
|
+
Placeholder syntax (`{0}`, `{0:c}` complement, `{0*}` no-translate) is documented
|
|
13
|
+
in `src/translator.ts` JSDoc.
|
package/cjs/index.d.ts
CHANGED
|
@@ -1,2 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @markuplint/i18n
|
|
3
|
+
*
|
|
4
|
+
* Internationalization for markuplint rule messages.
|
|
5
|
+
*
|
|
6
|
+
* Locale dictionary contract (`locales/*.json` and `$schema.json`):
|
|
7
|
+
* - Sentence template keys are the English sentences themselves, and an untranslated
|
|
8
|
+
* keyword falls back to its own key. Therefore `locales/en.json` needs no `sentences`
|
|
9
|
+
* section and holds only keyword overrides where the lowercase key cannot serve as
|
|
10
|
+
* display text (e.g. `"html elements"` → `"HTML elements"`), since keyword lookup
|
|
11
|
+
* keys are lowercase.
|
|
12
|
+
* - `locales/ja.json` is the reference dictionary: it is expected to translate every
|
|
13
|
+
* keyword and sentence template, and serves as the template for new languages.
|
|
14
|
+
* - `$schema.json` is the source of truth for valid keys. It intentionally declares
|
|
15
|
+
* `additionalProperties: false` so that a keyword or sentence added to a locale file
|
|
16
|
+
* without a matching schema entry fails validation instead of silently never matching.
|
|
17
|
+
* The schema is shared by all locales, so adding a language requires no schema change.
|
|
18
|
+
* - Translated sentence templates may reorder placeholders freely (e.g. `"{0} is not
|
|
19
|
+
* allowed in {1}"` → `"{1}に{0}は許可されていません"`) because placeholder numbers
|
|
20
|
+
* refer to translator argument positions, not to their position in the English
|
|
21
|
+
* template.
|
|
22
|
+
*/
|
|
1
23
|
export { translator } from './translator.js';
|
|
2
24
|
export type { Translator, LocaleSet } from './types.js';
|
package/cjs/index.js
CHANGED
|
@@ -1,4 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module @markuplint/i18n
|
|
4
|
+
*
|
|
5
|
+
* Internationalization for markuplint rule messages.
|
|
6
|
+
*
|
|
7
|
+
* Locale dictionary contract (`locales/*.json` and `$schema.json`):
|
|
8
|
+
* - Sentence template keys are the English sentences themselves, and an untranslated
|
|
9
|
+
* keyword falls back to its own key. Therefore `locales/en.json` needs no `sentences`
|
|
10
|
+
* section and holds only keyword overrides where the lowercase key cannot serve as
|
|
11
|
+
* display text (e.g. `"html elements"` → `"HTML elements"`), since keyword lookup
|
|
12
|
+
* keys are lowercase.
|
|
13
|
+
* - `locales/ja.json` is the reference dictionary: it is expected to translate every
|
|
14
|
+
* keyword and sentence template, and serves as the template for new languages.
|
|
15
|
+
* - `$schema.json` is the source of truth for valid keys. It intentionally declares
|
|
16
|
+
* `additionalProperties: false` so that a keyword or sentence added to a locale file
|
|
17
|
+
* without a matching schema entry fails validation instead of silently never matching.
|
|
18
|
+
* The schema is shared by all locales, so adding a language requires no schema change.
|
|
19
|
+
* - Translated sentence templates may reorder placeholders freely (e.g. `"{0} is not
|
|
20
|
+
* allowed in {1}"` → `"{1}に{0}は許可されていません"`) because placeholder numbers
|
|
21
|
+
* refer to translator argument positions, not to their position in the English
|
|
22
|
+
* template.
|
|
23
|
+
*/
|
|
2
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
25
|
exports.translator = void 0;
|
|
4
26
|
var translator_js_1 = require("./translator.js");
|
package/cjs/translator.d.ts
CHANGED
|
@@ -8,21 +8,21 @@ import type { LocaleSet, Primitive, Translator } from './types.js';
|
|
|
8
8
|
* - **List formatting**: `t(["apple", "banana", "cherry"], true)` – formats an array of strings
|
|
9
9
|
* into a human-readable list (e.g. `"apple", "banana" and "cherry"`).
|
|
10
10
|
*
|
|
11
|
+
* Placeholder flags carry translation intent:
|
|
12
|
+
* - `{0:c}` resolves through a `c:`-prefixed keyword (complement form); see `translateKeyword` below.
|
|
13
|
+
* - `{0*}` inserts the argument verbatim, for dynamic values such as attribute names or
|
|
14
|
+
* user input that must not go through keyword translation.
|
|
15
|
+
*
|
|
11
16
|
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
12
17
|
* @returns A translator function for producing localized messages
|
|
13
18
|
*/
|
|
14
19
|
export declare function translator(localeSet?: LocaleSet): Translator;
|
|
15
20
|
/**
|
|
16
|
-
* Creates a tagged template literal translator function.
|
|
17
|
-
*
|
|
18
|
-
* Allows using template literal syntax for translations:
|
|
19
21
|
* ```ts
|
|
20
22
|
* const tt = taggedTemplateTranslator(localeSet);
|
|
21
23
|
* const msg = tt`The ${name} is ${value}`;
|
|
22
24
|
* ```
|
|
23
25
|
*
|
|
24
26
|
* @experimental
|
|
25
|
-
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
26
|
-
* @returns A tagged template function that produces localized strings
|
|
27
27
|
*/
|
|
28
28
|
export declare function taggedTemplateTranslator(localeSet?: LocaleSet): (strings: Readonly<TemplateStringsArray>, ...keys: readonly Primitive[]) => string;
|
package/cjs/translator.js
CHANGED
|
@@ -17,6 +17,11 @@ const defaultListFormat = {
|
|
|
17
17
|
* - **List formatting**: `t(["apple", "banana", "cherry"], true)` – formats an array of strings
|
|
18
18
|
* into a human-readable list (e.g. `"apple", "banana" and "cherry"`).
|
|
19
19
|
*
|
|
20
|
+
* Placeholder flags carry translation intent:
|
|
21
|
+
* - `{0:c}` resolves through a `c:`-prefixed keyword (complement form); see `translateKeyword` below.
|
|
22
|
+
* - `{0*}` inserts the argument verbatim, for dynamic values such as attribute names or
|
|
23
|
+
* user input that must not go through keyword translation.
|
|
24
|
+
*
|
|
20
25
|
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
21
26
|
* @returns A translator function for producing localized messages
|
|
22
27
|
*/
|
|
@@ -69,17 +74,12 @@ function translator(localeSet) {
|
|
|
69
74
|
};
|
|
70
75
|
}
|
|
71
76
|
/**
|
|
72
|
-
* Creates a tagged template literal translator function.
|
|
73
|
-
*
|
|
74
|
-
* Allows using template literal syntax for translations:
|
|
75
77
|
* ```ts
|
|
76
78
|
* const tt = taggedTemplateTranslator(localeSet);
|
|
77
79
|
* const msg = tt`The ${name} is ${value}`;
|
|
78
80
|
* ```
|
|
79
81
|
*
|
|
80
82
|
* @experimental
|
|
81
|
-
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
82
|
-
* @returns A tagged template function that produces localized strings
|
|
83
83
|
*/
|
|
84
84
|
function taggedTemplateTranslator(localeSet) {
|
|
85
85
|
const t = translator(localeSet);
|
|
@@ -97,6 +97,16 @@ function taggedTemplateTranslator(localeSet) {
|
|
|
97
97
|
return t(template, ...keys);
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Resolves a keyword to its translation in the locale set.
|
|
102
|
+
*
|
|
103
|
+
* When the `c` flag is given (from a `{n:c}` placeholder), the lookup tries the
|
|
104
|
+
* `c:`-prefixed dictionary entry first. Complement (`c:`) keywords exist for languages
|
|
105
|
+
* such as Japanese where the translation must be a predicate that attaches to the
|
|
106
|
+
* preceding subject (e.g. `c:deprecated` → 「は非推奨です」, yielding 「〇〇は非推奨です」),
|
|
107
|
+
* which cannot be produced from the plain keyword translation. The plain keyword
|
|
108
|
+
* (without `c:`) may still exist as a separate dictionary entry for non-complement use.
|
|
109
|
+
*/
|
|
100
110
|
function translateKeyword(keyword, flag, localeSet) {
|
|
101
111
|
// No translate
|
|
102
112
|
if (/^%[^%]+%$/.test(keyword)) {
|
package/esm/index.d.ts
CHANGED
|
@@ -1,2 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @markuplint/i18n
|
|
3
|
+
*
|
|
4
|
+
* Internationalization for markuplint rule messages.
|
|
5
|
+
*
|
|
6
|
+
* Locale dictionary contract (`locales/*.json` and `$schema.json`):
|
|
7
|
+
* - Sentence template keys are the English sentences themselves, and an untranslated
|
|
8
|
+
* keyword falls back to its own key. Therefore `locales/en.json` needs no `sentences`
|
|
9
|
+
* section and holds only keyword overrides where the lowercase key cannot serve as
|
|
10
|
+
* display text (e.g. `"html elements"` → `"HTML elements"`), since keyword lookup
|
|
11
|
+
* keys are lowercase.
|
|
12
|
+
* - `locales/ja.json` is the reference dictionary: it is expected to translate every
|
|
13
|
+
* keyword and sentence template, and serves as the template for new languages.
|
|
14
|
+
* - `$schema.json` is the source of truth for valid keys. It intentionally declares
|
|
15
|
+
* `additionalProperties: false` so that a keyword or sentence added to a locale file
|
|
16
|
+
* without a matching schema entry fails validation instead of silently never matching.
|
|
17
|
+
* The schema is shared by all locales, so adding a language requires no schema change.
|
|
18
|
+
* - Translated sentence templates may reorder placeholders freely (e.g. `"{0} is not
|
|
19
|
+
* allowed in {1}"` → `"{1}に{0}は許可されていません"`) because placeholder numbers
|
|
20
|
+
* refer to translator argument positions, not to their position in the English
|
|
21
|
+
* template.
|
|
22
|
+
*/
|
|
1
23
|
export { translator } from './translator.js';
|
|
2
24
|
export type { Translator, LocaleSet } from './types.js';
|
package/esm/index.mjs
CHANGED
|
@@ -1 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @markuplint/i18n
|
|
3
|
+
*
|
|
4
|
+
* Internationalization for markuplint rule messages.
|
|
5
|
+
*
|
|
6
|
+
* Locale dictionary contract (`locales/*.mjson` and `$schema.mjson`):
|
|
7
|
+
* - Sentence template keys are the English sentences themselves, and an untranslated
|
|
8
|
+
* keyword falls back to its own key. Therefore `locales/en.mjson` needs no `sentences`
|
|
9
|
+
* section and holds only keyword overrides where the lowercase key cannot serve as
|
|
10
|
+
* display text (e.g. `"html elements"` → `"HTML elements"`), since keyword lookup
|
|
11
|
+
* keys are lowercase.
|
|
12
|
+
* - `locales/ja.mjson` is the reference dictionary: it is expected to translate every
|
|
13
|
+
* keyword and sentence template, and serves as the template for new languages.
|
|
14
|
+
* - `$schema.mjson` is the source of truth for valid keys. It intentionally declares
|
|
15
|
+
* `additionalProperties: false` so that a keyword or sentence added to a locale file
|
|
16
|
+
* without a matching schema entry fails validation instead of silently never matching.
|
|
17
|
+
* The schema is shared by all locales, so adding a language requires no schema change.
|
|
18
|
+
* - Translated sentence templates may reorder placeholders freely (e.g. `"{0} is not
|
|
19
|
+
* allowed in {1}"` → `"{1}に{0}は許可されていません"`) because placeholder numbers
|
|
20
|
+
* refer to translator argument positions, not to their position in the English
|
|
21
|
+
* template.
|
|
22
|
+
*/
|
|
1
23
|
export { translator } from './translator.mjs';
|
package/esm/translator.d.ts
CHANGED
|
@@ -8,21 +8,21 @@ import type { LocaleSet, Primitive, Translator } from './types.js';
|
|
|
8
8
|
* - **List formatting**: `t(["apple", "banana", "cherry"], true)` – formats an array of strings
|
|
9
9
|
* into a human-readable list (e.g. `"apple", "banana" and "cherry"`).
|
|
10
10
|
*
|
|
11
|
+
* Placeholder flags carry translation intent:
|
|
12
|
+
* - `{0:c}` resolves through a `c:`-prefixed keyword (complement form); see `translateKeyword` below.
|
|
13
|
+
* - `{0*}` inserts the argument verbatim, for dynamic values such as attribute names or
|
|
14
|
+
* user input that must not go through keyword translation.
|
|
15
|
+
*
|
|
11
16
|
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
12
17
|
* @returns A translator function for producing localized messages
|
|
13
18
|
*/
|
|
14
19
|
export declare function translator(localeSet?: LocaleSet): Translator;
|
|
15
20
|
/**
|
|
16
|
-
* Creates a tagged template literal translator function.
|
|
17
|
-
*
|
|
18
|
-
* Allows using template literal syntax for translations:
|
|
19
21
|
* ```ts
|
|
20
22
|
* const tt = taggedTemplateTranslator(localeSet);
|
|
21
23
|
* const msg = tt`The ${name} is ${value}`;
|
|
22
24
|
* ```
|
|
23
25
|
*
|
|
24
26
|
* @experimental
|
|
25
|
-
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
26
|
-
* @returns A tagged template function that produces localized strings
|
|
27
27
|
*/
|
|
28
28
|
export declare function taggedTemplateTranslator(localeSet?: LocaleSet): (strings: Readonly<TemplateStringsArray>, ...keys: readonly Primitive[]) => string;
|
package/esm/translator.mjs
CHANGED
|
@@ -13,6 +13,11 @@ const defaultListFormat = {
|
|
|
13
13
|
* - **List formatting**: `t(["apple", "banana", "cherry"], true)` – formats an array of strings
|
|
14
14
|
* into a human-readable list (e.g. `"apple", "banana" and "cherry"`).
|
|
15
15
|
*
|
|
16
|
+
* Placeholder flags carry translation intent:
|
|
17
|
+
* - `{0:c}` resolves through a `c:`-prefixed keyword (complement form); see `translateKeyword` below.
|
|
18
|
+
* - `{0*}` inserts the argument verbatim, for dynamic values such as attribute names or
|
|
19
|
+
* user input that must not go through keyword translation.
|
|
20
|
+
*
|
|
16
21
|
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
17
22
|
* @returns A translator function for producing localized messages
|
|
18
23
|
*/
|
|
@@ -65,17 +70,12 @@ export function translator(localeSet) {
|
|
|
65
70
|
};
|
|
66
71
|
}
|
|
67
72
|
/**
|
|
68
|
-
* Creates a tagged template literal translator function.
|
|
69
|
-
*
|
|
70
|
-
* Allows using template literal syntax for translations:
|
|
71
73
|
* ```ts
|
|
72
74
|
* const tt = taggedTemplateTranslator(localeSet);
|
|
73
75
|
* const msg = tt`The ${name} is ${value}`;
|
|
74
76
|
* ```
|
|
75
77
|
*
|
|
76
78
|
* @experimental
|
|
77
|
-
* @param localeSet - The locale configuration providing translations and formatting rules
|
|
78
|
-
* @returns A tagged template function that produces localized strings
|
|
79
79
|
*/
|
|
80
80
|
export function taggedTemplateTranslator(localeSet) {
|
|
81
81
|
const t = translator(localeSet);
|
|
@@ -93,6 +93,16 @@ export function taggedTemplateTranslator(localeSet) {
|
|
|
93
93
|
return t(template, ...keys);
|
|
94
94
|
};
|
|
95
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Resolves a keyword to its translation in the locale set.
|
|
98
|
+
*
|
|
99
|
+
* When the `c` flag is given (from a `{n:c}` placeholder), the lookup tries the
|
|
100
|
+
* `c:`-prefixed dictionary entry first. Complement (`c:`) keywords exist for languages
|
|
101
|
+
* such as Japanese where the translation must be a predicate that attaches to the
|
|
102
|
+
* preceding subject (e.g. `c:deprecated` → 「は非推奨です」, yielding 「〇〇は非推奨です」),
|
|
103
|
+
* which cannot be produced from the plain keyword translation. The plain keyword
|
|
104
|
+
* (without `c:`) may still exist as a separate dictionary entry for non-complement use.
|
|
105
|
+
*/
|
|
96
106
|
function translateKeyword(keyword, flag, localeSet) {
|
|
97
107
|
// No translate
|
|
98
108
|
if (/^%[^%]+%$/.test(keyword)) {
|
package/locales/ja.json
CHANGED
|
@@ -170,13 +170,14 @@
|
|
|
170
170
|
},
|
|
171
171
|
"sentences": {
|
|
172
172
|
"{0} {1}": "{0}{1}",
|
|
173
|
+
"{0} {1} has no cells beginning in it": "{0}つの{1}に開始するセルがありません",
|
|
174
|
+
"{0} {1} have no cells beginning in them": "{0}つの{1}に開始するセルがありません",
|
|
173
175
|
"{0:c} and {1:c}": "{0}且つ、{1}",
|
|
174
176
|
"{0:c} on {1}": "{1}では、{0:c}",
|
|
175
177
|
"{0} ({1})": "{0}({1})",
|
|
176
178
|
"{0} according to {1}": "{1}において、{0}",
|
|
177
179
|
"{0} are causing {1}": "{0}が{1}を引き起こしています",
|
|
178
180
|
"{0} as {1}": "{1}として{0}",
|
|
179
|
-
"{0} associates only {1}": "{0}は{1}だけを関連付けます",
|
|
180
181
|
"{0} behaves the same as {1} if {2}": "{0}は{2}の場合、{1}と同じ振る舞いをします",
|
|
181
182
|
"{0} chars": "{0}文字",
|
|
182
183
|
"{0} contradicts {1}": "{0}は{1}と矛盾しています",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/i18n",
|
|
3
|
-
"version": "5.0.0-rc.
|
|
3
|
+
"version": "5.0.0-rc.5",
|
|
4
4
|
"description": "Internationalization for markuplint",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"engines": {
|
|
13
|
-
"node": ">=
|
|
13
|
+
"node": ">=24"
|
|
14
14
|
},
|
|
15
15
|
"main": "./cjs/index.js",
|
|
16
16
|
"types": "./cjs/index.d.ts",
|
|
@@ -45,5 +45,5 @@
|
|
|
45
45
|
"clean:esm": "tsc --build --clean tsconfig.build.json",
|
|
46
46
|
"clean:cjs": "tsc --build --clean tsconfig.build-cjs.json"
|
|
47
47
|
},
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "8d87463af2ff3f1b83fb28da20f1819362cf3555"
|
|
49
49
|
}
|
package/SKILL.md
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
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/docs/maintenance.ja.md
DELETED
|
@@ -1,208 +0,0 @@
|
|
|
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
|
-
| `"c:prohibited": "は禁止されています"` | `"{0} is {1:c}"` + キーワード `"prohibited"` | `「属性」は禁止されています` |
|
|
93
|
-
|
|
94
|
-
補語キーワードを追加する際:
|
|
95
|
-
|
|
96
|
-
1. `ja.json` の keywords に `"c:<word>"` を追加
|
|
97
|
-
2. `$schema.json` の keywords properties に `"c:<word>"` を追加
|
|
98
|
-
3. 補語なしバージョン(`c:` なし)も別のキーワードとして必要な場合がある
|
|
99
|
-
|
|
100
|
-
## フレーズを追加する
|
|
101
|
-
|
|
102
|
-
文テンプレートは、プレースホルダー付きのメッセージパターンを定義します。ロケールファイルの `sentences` セクションに定義します。
|
|
103
|
-
|
|
104
|
-
### 手順
|
|
105
|
-
|
|
106
|
-
1. **英語テンプレート**をキーとして設計:
|
|
107
|
-
|
|
108
|
-
```
|
|
109
|
-
"{0} conflicts with {1}"
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
プレースホルダー構文:
|
|
113
|
-
- `{0}`, `{1}`, `{2}` — 位置パラメータ、キーワードとして翻訳される
|
|
114
|
-
- `{0:c}` — 補語フラグ、日本語では `c:` プレフィックスキーワードに解決
|
|
115
|
-
- `{0*}` — 翻訳スキップ、値がキーワード検索なしでそのまま挿入される
|
|
116
|
-
|
|
117
|
-
2. **`ja.json`** の `sentences` に追加:
|
|
118
|
-
|
|
119
|
-
```json
|
|
120
|
-
{
|
|
121
|
-
"sentences": {
|
|
122
|
-
"{0} conflicts with {1}": "{0}は{1}と競合しています"
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
日本語の自然な語順にするため、プレースホルダーの順序は英語と異なってもよい。
|
|
128
|
-
|
|
129
|
-
3. **`$schema.json`** の `sentences.properties` に追加:
|
|
130
|
-
|
|
131
|
-
```json
|
|
132
|
-
{
|
|
133
|
-
"sentences": {
|
|
134
|
-
"properties": {
|
|
135
|
-
"{0} conflicts with {1}": { "type": "string" }
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
4. **`en.json` に sentences エントリは不要**。英語のキー自体がテンプレートとして使用されます。翻訳が見つからない場合、translator はキーをそのまま使います。
|
|
142
|
-
|
|
143
|
-
5. **テスト**: `yarn test --scope @markuplint/i18n`
|
|
144
|
-
|
|
145
|
-
### プレースホルダーの並べ替え
|
|
146
|
-
|
|
147
|
-
日本語と英語では語順が異なります。文テンプレートを翻訳する際、プレースホルダーは自由に並べ替えできます:
|
|
148
|
-
|
|
149
|
-
- 英語: `"{0} is not allowed in {1}"`
|
|
150
|
-
- 日本語: `"{1}に{0}は許可されていません"`
|
|
151
|
-
|
|
152
|
-
プレースホルダーの番号は、translator に渡される引数の位置を指し、文字列内の位置ではありません。
|
|
153
|
-
|
|
154
|
-
## 新しい言語を追加する
|
|
155
|
-
|
|
156
|
-
まったく新しい言語のサポートを追加する手順です。
|
|
157
|
-
|
|
158
|
-
### 手順
|
|
159
|
-
|
|
160
|
-
1. **`locales/<lang>.json`** を `ja.json` をテンプレートにして作成:
|
|
161
|
-
|
|
162
|
-
```json
|
|
163
|
-
{
|
|
164
|
-
"$schema": "../$schema.json",
|
|
165
|
-
"listFormat": {
|
|
166
|
-
"quoteStart": "\"",
|
|
167
|
-
"quoteEnd": "\"",
|
|
168
|
-
"separator": ", "
|
|
169
|
-
},
|
|
170
|
-
"keywords": {
|
|
171
|
-
"attribute": "<翻訳>",
|
|
172
|
-
"element": "<翻訳>"
|
|
173
|
-
},
|
|
174
|
-
"sentences": {
|
|
175
|
-
"{0} is {1}": "<翻訳テンプレート>"
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
- `listFormat`: 言語に適した引用符と区切り文字を定義
|
|
181
|
-
- `keywords`: `ja.json` のすべてのキーワードを翻訳
|
|
182
|
-
- `sentences`: `ja.json` のすべての文テンプレートを翻訳
|
|
183
|
-
|
|
184
|
-
2. **`package.json`** にエクスポートエントリを追加:
|
|
185
|
-
|
|
186
|
-
```json
|
|
187
|
-
{
|
|
188
|
-
"exports": {
|
|
189
|
-
"./locales/<lang>.json": {
|
|
190
|
-
"import": "./locales/<lang>.json",
|
|
191
|
-
"require": "./locales/<lang>.json"
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
3. **`$schema.json` の変更は不要** — スキーマは全言語で共有されます。
|
|
198
|
-
|
|
199
|
-
4. **`src/index.spec.ts`** に新しいロケールのテストケースを追加。
|
|
200
|
-
|
|
201
|
-
5. **テスト**: `yarn test --scope @markuplint/i18n`
|
|
202
|
-
|
|
203
|
-
## コマンドリファレンス
|
|
204
|
-
|
|
205
|
-
| コマンド | 説明 |
|
|
206
|
-
| ------------------------------------- | ------------------ |
|
|
207
|
-
| `yarn test --scope @markuplint/i18n` | テスト実行 |
|
|
208
|
-
| `yarn build --scope @markuplint/i18n` | パッケージのビルド |
|
package/docs/maintenance.md
DELETED
|
@@ -1,208 +0,0 @@
|
|
|
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
|
-
| `"c:prohibited": "は禁止されています"` | `"{0} is {1:c}"` with keyword `"prohibited"` | `「属性」は禁止されています` |
|
|
93
|
-
|
|
94
|
-
When adding a complement keyword:
|
|
95
|
-
|
|
96
|
-
1. Add `"c:<word>"` to `ja.json` keywords
|
|
97
|
-
2. Add `"c:<word>"` to `$schema.json` keywords properties
|
|
98
|
-
3. The non-complement version (without `c:`) may also be needed as a separate keyword
|
|
99
|
-
|
|
100
|
-
## Adding a Sentence Template
|
|
101
|
-
|
|
102
|
-
Sentence templates define message patterns with placeholders. They appear in the `sentences` section of locale files.
|
|
103
|
-
|
|
104
|
-
### Steps
|
|
105
|
-
|
|
106
|
-
1. **Design the English template** as the key:
|
|
107
|
-
|
|
108
|
-
```
|
|
109
|
-
"{0} conflicts with {1}"
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Placeholder syntax:
|
|
113
|
-
- `{0}`, `{1}`, `{2}` — positional placeholders, translated as keywords
|
|
114
|
-
- `{0:c}` — complement flag, resolves to `c:` prefixed keyword in Japanese
|
|
115
|
-
- `{0*}` — no-translate mark, the value is inserted as-is without keyword lookup
|
|
116
|
-
|
|
117
|
-
2. **Add to `ja.json`** under `sentences`:
|
|
118
|
-
|
|
119
|
-
```json
|
|
120
|
-
{
|
|
121
|
-
"sentences": {
|
|
122
|
-
"{0} conflicts with {1}": "{0}は{1}と競合しています"
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Placeholder order may differ from English to produce natural Japanese.
|
|
128
|
-
|
|
129
|
-
3. **Add to `$schema.json`** under `sentences.properties`:
|
|
130
|
-
|
|
131
|
-
```json
|
|
132
|
-
{
|
|
133
|
-
"sentences": {
|
|
134
|
-
"properties": {
|
|
135
|
-
"{0} conflicts with {1}": { "type": "string" }
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
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.
|
|
142
|
-
|
|
143
|
-
5. **Test**: `yarn test --scope @markuplint/i18n`
|
|
144
|
-
|
|
145
|
-
### Placeholder Reordering
|
|
146
|
-
|
|
147
|
-
Japanese word order differs from English. When translating sentence templates, you can freely reorder placeholders:
|
|
148
|
-
|
|
149
|
-
- English: `"{0} is not allowed in {1}"`
|
|
150
|
-
- Japanese: `"{1}に{0}は許可されていません"`
|
|
151
|
-
|
|
152
|
-
The placeholder numbers refer to the arguments passed to the translator, not their position in the string.
|
|
153
|
-
|
|
154
|
-
## Adding a New Language
|
|
155
|
-
|
|
156
|
-
To add support for an entirely new language:
|
|
157
|
-
|
|
158
|
-
### Steps
|
|
159
|
-
|
|
160
|
-
1. **Create `locales/<lang>.json`** using `ja.json` as a template:
|
|
161
|
-
|
|
162
|
-
```json
|
|
163
|
-
{
|
|
164
|
-
"$schema": "../$schema.json",
|
|
165
|
-
"listFormat": {
|
|
166
|
-
"quoteStart": "\"",
|
|
167
|
-
"quoteEnd": "\"",
|
|
168
|
-
"separator": ", "
|
|
169
|
-
},
|
|
170
|
-
"keywords": {
|
|
171
|
-
"attribute": "<translated>",
|
|
172
|
-
"element": "<translated>"
|
|
173
|
-
},
|
|
174
|
-
"sentences": {
|
|
175
|
-
"{0} is {1}": "<translated template>"
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
- `listFormat`: Define the quote characters and separators appropriate for the language
|
|
181
|
-
- `keywords`: Translate all keywords from `ja.json`
|
|
182
|
-
- `sentences`: Translate all sentence templates from `ja.json`
|
|
183
|
-
|
|
184
|
-
2. **Add export entry in `package.json`**:
|
|
185
|
-
|
|
186
|
-
```json
|
|
187
|
-
{
|
|
188
|
-
"exports": {
|
|
189
|
-
"./locales/<lang>.json": {
|
|
190
|
-
"import": "./locales/<lang>.json",
|
|
191
|
-
"require": "./locales/<lang>.json"
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
3. **`$schema.json` requires no changes** — the schema is shared across all languages.
|
|
198
|
-
|
|
199
|
-
4. **Add test cases** in `src/index.spec.ts` to verify the new locale works correctly with the translator.
|
|
200
|
-
|
|
201
|
-
5. **Test**: `yarn test --scope @markuplint/i18n`
|
|
202
|
-
|
|
203
|
-
## Command Reference
|
|
204
|
-
|
|
205
|
-
| Command | Description |
|
|
206
|
-
| ------------------------------------- | ----------------- |
|
|
207
|
-
| `yarn test --scope @markuplint/i18n` | Run tests |
|
|
208
|
-
| `yarn build --scope @markuplint/i18n` | Build the package |
|