i18next-cli 1.64.1 → 1.64.2

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/dist/cjs/cli.js CHANGED
@@ -37,7 +37,7 @@ const program = new commander.Command();
37
37
  program
38
38
  .name('i18next-cli')
39
39
  .description('A unified, high-performance i18next CLI.')
40
- .version('1.64.1'); // This string is replaced with the actual version at build time by rollup
40
+ .version('1.64.2'); // This string is replaced with the actual version at build time by rollup
41
41
  // new: global config override option
42
42
  program.option('-c, --config <path>', 'Path to i18next-cli config file (overrides detection)');
43
43
  program
@@ -100,20 +100,44 @@ async function runStatus(config, options = {}) {
100
100
  const report = await generateStatusReport(config);
101
101
  spinner.succeed('Analysis complete.');
102
102
  await displayStatusReport(report, config, options);
103
+ // When a specific locale is requested (`status <locale>`), the pass/fail
104
+ // result must reflect THAT locale only — otherwise the displayed summary
105
+ // (which is scoped to the requested locale) can contradict the exit code
106
+ // by failing on an unrelated secondary language. See issue #271.
107
+ const scopedLocale = options.detail && config.locales.includes(options.detail)
108
+ ? options.detail
109
+ : undefined;
103
110
  let hasMissing = false;
104
- for (const [, localeData] of report.locales.entries()) {
105
- if (localeData.totalTranslated < localeData.totalKeys) {
106
- hasMissing = true;
107
- break;
111
+ if (scopedLocale) {
112
+ if (scopedLocale === config.extract.primaryLanguage) {
113
+ // The primary language fails only on absent keys (used in code but
114
+ // missing from the file); empty placeholders are deliberate.
115
+ hasMissing = !!report.primary && report.primary.totalAbsent > 0;
116
+ }
117
+ else {
118
+ const localeData = report.locales.get(scopedLocale);
119
+ hasMissing = !!localeData && localeData.totalTranslated < localeData.totalKeys;
108
120
  }
109
121
  }
110
- // The primary language fails the check only on absent keys (used in code but
111
- // missing from the translation file); empty placeholders are tolerated.
112
- if (!hasMissing && report.primary && report.primary.totalAbsent > 0) {
113
- hasMissing = true;
122
+ else {
123
+ for (const [, localeData] of report.locales.entries()) {
124
+ if (localeData.totalTranslated < localeData.totalKeys) {
125
+ hasMissing = true;
126
+ break;
127
+ }
128
+ }
129
+ // The primary language fails the check only on absent keys (used in code but
130
+ // missing from the translation file); empty placeholders are tolerated.
131
+ if (!hasMissing && report.primary && report.primary.totalAbsent > 0) {
132
+ hasMissing = true;
133
+ }
114
134
  }
115
135
  if (hasMissing) {
116
- spinner.fail('Error: Incomplete translations detected.');
136
+ // Name the locale when the check is scoped so the failure reason is clear
137
+ // (the displayed summary already explains what is missing for it).
138
+ spinner.fail(scopedLocale
139
+ ? `Error: Incomplete translations detected for "${scopedLocale}".`
140
+ : 'Error: Incomplete translations detected.');
117
141
  process.exit(1);
118
142
  }
119
143
  }
package/dist/esm/cli.js CHANGED
@@ -31,7 +31,7 @@ const program = new Command();
31
31
  program
32
32
  .name('i18next-cli')
33
33
  .description('A unified, high-performance i18next CLI.')
34
- .version('1.64.1'); // This string is replaced with the actual version at build time by rollup
34
+ .version('1.64.2'); // This string is replaced with the actual version at build time by rollup
35
35
  // new: global config override option
36
36
  program.option('-c, --config <path>', 'Path to i18next-cli config file (overrides detection)');
37
37
  program
@@ -94,20 +94,44 @@ async function runStatus(config, options = {}) {
94
94
  const report = await generateStatusReport(config);
95
95
  spinner.succeed('Analysis complete.');
96
96
  await displayStatusReport(report, config, options);
97
+ // When a specific locale is requested (`status <locale>`), the pass/fail
98
+ // result must reflect THAT locale only — otherwise the displayed summary
99
+ // (which is scoped to the requested locale) can contradict the exit code
100
+ // by failing on an unrelated secondary language. See issue #271.
101
+ const scopedLocale = options.detail && config.locales.includes(options.detail)
102
+ ? options.detail
103
+ : undefined;
97
104
  let hasMissing = false;
98
- for (const [, localeData] of report.locales.entries()) {
99
- if (localeData.totalTranslated < localeData.totalKeys) {
100
- hasMissing = true;
101
- break;
105
+ if (scopedLocale) {
106
+ if (scopedLocale === config.extract.primaryLanguage) {
107
+ // The primary language fails only on absent keys (used in code but
108
+ // missing from the file); empty placeholders are deliberate.
109
+ hasMissing = !!report.primary && report.primary.totalAbsent > 0;
110
+ }
111
+ else {
112
+ const localeData = report.locales.get(scopedLocale);
113
+ hasMissing = !!localeData && localeData.totalTranslated < localeData.totalKeys;
102
114
  }
103
115
  }
104
- // The primary language fails the check only on absent keys (used in code but
105
- // missing from the translation file); empty placeholders are tolerated.
106
- if (!hasMissing && report.primary && report.primary.totalAbsent > 0) {
107
- hasMissing = true;
116
+ else {
117
+ for (const [, localeData] of report.locales.entries()) {
118
+ if (localeData.totalTranslated < localeData.totalKeys) {
119
+ hasMissing = true;
120
+ break;
121
+ }
122
+ }
123
+ // The primary language fails the check only on absent keys (used in code but
124
+ // missing from the translation file); empty placeholders are tolerated.
125
+ if (!hasMissing && report.primary && report.primary.totalAbsent > 0) {
126
+ hasMissing = true;
127
+ }
108
128
  }
109
129
  if (hasMissing) {
110
- spinner.fail('Error: Incomplete translations detected.');
130
+ // Name the locale when the check is scoped so the failure reason is clear
131
+ // (the displayed summary already explains what is missing for it).
132
+ spinner.fail(scopedLocale
133
+ ? `Error: Incomplete translations detected for "${scopedLocale}".`
134
+ : 'Error: Incomplete translations detected.');
111
135
  process.exit(1);
112
136
  }
113
137
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i18next-cli",
3
- "version": "1.64.1",
3
+ "version": "1.64.2",
4
4
  "description": "A unified, high-performance i18next CLI.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAgB,MAAM,YAAY,CAAA;AAOpE;;GAEG;AACH,UAAU,aAAa;IACrB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAyHD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,SAAS,CAAE,MAAM,EAAE,oBAAoB,EAAE,OAAO,GAAE,aAAkB,iBA4BzF"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAgB,MAAM,YAAY,CAAA;AAOpE;;GAEG;AACH,UAAU,aAAa;IACrB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAyHD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,SAAS,CAAE,MAAM,EAAE,oBAAoB,EAAE,OAAO,GAAE,aAAkB,iBAoDzF"}