@localheroai/cli 0.0.73 → 0.0.74-rc.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/README.md CHANGED
@@ -209,6 +209,53 @@ Both modes automatically commit changes to your repository when running in GitHu
209
209
  npx @localheroai/cli ci --verbose
210
210
  ```
211
211
 
212
+ ### Check
213
+
214
+ ```bash
215
+ npx @localheroai/cli check
216
+ ```
217
+
218
+ Checks your translation files for missing keys, broken placeholders and structure problems. It runs offline on the files in your repo, with no Localhero.ai account, no API key and no `localhero.json` needed. Run it once to see where a repo stands, or in CI to fail a pull request that leaves translations behind.
219
+
220
+ With a `localhero.json` it uses that file's paths, locales and `ignoreKeys`. Without one it finds the locale folder the way `init` does and reads the languages from file and folder names. The source language is the first of: `--source`, a gettext catalog whose `msgstr` are untranslated, a `.pot` template, `en` and the language with the most keys. `check` prints what it picked and says so when it guessed. A language only counts as a target when one of its files matches a source file. That leaves out vendored translations such as rails-i18n.
221
+
222
+ For each target locale it reports:
223
+
224
+ - **Missing keys**: in the source but absent or `null` in the target. Without a config, a source file the language has no file for is listed as not checked instead of counting all its keys as missing.
225
+ - **Placeholder mismatches**: a placeholder the translation drops or adds. Covers Rails `%{name}` and `%<name>s`, printf (`%s`, `%d`, positional `%1$s`), i18next `{{name}}`, ICU `{name}` and Python `%(name)s`. Translators may reorder positional arguments. Date formats (`%b %d`) and literal percent signs are not compared.
226
+ - **Placeholder hints**: a `zero`, `one` or `two` form that leaves out a placeholder, like `"%{count} language"` → `"1 språk"`. That is often correct. Hints never fail the run. A `few`, `many` or `other` form that drops a placeholder is a mismatch.
227
+ - **Missing plural categories**: a Rails plural group without the forms its language needs, like Polish with only `one` and `other`. Rails falls back to `other` without raising an error.
228
+ - **Structure mismatches**: a string in the source that is a map or array in the target, or a plural group collapsed to one string.
229
+ - **Conflicting and duplicate keys**: a key defined with different values in several YAML files of one locale, or twice in the same file. Rails keeps one of the values and says nothing. Gettext domains, i18next namespaces and multi-language files are separate namespaces and are not compared with each other.
230
+ - **Orphan keys**: in a target but in no source file. They are warnings only. Often they are framework translations the source never had.
231
+ - **Empty and identical values**: an empty target string fails like a missing key. A target identical to its source is a hint, as short words and names are often the same across languages.
232
+
233
+ #### Options
234
+
235
+ **`--source <locale>`**: The source language. Defaults to the one in `localhero.json`, or the detected one without it.
236
+
237
+ **`--locales <codes>`**: Comma-separated target locales to check. Defaults to the configured output locales, or every matching language found without a config.
238
+
239
+ **`--path <dir>`**: The locale folder to scan when there is no `localhero.json`. Use it for layouts the detection misses.
240
+
241
+ **`--pattern <glob>`**: The file pattern inside `--path`. Defaults to `**/*.{json,yml,yaml,po,pot}`.
242
+
243
+ **`--json`**: Prints the full report as JSON on stdout and nothing else: every finding, the files loaded per locale, files that could not be parsed and what was detected without a config. Key names stay stable between releases.
244
+
245
+ **`--all`**: Prints every finding instead of the first 10 per category.
246
+
247
+ **`--fail-on <mode>`**: When to exit 1. `missing` (default) fails on missing or empty keys. `placeholders` fails on placeholder mismatches. `any` fails on every finding except hints, orphan keys and files not checked. `none` never fails. A file that cannot be parsed fails every mode except `none`.
248
+
249
+ **`--format github`**: Prints GitHub Actions annotations instead of the report: `::error` for problems, `::warning` for orphan and duplicate keys, `::notice` for hints. At most 50, followed by a count of the rest. Annotations point at files, not lines.
250
+
251
+ In CI, pass `--source` so the gate never depends on a guess:
252
+
253
+ ```bash
254
+ npx @localheroai/cli check --source en --format github
255
+ npx @localheroai/cli check --source en --locales sv,de --fail-on any
256
+ npx @localheroai/cli check --json > report.json
257
+ ```
258
+
212
259
  ### Pull / push
213
260
 
214
261
  ```bash
package/dist/cli.js CHANGED
@@ -10,6 +10,7 @@ import { push } from './commands/push.js';
10
10
  import { init } from './commands/init.js';
11
11
  import { translate } from './commands/translate.js';
12
12
  import { ci } from './commands/ci.js';
13
+ import { check } from './commands/check.js';
13
14
  import { clone } from './commands/clone.js';
14
15
  import { glossary } from './commands/glossary.js';
15
16
  import { settings } from './commands/settings.js';
@@ -90,6 +91,18 @@ program
90
91
  .option('-v, --verbose', 'Show detailed progress information')
91
92
  .option('--skip-commit', 'Skip auto-commit (translations still run on backend)')
92
93
  .action(wrapCommandAction((options) => ci(options)));
94
+ program
95
+ .command('check')
96
+ .description('Check translation files for missing keys, broken placeholders and structure issues. Runs offline, no account or localhero.json needed')
97
+ .option('--source <locale>', 'Source locale (default: from localhero.json, else detected)')
98
+ .option('--locales <codes>', 'Comma-separated target locales to check (default: from localhero.json, else every other locale found)')
99
+ .option('--path <dir>', 'Locale folder to scan when there is no localhero.json')
100
+ .option('--pattern <glob>', 'File pattern inside --path (default: **/*.{json,yml,yaml,po,pot})')
101
+ .option('--json', 'Output a machine-readable JSON report on stdout')
102
+ .option('--all', 'Print every finding instead of capping each category')
103
+ .option('--fail-on <mode>', 'Exit non-zero when findings exist: missing (default), placeholders, any, or none', 'missing')
104
+ .option('--format <format>', 'Use "github" for GitHub Actions annotation output')
105
+ .action(wrapCommandAction((options) => check(options)));
93
106
  program
94
107
  .command('pull')
95
108
  .description('Pull updates from Localhero.ai to your local files')
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,451 @@
1
+ import chalk from 'chalk';
2
+ import { configService } from '../utils/config.js';
3
+ import { findTranslationFiles, parseFile, flattenTranslations, extractLocaleFromPath } from '../utils/files.js';
4
+ import { findDuplicateYamlKeys, dedupeYaml } from '../utils/yaml-duplicates.js';
5
+ import { findMissingTranslationsByLocale, findTargetFile, processTargetContent } from '../utils/translation-utils.js';
6
+ import { createIgnoreMatcher, filterKeys } from '../utils/ignore-keys.js';
7
+ import { detectCheckConfig, defaultConfigDetectionDeps } from '../utils/check-config.js';
8
+ import { findOrphanKeys, findPlaceholderMismatches, findStructureMismatches, findPluralShapeMismatches, findPluralizedFlatKeys, findMissingPluralCategories, usedPluralCategories, findEmptyAndIdentical, findConflictingKeys, toStringValue } from '../utils/check-utils.js';
9
+ const FAIL_ON_MODES = ['missing', 'placeholders', 'any', 'none'];
10
+ const FORMATS = ['github'];
11
+ const defaultDeps = {
12
+ console,
13
+ configUtils: configService,
14
+ fileUtils: { findTranslationFiles },
15
+ projectDetection: { detectProjectType: defaultConfigDetectionDeps.detectProjectType },
16
+ fsUtils: { listFiles: defaultConfigDetectionDeps.listFiles, readFile: defaultConfigDetectionDeps.readFile }
17
+ };
18
+ const DUPLICATE_KEY_ERROR = 'Map keys must be unique';
19
+ // The CLI's YAML parser rejects a repeated key that Rails accepts (last value
20
+ // wins), so such files are reparsed here and the repeat becomes a finding.
21
+ async function recoverDuplicateKeyFiles(failures, knownLocales, config, readFile) {
22
+ const recovered = { files: [], duplicates: [] };
23
+ for (const failure of failures) {
24
+ const format = failure.path.split('.').pop() ?? '';
25
+ if (!['yml', 'yaml'].includes(format) || !String(failure.error).includes(DUPLICATE_KEY_ERROR))
26
+ continue;
27
+ let locale;
28
+ try {
29
+ locale = extractLocaleFromPath(failure.path, config.translationFiles.localeRegex, knownLocales);
30
+ }
31
+ catch {
32
+ continue;
33
+ }
34
+ const raw = await readFile(failure.path);
35
+ recovered.files.push({ path: failure.path, format, locale, content: Buffer.from(dedupeYaml(raw)).toString('base64') });
36
+ for (const duplicate of findDuplicateYamlKeys(raw, locale)) {
37
+ recovered.duplicates.push({ locale, path: failure.path, ...duplicate });
38
+ }
39
+ }
40
+ return recovered;
41
+ }
42
+ function decode(file, sourceLocale) {
43
+ if (!file.content)
44
+ return {};
45
+ const raw = Buffer.from(file.content, 'base64').toString('utf8');
46
+ return parseFile(raw, file.format, file.path, { sourceLanguage: sourceLocale, currentLanguage: file.locale });
47
+ }
48
+ function sourceKeysFor(sourceFile, sourceLocale) {
49
+ const parsed = decode(sourceFile, sourceLocale);
50
+ const wrapper = parsed[sourceLocale];
51
+ const tree = wrapper && typeof wrapper === 'object' && !Array.isArray(wrapper) ? wrapper : parsed;
52
+ return flattenTranslations(tree, '', sourceFile.format);
53
+ }
54
+ function isYaml(file) {
55
+ return file.format === 'yml' || file.format === 'yaml';
56
+ }
57
+ function targetKeysFor(targetFiles, targetLocale, sourceFile, sourceLocale) {
58
+ const targetFile = findTargetFile(targetFiles, targetLocale, sourceFile, sourceLocale);
59
+ if (!targetFile)
60
+ return { keys: {}, path: '' };
61
+ return { keys: keysOf(targetFile, targetLocale, sourceLocale), path: targetFile.path };
62
+ }
63
+ function keysOf(targetFile, targetLocale, sourceLocale) {
64
+ return processTargetContent(decode(targetFile, sourceLocale), targetLocale, targetFile.format);
65
+ }
66
+ function failedResult(sourceLocale = '') {
67
+ return {
68
+ aborted: true,
69
+ exitCode: 1,
70
+ reports: [],
71
+ sourceLocale,
72
+ sourceFiles: [],
73
+ keyCount: 0,
74
+ parseFailures: [],
75
+ detected: null
76
+ };
77
+ }
78
+ const SOURCE_REASONS = {
79
+ option: 'from --source',
80
+ gettext: 'its catalog is untranslated',
81
+ template: 'from the .pot template',
82
+ en: 'en is present',
83
+ guessed: 'guessed from the most keys'
84
+ };
85
+ function printDetected(con, detected, targetCount) {
86
+ const where = detected.paths.map((dir) => `${dir}${detected.pattern}`).join(', ');
87
+ if (targetCount === 0) {
88
+ con.log(chalk.blue(`ℹ No localhero.json found. Only ${detected.source} found in ${where}, so there is nothing to compare.`));
89
+ return;
90
+ }
91
+ con.log(chalk.blue(`ℹ No localhero.json found. Checking ${where}, source ${detected.source} (${SOURCE_REASONS[detected.reason]}).`));
92
+ if (detected.excluded.length > 0) {
93
+ con.log(chalk.blue(`ℹ Skipped ${detected.excluded.join(', ')}: no file matches a source file. Include them with --locales.`));
94
+ }
95
+ if (detected.reason === 'guessed') {
96
+ con.log(chalk.yellow(`⚠ ${detected.source} is a guess. If your source language is another one, pass --source <locale>.`));
97
+ }
98
+ }
99
+ function parseLocales(value) {
100
+ return value ? value.split(',').map((l) => l.trim()).filter(Boolean) : [];
101
+ }
102
+ function invalidOption(options) {
103
+ if (options.failOn && !FAIL_ON_MODES.includes(options.failOn)) {
104
+ return `Invalid --fail-on "${options.failOn}". Use one of: ${FAIL_ON_MODES.join(', ')}.`;
105
+ }
106
+ if (options.format && !FORMATS.includes(options.format)) {
107
+ return `Invalid --format "${options.format}". Use one of: ${FORMATS.join(', ')}.`;
108
+ }
109
+ return null;
110
+ }
111
+ function withPath(findings, path) {
112
+ return findings.map((finding) => ({ ...finding, path }));
113
+ }
114
+ function missingCount(report) {
115
+ return report.missing.length + report.empty.length;
116
+ }
117
+ function isAtOrUnder(key, parents) {
118
+ for (let end = key.length; end !== -1; end = key.lastIndexOf('.', end - 1)) {
119
+ if (parents.has(key.slice(0, end)))
120
+ return true;
121
+ }
122
+ return false;
123
+ }
124
+ function reshapedKeysBetween(sourceKeys, targetKeys) {
125
+ return [
126
+ ...findStructureMismatches(sourceKeys, targetKeys).map((f) => f.key),
127
+ ...findPluralShapeMismatches(sourceKeys, targetKeys).map((f) => f.key),
128
+ ...findPluralizedFlatKeys(sourceKeys, targetKeys)
129
+ ];
130
+ }
131
+ export async function runCheck(options = {}, deps = defaultDeps) {
132
+ const { console, configUtils, fileUtils, projectDetection, fsUtils } = deps;
133
+ const optionError = invalidOption(options);
134
+ if (optionError) {
135
+ console.error(chalk.red(`\n✖ ${optionError}\n`));
136
+ return failedResult();
137
+ }
138
+ const requestedLocales = parseLocales(options.locales);
139
+ let config = await configUtils.getProjectConfig();
140
+ let detected = null;
141
+ if (!config) {
142
+ const detection = await detectCheckConfig({ source: options.source, locales: requestedLocales, path: options.path, pattern: options.pattern }, { ...projectDetection, ...fsUtils });
143
+ if (!detection) {
144
+ console.error(chalk.red('\n✖ No translation files found. Run check from your project root, or point it at your locale folder with --path <dir>.\n'));
145
+ return failedResult();
146
+ }
147
+ ({ config, detected } = detection);
148
+ }
149
+ if (!config.translationFiles?.paths) {
150
+ console.error(chalk.red('\n✖ Invalid configuration: missing translationFiles.paths. Please run `npx @localheroai/cli init` to set up your configuration.\n'));
151
+ return failedResult();
152
+ }
153
+ const sourceLocale = options.source || config.sourceLocale;
154
+ const targetLocales = options.locales ? requestedLocales : config.outputLocales || [];
155
+ const result = await fileUtils.findTranslationFiles(config, {
156
+ returnFullResult: true,
157
+ sourceLocale,
158
+ targetLocales,
159
+ ...(options.json ? { logger: { log: console.error } } : {})
160
+ });
161
+ const discovered = result;
162
+ const recovered = await recoverDuplicateKeyFiles(discovered.parseFailures ?? [], [sourceLocale, ...targetLocales], config, fsUtils.readFile);
163
+ const recoveredPaths = new Set(recovered.files.map((f) => f.path));
164
+ const parseFailures = (discovered.parseFailures ?? []).filter((f) => !recoveredPaths.has(f.path));
165
+ const allFiles = [...discovered.allFiles, ...recovered.files];
166
+ const sourceFiles = [...discovered.sourceFiles, ...recovered.files.filter((f) => f.locale === sourceLocale)];
167
+ const targetFilesByLocale = { ...discovered.targetFilesByLocale };
168
+ for (const file of recovered.files.filter((f) => f.locale !== sourceLocale)) {
169
+ targetFilesByLocale[file.locale] = [...(targetFilesByLocale[file.locale] ?? []), file];
170
+ }
171
+ const filesFor = (locale) => (targetFilesByLocale[locale] || []).map((f) => f.path);
172
+ if (!options.json && !options.format) {
173
+ if (detected)
174
+ printDetected(console, detected, targetLocales.length);
175
+ console.log(chalk.blue(`ℹ Source locale: ${sourceLocale} (${sourceFiles.map((f) => f.path).join(', ') || 'no source files found'})`));
176
+ if (targetLocales.length === 0 && !detected)
177
+ console.log(chalk.blue('ℹ Target locales: none configured'));
178
+ for (const locale of targetLocales) {
179
+ console.log(chalk.blue(`ℹ ${locale}: ${filesFor(locale).join(', ') || 'no files found'}`));
180
+ }
181
+ }
182
+ if (parseFailures.length > 0 && !options.json) {
183
+ console.error(chalk.red(`\n✖ ${parseFailures.length} translation file(s) could not be parsed and were skipped:`));
184
+ for (const failure of parseFailures) {
185
+ console.error(chalk.red(` - ${failure.path}: ${failure.error}`));
186
+ }
187
+ }
188
+ if (!allFiles || allFiles.length === 0) {
189
+ console.error(chalk.red('\n✖ No translation files found in the specified paths.\n'));
190
+ return failedResult(sourceLocale);
191
+ }
192
+ const ignoreMatcher = createIgnoreMatcher(config.translationFiles?.ignoreKeys ?? []);
193
+ const withoutIgnored = (keys) => filterKeys(keys, ignoreMatcher).kept;
194
+ const localePluralCategories = {};
195
+ for (const locale of targetLocales) {
196
+ const categories = usedPluralCategories(locale);
197
+ if (categories)
198
+ localePluralCategories[locale] = categories;
199
+ }
200
+ const { missing } = findMissingTranslationsByLocale(sourceFiles, targetFilesByLocale, { sourceLocale, outputLocales: targetLocales, localePluralCategories }, false, console, { ignoreMatcher });
201
+ const sourceKeyMaps = sourceFiles.map((file) => ({ file, keys: withoutIgnored(sourceKeysFor(file, sourceLocale)) }));
202
+ const totalSourceKeys = new Set();
203
+ for (const { keys } of sourceKeyMaps) {
204
+ for (const [key, value] of Object.entries(keys)) {
205
+ const text = toStringValue(value);
206
+ if (Array.isArray(value) || (text !== null && text !== ''))
207
+ totalSourceKeys.add(key);
208
+ }
209
+ }
210
+ const allSourceKeys = Object.assign({}, ...sourceKeyMaps.map(({ keys }) => keys));
211
+ const reports = targetLocales.map((locale) => {
212
+ const reshapedKeys = new Set();
213
+ const report = {
214
+ locale,
215
+ files: filesFor(locale),
216
+ keyCount: totalSourceKeys.size,
217
+ missing: [],
218
+ empty: [],
219
+ identical: [],
220
+ placeholderMismatches: [],
221
+ placeholderHints: [],
222
+ missingPluralCategories: [],
223
+ orphans: [],
224
+ structureMismatches: [],
225
+ pluralShapeMismatches: [],
226
+ conflictingKeys: [],
227
+ duplicateKeys: recovered.duplicates
228
+ .filter((d) => d.locale === locale)
229
+ .map(({ key, path, values }) => ({ key, path, values })),
230
+ missingFiles: []
231
+ };
232
+ const targetFiles = targetFilesByLocale[locale] || [];
233
+ const pairedTargetKeys = new Map();
234
+ for (const { file: sourceFile, keys: sourceKeys } of sourceKeyMaps) {
235
+ const { keys: allTargetKeys, path: targetPath } = targetKeysFor(targetFiles, locale, sourceFile, sourceLocale);
236
+ const targetKeys = withoutIgnored(allTargetKeys);
237
+ const { empty, identical } = findEmptyAndIdentical(sourceKeys, targetKeys);
238
+ report.empty.push(...withPath(empty, targetPath));
239
+ report.identical.push(...withPath(identical, targetPath));
240
+ for (const finding of withPath(findPlaceholderMismatches(sourceKeys, targetKeys), targetPath)) {
241
+ (finding.hint ? report.placeholderHints : report.placeholderMismatches).push(finding);
242
+ }
243
+ const structureMismatches = findStructureMismatches(sourceKeys, targetKeys);
244
+ const pluralShapeMismatches = findPluralShapeMismatches(sourceKeys, targetKeys);
245
+ report.structureMismatches.push(...withPath(structureMismatches, targetPath));
246
+ report.pluralShapeMismatches.push(...withPath(pluralShapeMismatches, targetPath));
247
+ for (const { key } of [...structureMismatches, ...pluralShapeMismatches])
248
+ reshapedKeys.add(key);
249
+ for (const key of findPluralizedFlatKeys(sourceKeys, targetKeys))
250
+ reshapedKeys.add(key);
251
+ if (targetPath)
252
+ pairedTargetKeys.set(targetPath, targetKeys);
253
+ report.missingPluralCategories.push(...withPath(findMissingPluralCategories(targetKeys, locale), targetPath));
254
+ }
255
+ // Rails merges every file of a locale, so a target key is an orphan only when no source file has it.
256
+ for (const [targetPath, targetKeys] of pairedTargetKeys) {
257
+ const reshaped = new Set([...reshapedKeys, ...reshapedKeysBetween(allSourceKeys, targetKeys)]);
258
+ const orphans = findOrphanKeys(allSourceKeys, targetKeys).filter((f) => !isAtOrUnder(f.key, reshaped));
259
+ report.orphans.push(...withPath(orphans, targetPath));
260
+ }
261
+ // Only single-language YAML shares one namespace per locale: gettext domains, i18next namespaces
262
+ // and multi-language files (often scoped to one view) are separate.
263
+ report.conflictingKeys = findConflictingKeys(targetFiles.filter((file) => isYaml(file) && !file.multiLanguage).map((file) => ({ path: file.path, keys: withoutIgnored(keysOf(file, locale, sourceLocale)) })));
264
+ const reportedElsewhere = new Set([...reshapedKeys, ...report.empty.map((f) => f.key)]);
265
+ const existingTargets = new Set(filesFor(locale));
266
+ for (const entry of Object.values(missing)) {
267
+ if (entry.locale !== locale)
268
+ continue;
269
+ // Without a config the targets are guessed, so a language that only
270
+ // translates part of the app is not reported missing for the rest.
271
+ if (detected && !existingTargets.has(entry.targetPath)) {
272
+ report.missingFiles.push(entry.path);
273
+ continue;
274
+ }
275
+ for (const key of Object.keys(entry.keys)) {
276
+ if (ignoreMatcher(key) || isAtOrUnder(key, reportedElsewhere))
277
+ continue;
278
+ report.missing.push({ key, path: entry.path, targetPath: entry.targetPath });
279
+ }
280
+ }
281
+ return report;
282
+ });
283
+ const failOn = options.failOn || 'missing';
284
+ const exitCode = shouldFail(reports, failOn) || (parseFailures.length > 0 && failOn !== 'none') ? 1 : 0;
285
+ return {
286
+ aborted: false,
287
+ exitCode,
288
+ reports,
289
+ sourceLocale,
290
+ sourceFiles: sourceFiles.map((f) => f.path),
291
+ keyCount: totalSourceKeys.size,
292
+ parseFailures,
293
+ detected
294
+ };
295
+ }
296
+ function shouldFail(reports, failOn) {
297
+ if (failOn === 'none')
298
+ return false;
299
+ const totalMissing = reports.reduce((sum, r) => sum + missingCount(r), 0);
300
+ const placeholderCount = reports.reduce((sum, r) => sum + r.placeholderMismatches.length, 0);
301
+ if (failOn === 'missing')
302
+ return totalMissing > 0;
303
+ if (failOn === 'placeholders')
304
+ return placeholderCount > 0;
305
+ // Orphans never fail a run: a target-only key is as often an unloaded file or a
306
+ // framework's bundled translations as a real leftover, too unreliable to break CI.
307
+ const structureCount = reports.reduce((sum, r) => sum +
308
+ r.structureMismatches.length +
309
+ r.pluralShapeMismatches.length +
310
+ r.missingPluralCategories.length +
311
+ r.conflictingKeys.length +
312
+ r.duplicateKeys.length, 0);
313
+ return totalMissing > 0 || placeholderCount > 0 || structureCount > 0;
314
+ }
315
+ function truncate(text, max = 60) {
316
+ const oneLine = text.replace(/\s+/g, ' ').trim();
317
+ return oneLine.length > max ? `${oneLine.slice(0, max - 1)}…` : oneLine;
318
+ }
319
+ function printList(con, title, items, render, all, cap = 10) {
320
+ if (items.length === 0)
321
+ return;
322
+ con.log(chalk.bold(`\n${title} (${items.length}):`));
323
+ const shown = all ? items : items.slice(0, cap);
324
+ for (const item of shown)
325
+ con.log(` ${render(item)}`);
326
+ if (!all && items.length > cap)
327
+ con.log(chalk.dim(` ... and ${items.length - cap} more`));
328
+ }
329
+ function printHumanReport(con, reports, keyCount, all) {
330
+ if (reports.length === 0)
331
+ return;
332
+ con.log(chalk.bold('\nLocale Keys Missing Placeholders Orphans Complete'));
333
+ for (const r of reports) {
334
+ const missing = missingCount(r);
335
+ const complete = keyCount === 0 ? 100 : Math.round(((keyCount - missing) / keyCount) * 100);
336
+ con.log(`${r.locale.padEnd(14)}${String(keyCount).padEnd(7)}${String(missing).padEnd(9)}${String(r.placeholderMismatches.length).padEnd(14)}${String(r.orphans.length).padEnd(9)}${complete}%`);
337
+ }
338
+ const totalPlaceholders = reports.reduce((sum, r) => sum + r.placeholderMismatches.length, 0);
339
+ const totalOrphans = reports.reduce((sum, r) => sum + r.orphans.length, 0);
340
+ const totalMissing = reports.reduce((sum, r) => sum + missingCount(r), 0);
341
+ const totalPossible = keyCount * reports.length;
342
+ const overallComplete = totalPossible === 0 ? 100 : Math.round(((totalPossible - totalMissing) / totalPossible) * 100);
343
+ con.log(chalk.bold(`\n${reports.length} locale(s), ${keyCount} keys, ${overallComplete}% complete, ${totalPlaceholders} placeholder mismatches, ${totalOrphans} orphans`));
344
+ for (const r of reports) {
345
+ con.log(chalk.bold(`\n== ${r.locale} ==`));
346
+ printList(con, 'Missing keys', r.missing, (m) => m.key, all);
347
+ printList(con, 'Empty values', r.empty, (m) => `${m.key}: "${truncate(m.source)}" -> ""`, all);
348
+ printList(con, 'Placeholder mismatches', r.placeholderMismatches, (m) => `${m.key}: "${truncate(m.source)}" -> "${truncate(m.target)}"` +
349
+ (m.missingInTarget.length ? ` [missing: ${m.missingInTarget.join(', ')}]` : '') +
350
+ (m.unexpectedInTarget.length ? ` [unexpected: ${m.unexpectedInTarget.join(', ')}]` : ''), all);
351
+ printList(con, 'Placeholder hints (a plural form may leave out a placeholder)', r.placeholderHints, (m) => `${m.key}: "${truncate(m.source)}" -> "${truncate(m.target)}" [omits: ${m.missingInTarget.join(', ')}]`, all);
352
+ printList(con, 'Orphan keys', r.orphans, (m) => `${m.key}: "${truncate(m.target ?? '')}"`, all);
353
+ printList(con, 'Structure mismatches', r.structureMismatches, (m) => `${m.key}: source is ${m.sourceShape}, target is ${m.targetShape}`, all);
354
+ printList(con, 'Plural shape mismatches', r.pluralShapeMismatches, (m) => m.key, all);
355
+ printList(con, 'Missing plural categories (falls back to `other`)', r.missingPluralCategories, (m) => `${m.key}: needs ${m.missing.join(', ')}`, all);
356
+ printList(con, 'Conflicting values (defined differently in several files)', r.conflictingKeys, (m) => `${m.key}: ${m.files.join(', ')}`, all);
357
+ printList(con, 'Duplicate keys (the last value wins)', r.duplicateKeys, (m) => `${m.key}: ${m.values.map((v) => `"${truncate(v, 30)}"`).join(' then ')} in ${m.path}`, all);
358
+ printList(con, `Not checked: no ${r.locale} file for`, r.missingFiles, (m) => m, all);
359
+ printList(con, 'Identical to source (hint)', r.identical, (m) => `${m.key}: "${truncate(m.value)}"`, all);
360
+ }
361
+ }
362
+ function escapeAnnotationData(text) {
363
+ return text.replace(/%/g, '%25').replace(/\r/g, '%0D').replace(/\n/g, '%0A');
364
+ }
365
+ function escapeAnnotationProperty(text) {
366
+ return escapeAnnotationData(text).replace(/:/g, '%3A').replace(/,/g, '%2C');
367
+ }
368
+ // GitHub shows only a handful of annotations per run; thousands just bury the log.
369
+ const MAX_ANNOTATIONS = 50;
370
+ function printGithubAnnotations(con, reports) {
371
+ const lines = [];
372
+ const annotate = (level, file, message) => lines.push(`::${level} file=${escapeAnnotationProperty(file)}::${escapeAnnotationData(message)}`);
373
+ // Parsed locale files carry no line numbers, so annotations are file-level.
374
+ for (const r of reports) {
375
+ for (const m of r.missing) {
376
+ annotate('error', m.targetPath, `Missing translation for "${m.key}" (locale ${r.locale})`);
377
+ }
378
+ for (const m of r.empty) {
379
+ annotate('error', m.path, `Empty translation for "${m.key}" (locale ${r.locale})`);
380
+ }
381
+ for (const m of r.placeholderMismatches) {
382
+ annotate('error', m.path, `Placeholder mismatch for "${m.key}" (locale ${r.locale})`);
383
+ }
384
+ for (const m of r.missingPluralCategories) {
385
+ annotate('error', m.path, `"${m.key}" lacks plural forms ${m.missing.join(', ')} (locale ${r.locale})`);
386
+ }
387
+ for (const m of r.placeholderHints) {
388
+ annotate('notice', m.path, `Plural form omits ${m.missingInTarget.join(', ')} for "${m.key}" (locale ${r.locale})`);
389
+ }
390
+ for (const m of r.orphans) {
391
+ annotate('warning', m.path, `Orphan key "${m.key}" (locale ${r.locale}) no longer in source`);
392
+ }
393
+ for (const m of r.structureMismatches) {
394
+ annotate('error', m.path, `Structure mismatch for "${m.key}" (locale ${r.locale})`);
395
+ }
396
+ for (const m of r.pluralShapeMismatches) {
397
+ annotate('error', m.path, `Plural shape mismatch for "${m.key}" (locale ${r.locale})`);
398
+ }
399
+ for (const m of r.conflictingKeys) {
400
+ annotate('error', m.files[0], `"${m.key}" has different values in ${m.files.join(', ')} (locale ${r.locale})`);
401
+ }
402
+ for (const m of r.duplicateKeys) {
403
+ annotate('warning', m.path, `"${m.key}" is defined ${m.values.length} times; the last value wins (locale ${r.locale})`);
404
+ }
405
+ }
406
+ for (const line of lines.slice(0, MAX_ANNOTATIONS))
407
+ con.log(line);
408
+ if (lines.length > MAX_ANNOTATIONS) {
409
+ con.log(`::warning::${lines.length - MAX_ANNOTATIONS} more findings not shown. Run check --json for the full report.`);
410
+ }
411
+ }
412
+ export async function check(options = {}, deps = defaultDeps) {
413
+ const con = deps.console;
414
+ const { aborted, exitCode, reports, sourceLocale, sourceFiles, keyCount, parseFailures, detected } = await runCheck(options, deps);
415
+ process.exitCode = exitCode;
416
+ if (aborted)
417
+ return;
418
+ if (options.json) {
419
+ con.log(JSON.stringify({
420
+ sourceLocale,
421
+ sourceFiles,
422
+ keyCount,
423
+ parseFailures,
424
+ detected,
425
+ locales: reports.map((r) => ({
426
+ locale: r.locale,
427
+ files: r.files,
428
+ keyCount: r.keyCount,
429
+ missing: r.missing,
430
+ empty: r.empty,
431
+ identical: r.identical,
432
+ placeholderMismatches: r.placeholderMismatches,
433
+ placeholderHints: r.placeholderHints,
434
+ missingPluralCategories: r.missingPluralCategories,
435
+ orphans: r.orphans,
436
+ structureMismatches: r.structureMismatches,
437
+ pluralShapeMismatches: r.pluralShapeMismatches,
438
+ conflictingKeys: r.conflictingKeys,
439
+ duplicateKeys: r.duplicateKeys,
440
+ missingFiles: r.missingFiles
441
+ }))
442
+ }));
443
+ }
444
+ else if (options.format === 'github') {
445
+ printGithubAnnotations(con, reports);
446
+ }
447
+ else {
448
+ printHumanReport(con, reports, keyCount, Boolean(options.all));
449
+ }
450
+ }
451
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"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"}