@katerynakhar/i18n-keeper 0.16.0
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/LICENSE +21 -0
- package/README.md +666 -0
- package/dist/apply.d.ts +66 -0
- package/dist/apply.js +254 -0
- package/dist/apply.js.map +1 -0
- package/dist/check.d.ts +5 -0
- package/dist/check.js +326 -0
- package/dist/check.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +525 -0
- package/dist/cli.js.map +1 -0
- package/dist/formats/error.d.ts +12 -0
- package/dist/formats/error.js +19 -0
- package/dist/formats/error.js.map +1 -0
- package/dist/formats/flatten.d.ts +6 -0
- package/dist/formats/flatten.js +26 -0
- package/dist/formats/flatten.js.map +1 -0
- package/dist/formats/json-write.d.ts +7 -0
- package/dist/formats/json-write.js +55 -0
- package/dist/formats/json-write.js.map +1 -0
- package/dist/formats/json.d.ts +6 -0
- package/dist/formats/json.js +21 -0
- package/dist/formats/json.js.map +1 -0
- package/dist/formats/php-write.d.ts +16 -0
- package/dist/formats/php-write.js +130 -0
- package/dist/formats/php-write.js.map +1 -0
- package/dist/formats/php.d.ts +44 -0
- package/dist/formats/php.js +356 -0
- package/dist/formats/php.js.map +1 -0
- package/dist/formats/po-write.d.ts +3 -0
- package/dist/formats/po-write.js +200 -0
- package/dist/formats/po-write.js.map +1 -0
- package/dist/formats/po.d.ts +30 -0
- package/dist/formats/po.js +202 -0
- package/dist/formats/po.js.map +1 -0
- package/dist/formats/write.d.ts +29 -0
- package/dist/formats/write.js +19 -0
- package/dist/formats/write.js.map +1 -0
- package/dist/formats/yaml-write.d.ts +12 -0
- package/dist/formats/yaml-write.js +42 -0
- package/dist/formats/yaml-write.js.map +1 -0
- package/dist/formats/yaml.d.ts +18 -0
- package/dist/formats/yaml.js +51 -0
- package/dist/formats/yaml.js.map +1 -0
- package/dist/glossary.d.ts +38 -0
- package/dist/glossary.js +140 -0
- package/dist/glossary.js.map +1 -0
- package/dist/lengths.d.ts +37 -0
- package/dist/lengths.js +195 -0
- package/dist/lengths.js.map +1 -0
- package/dist/mcp.d.ts +2 -0
- package/dist/mcp.js +374 -0
- package/dist/mcp.js.map +1 -0
- package/dist/memory.d.ts +72 -0
- package/dist/memory.js +162 -0
- package/dist/memory.js.map +1 -0
- package/dist/placeholders.d.ts +15 -0
- package/dist/placeholders.js +103 -0
- package/dist/placeholders.js.map +1 -0
- package/dist/plurals.d.ts +59 -0
- package/dist/plurals.js +280 -0
- package/dist/plurals.js.map +1 -0
- package/dist/report.d.ts +2 -0
- package/dist/report.js +126 -0
- package/dist/report.js.map +1 -0
- package/dist/scan.d.ts +23 -0
- package/dist/scan.js +250 -0
- package/dist/scan.js.map +1 -0
- package/dist/translate.d.ts +93 -0
- package/dist/translate.js +369 -0
- package/dist/translate.js.map +1 -0
- package/dist/types.d.ts +88 -0
- package/dist/types.js +50 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +28 -0
- package/dist/version.js.map +1 -0
- package/package.json +77 -0
- package/src/apply.ts +334 -0
- package/src/check.ts +468 -0
- package/src/cli.ts +637 -0
- package/src/formats/error.ts +19 -0
- package/src/formats/flatten.ts +38 -0
- package/src/formats/json-write.ts +66 -0
- package/src/formats/json.ts +27 -0
- package/src/formats/php-write.ts +146 -0
- package/src/formats/php.ts +414 -0
- package/src/formats/po-write.ts +230 -0
- package/src/formats/po.ts +233 -0
- package/src/formats/write.ts +41 -0
- package/src/formats/yaml-write.ts +53 -0
- package/src/formats/yaml.ts +62 -0
- package/src/glossary.ts +191 -0
- package/src/lengths.ts +214 -0
- package/src/mcp.ts +451 -0
- package/src/memory.ts +227 -0
- package/src/placeholders.ts +123 -0
- package/src/plurals.ts +320 -0
- package/src/report.ts +162 -0
- package/src/scan.ts +280 -0
- package/src/translate.ts +486 -0
- package/src/types.ts +136 -0
- package/src/version.ts +27 -0
package/dist/plurals.js
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLDR plural categories, taken from the ICU data already in the runtime rather
|
|
3
|
+
* than a hand-maintained table: the table would go stale, and this is the same
|
|
4
|
+
* data the application itself will use at runtime.
|
|
5
|
+
*/
|
|
6
|
+
export const CATEGORY_NAMES = ['zero', 'one', 'two', 'few', 'many', 'other'];
|
|
7
|
+
const CATEGORIES = new Set(CATEGORY_NAMES);
|
|
8
|
+
const cache = new Map();
|
|
9
|
+
export function isCategory(name) {
|
|
10
|
+
return CATEGORIES.has(name);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Categories CLDR defines for a locale, or null when we cannot tell.
|
|
14
|
+
*
|
|
15
|
+
* Intl.PluralRules silently falls back to the system locale for tags it does
|
|
16
|
+
* not know — asking for "zz" on a Russian machine reports four categories — so
|
|
17
|
+
* a resolved language subtag that does not match the request means "unknown"
|
|
18
|
+
* rather than a wrong answer.
|
|
19
|
+
*/
|
|
20
|
+
export function categoriesFor(locale) {
|
|
21
|
+
const cached = cache.get(locale);
|
|
22
|
+
if (cached !== undefined)
|
|
23
|
+
return cached;
|
|
24
|
+
const tag = locale.replace(/_/g, '-');
|
|
25
|
+
let result = null;
|
|
26
|
+
try {
|
|
27
|
+
const resolved = new Intl.PluralRules(tag, { type: 'cardinal' }).resolvedOptions();
|
|
28
|
+
const asked = tag.split('-')[0].toLowerCase();
|
|
29
|
+
const got = resolved.locale.split('-')[0].toLowerCase();
|
|
30
|
+
if (asked === got && resolved.pluralCategories.length > 0) {
|
|
31
|
+
result = new Set(resolved.pluralCategories);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
result = null;
|
|
36
|
+
}
|
|
37
|
+
cache.set(locale, result);
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
const PLURAL_INTENT = /\{\s*[\w.$-]+\s*,\s*(?:plural|selectordinal)\b/;
|
|
41
|
+
/** Whether the string is trying to be an ICU plural at all. */
|
|
42
|
+
export function looksLikeIcuPlural(text) {
|
|
43
|
+
return PLURAL_INTENT.test(text);
|
|
44
|
+
}
|
|
45
|
+
class IcuScanner {
|
|
46
|
+
text;
|
|
47
|
+
pos = 0;
|
|
48
|
+
blocks = [];
|
|
49
|
+
constructor(text) {
|
|
50
|
+
this.text = text;
|
|
51
|
+
}
|
|
52
|
+
get done() {
|
|
53
|
+
return this.pos >= this.text.length;
|
|
54
|
+
}
|
|
55
|
+
fail(message) {
|
|
56
|
+
throw new Error(`${message} at offset ${this.pos}`);
|
|
57
|
+
}
|
|
58
|
+
skipWs() {
|
|
59
|
+
while (!this.done && /\s/.test(this.text[this.pos]))
|
|
60
|
+
this.pos++;
|
|
61
|
+
}
|
|
62
|
+
readIdent() {
|
|
63
|
+
const start = this.pos;
|
|
64
|
+
while (!this.done && /[\w.$-]/.test(this.text[this.pos]))
|
|
65
|
+
this.pos++;
|
|
66
|
+
return this.text.slice(start, this.pos);
|
|
67
|
+
}
|
|
68
|
+
/** ICU quoting: '{', '}' and '#' start a literal run; '' is one apostrophe. */
|
|
69
|
+
skipQuote() {
|
|
70
|
+
const next = this.text[this.pos + 1];
|
|
71
|
+
if (next === "'") {
|
|
72
|
+
this.pos += 2;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (next === '{' || next === '}' || next === '#') {
|
|
76
|
+
const close = this.text.indexOf("'", this.pos + 1);
|
|
77
|
+
this.pos = close === -1 ? this.text.length : close + 1;
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
this.pos++;
|
|
81
|
+
}
|
|
82
|
+
/** Consumes a message body; with `nested`, stops after the matching brace. */
|
|
83
|
+
scanMessage(nested) {
|
|
84
|
+
while (!this.done) {
|
|
85
|
+
const ch = this.text[this.pos];
|
|
86
|
+
if (ch === "'") {
|
|
87
|
+
this.skipQuote();
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (ch === '}') {
|
|
91
|
+
if (!nested)
|
|
92
|
+
this.fail('Unexpected }');
|
|
93
|
+
this.pos++;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (ch === '{') {
|
|
97
|
+
this.scanArgument();
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
this.pos++;
|
|
101
|
+
}
|
|
102
|
+
if (nested)
|
|
103
|
+
this.fail('Unclosed {');
|
|
104
|
+
}
|
|
105
|
+
/** Consumes `{...}` of any argument type, starting at the opening brace. */
|
|
106
|
+
scanArgument() {
|
|
107
|
+
this.pos++; // {
|
|
108
|
+
this.skipWs();
|
|
109
|
+
const name = this.readIdent();
|
|
110
|
+
this.skipWs();
|
|
111
|
+
if (this.done)
|
|
112
|
+
this.fail('Unclosed {');
|
|
113
|
+
if (this.text[this.pos] === '}') {
|
|
114
|
+
this.pos++;
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (this.text[this.pos] !== ',')
|
|
118
|
+
this.fail('Expected , or } in argument');
|
|
119
|
+
this.pos++;
|
|
120
|
+
this.skipWs();
|
|
121
|
+
const type = this.readIdent();
|
|
122
|
+
this.skipWs();
|
|
123
|
+
if (this.done)
|
|
124
|
+
this.fail('Unclosed {');
|
|
125
|
+
if (this.text[this.pos] === '}') {
|
|
126
|
+
this.pos++;
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (this.text[this.pos] !== ',')
|
|
130
|
+
this.fail(`Expected , or } after ${type || 'argument type'}`);
|
|
131
|
+
this.pos++;
|
|
132
|
+
if (type === 'plural' || type === 'selectordinal') {
|
|
133
|
+
this.scanPluralBody(name, type);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
this.scanOpaqueBody();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/** For select/number/date: keep the braces balanced, ignore the content. */
|
|
140
|
+
scanOpaqueBody() {
|
|
141
|
+
let depth = 1;
|
|
142
|
+
while (!this.done) {
|
|
143
|
+
const ch = this.text[this.pos];
|
|
144
|
+
if (ch === "'") {
|
|
145
|
+
this.skipQuote();
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (ch === '{')
|
|
149
|
+
depth++;
|
|
150
|
+
if (ch === '}') {
|
|
151
|
+
depth--;
|
|
152
|
+
this.pos++;
|
|
153
|
+
if (depth === 0)
|
|
154
|
+
return;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
this.pos++;
|
|
158
|
+
}
|
|
159
|
+
this.fail('Unclosed {');
|
|
160
|
+
}
|
|
161
|
+
scanPluralBody(arg, type) {
|
|
162
|
+
const block = { arg, type, categories: new Set(), exact: new Set() };
|
|
163
|
+
for (;;) {
|
|
164
|
+
this.skipWs();
|
|
165
|
+
if (this.done)
|
|
166
|
+
this.fail('Unclosed plural');
|
|
167
|
+
if (this.text[this.pos] === '}') {
|
|
168
|
+
this.pos++;
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
if (this.text.startsWith('offset:', this.pos)) {
|
|
172
|
+
this.pos += 'offset:'.length;
|
|
173
|
+
this.skipWs();
|
|
174
|
+
while (!this.done && /[\d.-]/.test(this.text[this.pos]))
|
|
175
|
+
this.pos++;
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (this.text[this.pos] === '=') {
|
|
179
|
+
this.pos++;
|
|
180
|
+
const start = this.pos;
|
|
181
|
+
while (!this.done && /[\d.]/.test(this.text[this.pos]))
|
|
182
|
+
this.pos++;
|
|
183
|
+
if (this.pos === start)
|
|
184
|
+
this.fail('Expected a number after =');
|
|
185
|
+
block.exact.add(`=${this.text.slice(start, this.pos)}`);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
const keyword = this.readIdent();
|
|
189
|
+
if (!keyword)
|
|
190
|
+
this.fail('Expected a plural selector');
|
|
191
|
+
block.categories.add(keyword);
|
|
192
|
+
}
|
|
193
|
+
this.skipWs();
|
|
194
|
+
if (this.text[this.pos] !== '{')
|
|
195
|
+
this.fail('Expected { after a plural selector');
|
|
196
|
+
this.pos++;
|
|
197
|
+
this.scanMessage(true);
|
|
198
|
+
}
|
|
199
|
+
this.blocks.push(block);
|
|
200
|
+
}
|
|
201
|
+
run() {
|
|
202
|
+
this.scanMessage(false);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
export function scanIcu(text) {
|
|
206
|
+
const scanner = new IcuScanner(text);
|
|
207
|
+
try {
|
|
208
|
+
scanner.run();
|
|
209
|
+
return { blocks: scanner.blocks, error: null };
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
return {
|
|
213
|
+
blocks: scanner.blocks,
|
|
214
|
+
// Only meaningful for strings that meant to be ICU; i18next's {{name}}
|
|
215
|
+
// is not ICU and must not be reported as broken ICU.
|
|
216
|
+
error: looksLikeIcuPlural(text) ? (err instanceof Error ? err.message : String(err)) : null,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/** i18next writes item_one; Rails and Symfony nest it as item.one. */
|
|
221
|
+
export function splitPluralSuffix(key) {
|
|
222
|
+
for (const separator of ['_', '.']) {
|
|
223
|
+
const at = key.lastIndexOf(separator);
|
|
224
|
+
if (at <= 0)
|
|
225
|
+
continue;
|
|
226
|
+
const suffix = key.slice(at + 1);
|
|
227
|
+
if (isCategory(suffix))
|
|
228
|
+
return { base: key.slice(0, at), category: suffix, separator };
|
|
229
|
+
}
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Groups keys like item_one / item_other into base -> categories.
|
|
234
|
+
*
|
|
235
|
+
* A group must carry `other`, which every CLDR plural set has. Without that
|
|
236
|
+
* test, Rails' `restrict_dependent_destroy.has_one` / `has_many` — ActiveRecord
|
|
237
|
+
* association names — read as a plural group and were asked to grow the forms
|
|
238
|
+
* their language requires.
|
|
239
|
+
*/
|
|
240
|
+
export function pluralGroups(keys) {
|
|
241
|
+
const groups = new Map();
|
|
242
|
+
for (const key of keys) {
|
|
243
|
+
const split = splitPluralSuffix(key);
|
|
244
|
+
if (!split)
|
|
245
|
+
continue;
|
|
246
|
+
let group = groups.get(split.base);
|
|
247
|
+
if (!group) {
|
|
248
|
+
group = { categories: new Set(), separator: split.separator };
|
|
249
|
+
groups.set(split.base, group);
|
|
250
|
+
}
|
|
251
|
+
group.categories.add(split.category);
|
|
252
|
+
}
|
|
253
|
+
for (const [base, group] of groups) {
|
|
254
|
+
if (!group.categories.has('other'))
|
|
255
|
+
groups.delete(base);
|
|
256
|
+
}
|
|
257
|
+
return groups;
|
|
258
|
+
}
|
|
259
|
+
// ---------------------------------------------------------------------------
|
|
260
|
+
// Laravel pipe selection — deliberately not CLDR
|
|
261
|
+
// ---------------------------------------------------------------------------
|
|
262
|
+
/**
|
|
263
|
+
* Laravel picks a segment by position or by explicit {0} / [1,*] ranges, which
|
|
264
|
+
* is its own mechanism and not CLDR. All we can honestly compare is the segment
|
|
265
|
+
* count, so that is all this reports.
|
|
266
|
+
*/
|
|
267
|
+
export function pipeSegments(text) {
|
|
268
|
+
let count = 1;
|
|
269
|
+
let depth = 0;
|
|
270
|
+
for (const ch of text) {
|
|
271
|
+
if (ch === '{' || ch === '[')
|
|
272
|
+
depth++;
|
|
273
|
+
else if (ch === '}' || ch === ']')
|
|
274
|
+
depth = Math.max(0, depth - 1);
|
|
275
|
+
else if (ch === '|' && depth === 0)
|
|
276
|
+
count++;
|
|
277
|
+
}
|
|
278
|
+
return count;
|
|
279
|
+
}
|
|
280
|
+
//# sourceMappingURL=plurals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plurals.js","sourceRoot":"","sources":["../src/plurals.ts"],"names":[],"mappings":"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"}
|
package/dist/report.d.ts
ADDED
package/dist/report.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { relative } from 'node:path';
|
|
2
|
+
const useColor = process.stdout.isTTY === true && !process.env['NO_COLOR'] && process.env['TERM'] !== 'dumb';
|
|
3
|
+
const paint = (code) => (s) => useColor ? `\u001b[${code}m${s}\u001b[0m` : s;
|
|
4
|
+
const dim = paint('2');
|
|
5
|
+
const bold = paint('1');
|
|
6
|
+
const red = paint('31');
|
|
7
|
+
const yellow = paint('33');
|
|
8
|
+
const green = paint('32');
|
|
9
|
+
function pad(s, width, align = 'left') {
|
|
10
|
+
const gap = ' '.repeat(Math.max(0, width - s.length));
|
|
11
|
+
return align === 'right' ? gap + s : s + gap;
|
|
12
|
+
}
|
|
13
|
+
function colorCoverage(value, text) {
|
|
14
|
+
if (value >= 0.99)
|
|
15
|
+
return green(text);
|
|
16
|
+
if (value >= 0.9)
|
|
17
|
+
return yellow(text);
|
|
18
|
+
return red(text);
|
|
19
|
+
}
|
|
20
|
+
function columns(report) {
|
|
21
|
+
const cols = [
|
|
22
|
+
{ header: 'locale', align: 'left', value: (s) => s.locale },
|
|
23
|
+
{
|
|
24
|
+
header: 'coverage',
|
|
25
|
+
align: 'right',
|
|
26
|
+
value: (s) => `${(s.coverage * 100).toFixed(1)}%`,
|
|
27
|
+
color: (s, text) => colorCoverage(s.coverage, text),
|
|
28
|
+
},
|
|
29
|
+
{ header: 'missing', align: 'right', value: (s) => String(s.missing) },
|
|
30
|
+
{ header: 'orphan', align: 'right', value: (s) => String(s.orphan) },
|
|
31
|
+
];
|
|
32
|
+
// Without a translation memory there is nothing to compare against, so the
|
|
33
|
+
// column would only ever print zeroes.
|
|
34
|
+
if (report.memoryLoaded) {
|
|
35
|
+
cols.push({
|
|
36
|
+
header: 'stale',
|
|
37
|
+
align: 'right',
|
|
38
|
+
value: (s) => String(s.stale),
|
|
39
|
+
color: (s, text) => (s.stale > 0 ? yellow(text) : text),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
cols.push({
|
|
43
|
+
header: 'errors',
|
|
44
|
+
align: 'right',
|
|
45
|
+
value: (s) => String(s.errors),
|
|
46
|
+
color: (s, text) => (s.errors > 0 ? red(text) : text),
|
|
47
|
+
}, {
|
|
48
|
+
header: 'warnings',
|
|
49
|
+
align: 'right',
|
|
50
|
+
value: (s) => String(s.warnings),
|
|
51
|
+
color: (s, text) => (s.warnings > 0 ? yellow(text) : text),
|
|
52
|
+
});
|
|
53
|
+
return cols;
|
|
54
|
+
}
|
|
55
|
+
function renderTable(report) {
|
|
56
|
+
const cols = columns(report);
|
|
57
|
+
const cells = report.stats.map((s) => cols.map((c) => c.value(s)));
|
|
58
|
+
const widths = cols.map((c, i) => Math.max(c.header.length, ...cells.map((row) => (row[i] ?? '').length)));
|
|
59
|
+
const lines = [dim(cols.map((c, i) => pad(c.header, widths[i], c.align)).join(' '))];
|
|
60
|
+
for (const [rowIndex, row] of cells.entries()) {
|
|
61
|
+
const stat = report.stats[rowIndex];
|
|
62
|
+
lines.push(cols
|
|
63
|
+
.map((c, i) => {
|
|
64
|
+
const text = pad(row[i] ?? '', widths[i], c.align);
|
|
65
|
+
return c.color ? c.color(stat, text) : text;
|
|
66
|
+
})
|
|
67
|
+
.join(' '));
|
|
68
|
+
}
|
|
69
|
+
return lines;
|
|
70
|
+
}
|
|
71
|
+
function renderFindings(findings, limit) {
|
|
72
|
+
if (findings.length === 0)
|
|
73
|
+
return [];
|
|
74
|
+
const shown = findings.slice(0, limit);
|
|
75
|
+
const localeWidth = Math.max(...shown.map((f) => f.locale.length));
|
|
76
|
+
const keyWidth = Math.min(36, Math.max(...shown.map((f) => f.key.length)));
|
|
77
|
+
const ruleWidth = Math.max(...shown.map((f) => f.rule.length));
|
|
78
|
+
const lines = [];
|
|
79
|
+
let lastSeverity = '';
|
|
80
|
+
for (const f of shown) {
|
|
81
|
+
if (f.severity !== lastSeverity) {
|
|
82
|
+
lines.push('');
|
|
83
|
+
lines.push(f.severity === 'error' ? red(bold('errors')) : yellow(bold('warnings')));
|
|
84
|
+
lastSeverity = f.severity;
|
|
85
|
+
}
|
|
86
|
+
const key = f.key.length > keyWidth ? `…${f.key.slice(-(keyWidth - 1))}` : f.key;
|
|
87
|
+
lines.push(' ' +
|
|
88
|
+
[pad(f.locale, localeWidth), pad(key, keyWidth), dim(pad(f.rule, ruleWidth)), f.detail].join(' '));
|
|
89
|
+
}
|
|
90
|
+
if (findings.length > shown.length) {
|
|
91
|
+
lines.push(dim(` … ${findings.length - shown.length} more (use --limit)`));
|
|
92
|
+
}
|
|
93
|
+
return lines;
|
|
94
|
+
}
|
|
95
|
+
export function renderReport(report, root, limit) {
|
|
96
|
+
const errors = report.findings.filter((f) => f.severity === 'error').length;
|
|
97
|
+
const warnings = report.findings.length - errors;
|
|
98
|
+
const head = [
|
|
99
|
+
`${bold('i18n check')}`,
|
|
100
|
+
`source: ${bold(report.sourceLocale)}${report.sourceFromMsgid ? dim(' (msgid)') : ''}`,
|
|
101
|
+
`${report.sourceKeys} keys`,
|
|
102
|
+
dim(relative(root, report.localesDir) || report.localesDir),
|
|
103
|
+
];
|
|
104
|
+
if (!report.memoryLoaded)
|
|
105
|
+
head.push(dim('no memory'));
|
|
106
|
+
const lines = [
|
|
107
|
+
head.join(` ${dim('·')} `),
|
|
108
|
+
'',
|
|
109
|
+
...renderTable(report),
|
|
110
|
+
...renderFindings(report.findings, limit),
|
|
111
|
+
'',
|
|
112
|
+
];
|
|
113
|
+
if (report.findings.length === 0) {
|
|
114
|
+
lines.push(green('✓ no issues'));
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
const parts = [];
|
|
118
|
+
if (errors > 0)
|
|
119
|
+
parts.push(red(`${errors} error${errors === 1 ? '' : 's'}`));
|
|
120
|
+
if (warnings > 0)
|
|
121
|
+
parts.push(yellow(`${warnings} warning${warnings === 1 ? '' : 's'}`));
|
|
122
|
+
lines.push(parts.join(dim(' · ')));
|
|
123
|
+
}
|
|
124
|
+
return lines.join('\n');
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
|
package/dist/scan.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type Config, type LocaleBundle } from './types.js';
|
|
2
|
+
export declare class ScanError extends Error {
|
|
3
|
+
}
|
|
4
|
+
/** Finds the directory holding locale files, or throws with the paths it tried. */
|
|
5
|
+
export declare function findLocalesDir(root: string, explicit?: string): string;
|
|
6
|
+
export interface LocaleLayout {
|
|
7
|
+
layout: 'flat' | 'nested';
|
|
8
|
+
locales: string[];
|
|
9
|
+
}
|
|
10
|
+
/** `locales/en.json` is flat; `locales/en/common.json` is nested. */
|
|
11
|
+
export declare function listLocales(dir: string): LocaleLayout;
|
|
12
|
+
/**
|
|
13
|
+
* Whether a bundle's source text comes from msgid rather than from the locale
|
|
14
|
+
* itself. In gettext every catalogue carries the untranslated string, so the
|
|
15
|
+
* locale named as the source only supplies the keys.
|
|
16
|
+
*/
|
|
17
|
+
export declare function sourceIsMsgid(bundle: LocaleBundle): boolean;
|
|
18
|
+
export declare function loadBundle(config: Config, locale: string): LocaleBundle;
|
|
19
|
+
export interface DetectOptions {
|
|
20
|
+
localesDir?: string;
|
|
21
|
+
sourceLocale?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function detectProject(root: string, opts?: DetectOptions): Config;
|