@better-i18n/cli 0.1.1 → 0.1.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/README.md CHANGED
@@ -27,7 +27,7 @@ Hardcoded strings slip into codebases easily. Finding them manually is tedious.
27
27
  # Global install
28
28
  npm install -g @better-i18n/cli
29
29
 
30
- # Or use with npx (no install)
30
+ # Or use with npx (no install needed)
31
31
  npx @better-i18n/cli scan
32
32
 
33
33
  # Or add to your project
@@ -43,93 +43,167 @@ better-i18n scan
43
43
  # That's it! The CLI auto-detects your i18n.config.ts
44
44
  ```
45
45
 
46
- ## Usage
46
+ ## Features
47
47
 
48
- ```bash
49
- # Scan specific directory
50
- better-i18n scan --dir ./src
48
+ - ✅ **Auto-config detection** - Reads your existing `i18n.config.ts`
49
+ - **Smart filtering** - Ignores CSS classes, URLs, constants, HTML entities
50
+ - **Glob patterns** - Exclude test files, stories, UI components
51
+ - ✅ **Clickable output** - File paths are Cmd+clickable in VS Code terminal
52
+ - ✅ **CI/CD ready** - JSON output, exit codes, staged files support
53
+ - ✅ **Fast** - Scans 100+ files in <100ms
54
+
55
+ ## Example Output
56
+
57
+ ```
58
+ $ better-i18n scan
59
+
60
+ ✓ Project: better-i18n/landing
61
+ ✓ Found 57 files
51
62
 
52
- # JSON output (for CI/tooling)
53
- better-i18n scan --format json
63
+ components/sign-up.tsx (11)
64
+ 24:13 missing "Create an account" i18n/jsx-text
65
+ 32:22 missing "Name" i18n/jsx-text
66
+ 40:22 missing "Email" i18n/jsx-text
54
67
 
55
- # CI mode (exit code 1 if issues found)
56
- better-i18n scan --ci
68
+ components/contact.tsx (9)
69
+ 24:59 missing "Contact us" i18n/jsx-text
70
+ 31:22 missing "Message" i18n/jsx-text
57
71
 
58
- # Only scan git staged files (for pre-commit hooks)
59
- better-i18n scan --staged
72
+ 87 problems (87 missing translations)
60
73
 
61
- # Verbose output
62
- better-i18n scan --verbose
74
+ Scanned 57 files in 0.07s
63
75
  ```
64
76
 
65
- ## Example Output
77
+ **Cmd+Click** on any file path to jump directly to the issue in VS Code!
66
78
 
67
- ```
68
- $ better-i18n scan
79
+ ## Commands & Options
69
80
 
70
- Project: acme/web-app
71
- ✓ Found 45 files
81
+ ### `better-i18n scan`
72
82
 
73
- src/components/Header.tsx
74
- 12:8 warning "Welcome back" i18n/jsx-text
75
- 15:18 warning "Profile picture" i18n/jsx-attribute
83
+ Scan your codebase for hardcoded strings.
76
84
 
77
- src/pages/login.tsx
78
- 23:15 error locale === 'en' ? ... : ... i18n/ternary-locale
85
+ ```bash
86
+ # Basic usage
87
+ better-i18n scan
88
+
89
+ # Scan specific directory
90
+ better-i18n scan --dir ./src
91
+
92
+ # Output formats
93
+ better-i18n scan --format json # JSON output for CI/tooling
94
+ better-i18n scan --format eslint # Human-readable (default)
79
95
 
80
- 3 problems (1 error, 2 warnings)
96
+ # CI/CD integration
97
+ better-i18n scan --ci # Exit with code 1 if issues found
98
+ better-i18n scan --staged # Only scan git staged files
81
99
 
82
- Scanned 45 files in 0.23s
100
+ # Debug
101
+ better-i18n scan --verbose # Show detailed output
83
102
  ```
84
103
 
85
104
  ## Detection Rules
86
105
 
87
- | Rule | Severity | What it catches |
88
- |------|----------|-----------------|
89
- | `jsx-text` | warning | Hardcoded text inside JSX elements |
90
- | `jsx-attribute` | warning | Hardcoded `title`, `alt`, `placeholder`, `aria-label` |
91
- | `ternary-locale` | error | `locale === 'en' ? 'Hello' : 'Hola'` anti-pattern |
106
+ | Rule | Severity | What it catches | Example |
107
+ |------|----------|-----------------|---------|
108
+ | `jsx-text` | missing | Hardcoded text in JSX | `<h1>Hello</h1>` |
109
+ | `jsx-attribute` | missing | Hardcoded attributes | `<img alt="Logo" />` |
110
+ | `ternary-locale` | error | Locale-based ternaries | `locale === 'en' ? 'Hi' : 'Hola'` |
111
+
112
+ ### Automatically Ignored
113
+
114
+ - HTML entities: `&quot;`, `&amp;`, `&#39;`
115
+ - CSS classes: `className="flex items-center"`
116
+ - URLs: `href="https://example.com"`
117
+ - Paths: `/api/users`
118
+ - Numbers: `42`, `3.14`, `100%`
119
+ - Constants: `SCREAMING_CASE`
120
+ - Symbols: `→`, `•`, `...`
92
121
 
93
122
  ## Configuration
94
123
 
95
- The CLI automatically reads your `i18n.config.ts` file. No extra config needed!
124
+ Create or update your `i18n.config.ts`:
96
125
 
97
126
  ```ts
98
- // i18n.config.ts
99
- import { createI18n } from "@better-i18n/next";
100
-
101
- export const { useTranslation, I18nProvider } = createI18n({
102
- project: "your-org/your-project",
103
- defaultLocale: "en",
104
-
105
- // Optional: customize lint behavior
127
+ export const project = "your-org/your-project";
128
+ export const defaultLocale = "en";
129
+
130
+ export const i18nWorkspaceConfig = {
131
+ project,
132
+ defaultLocale,
106
133
  lint: {
134
+ // Files to scan (defaults: ["src", "app", "components", "pages"])
107
135
  include: ["src/**/*.tsx", "app/**/*.tsx"],
108
- exclude: ["**/*.test.tsx", "**/*.stories.tsx"],
136
+
137
+ // Files to ignore (automatically merges with defaults)
138
+ exclude: [
139
+ "**/skeletons.tsx", // Mock/demo components
140
+ "**/*.stories.tsx", // Storybook files
141
+ "**/*.test.tsx", // Test files
142
+ "**/components/ui/**", // UI library components
143
+ ],
144
+
145
+ // Rule configuration (optional)
109
146
  rules: {
110
147
  "jsx-text": "warning",
111
- "jsx-attribute": "warning",
148
+ "jsx-attribute": "warning",
112
149
  "ternary-locale": "error",
113
150
  },
114
151
  },
115
- });
152
+ };
116
153
  ```
117
154
 
118
- ### Lint Options
155
+ ### Config Options
119
156
 
120
157
  | Option | Type | Description |
121
158
  |--------|------|-------------|
122
- | `include` | `string[]` | Glob patterns for files to scan |
123
- | `exclude` | `string[]` | Glob patterns for files to ignore |
124
- | `rules` | `object` | Rule severity: `"error"`, `"warning"`, or `"off"` |
159
+ | `include` | `string[]` | Glob patterns for files to scan (default: `["src", "app", "components", "pages"]`) |
160
+ | `exclude` | `string[]` | Glob patterns to ignore (merges with defaults: `node_modules`, `.next`, etc.) |
161
+ | `rules` | `object` | Set severity: `"error"` \| `"warning"` \| `"off"` |
162
+
163
+ ## Usage Scenarios
164
+
165
+ ### 1. Local Development
166
+
167
+ Add to your `package.json`:
125
168
 
126
- ## CI/CD Integration
169
+ ```json
170
+ {
171
+ "scripts": {
172
+ "lint": "next lint && better-i18n scan --ci",
173
+ "lint:i18n": "better-i18n scan"
174
+ }
175
+ }
176
+ ```
177
+
178
+ Run before commits:
179
+ ```bash
180
+ npm run lint:i18n
181
+ ```
182
+
183
+ ### 2. Pre-commit Hook
184
+
185
+ Install [Husky](https://typicode.github.io/husky/):
186
+
187
+ ```bash
188
+ npx husky init
189
+ echo "npx @better-i18n/cli scan --staged --ci" > .husky/pre-commit
190
+ ```
191
+
192
+ Or with [lint-staged](https://github.com/lint-staged/lint-staged):
193
+
194
+ ```json
195
+ {
196
+ "lint-staged": {
197
+ "*.{tsx,jsx}": ["better-i18n scan --ci"]
198
+ }
199
+ }
200
+ ```
127
201
 
128
- ### GitHub Actions
202
+ ### 3. GitHub Actions CI
129
203
 
130
204
  ```yaml
131
- # .github/workflows/i18n-lint.yml
132
- name: i18n Lint
205
+ # .github/workflows/i18n-check.yml
206
+ name: i18n Check
133
207
 
134
208
  on: [push, pull_request]
135
209
 
@@ -141,77 +215,167 @@ jobs:
141
215
  - uses: actions/setup-node@v4
142
216
  with:
143
217
  node-version: '20'
144
- - run: npx @better-i18n/cli scan --ci
218
+ - run: npx @better-i18n/cli scan --ci --format json
145
219
  ```
146
220
 
147
- ### Pre-commit Hook
221
+ ### 4. VS Code Integration
148
222
 
149
- With [Husky](https://typicode.github.io/husky/):
150
-
151
- ```bash
152
- # .husky/pre-commit
153
- npx @better-i18n/cli scan --staged --ci
154
- ```
155
-
156
- Or with [lint-staged](https://github.com/lint-staged/lint-staged):
223
+ Add to `.vscode/tasks.json`:
157
224
 
158
225
  ```json
159
226
  {
160
- "lint-staged": {
161
- "*.{tsx,jsx}": ["better-i18n scan --ci"]
162
- }
227
+ "version": "2.0.0",
228
+ "tasks": [
229
+ {
230
+ "label": "i18n: Check translations",
231
+ "type": "shell",
232
+ "command": "npx @better-i18n/cli scan",
233
+ "problemMatcher": [],
234
+ "presentation": {
235
+ "reveal": "always",
236
+ "panel": "new"
237
+ }
238
+ }
239
+ ]
163
240
  }
164
241
  ```
165
242
 
243
+ Run with: `Cmd+Shift+P` → `Tasks: Run Task` → `i18n: Check translations`
244
+
245
+ ### 5. Monorepo Usage
246
+
247
+ ```bash
248
+ # Scan specific package
249
+ cd packages/web-app
250
+ better-i18n scan
251
+
252
+ # Or from root with --dir
253
+ better-i18n scan --dir packages/web-app
254
+ ```
255
+
256
+ Each package can have its own `i18n.config.ts`.
257
+
166
258
  ## JSON Output
167
259
 
168
- Use `--format json` for programmatic access:
260
+ Use `--format json` for programmatic integration:
169
261
 
170
262
  ```bash
171
- better-i18n scan --format json
263
+ better-i18n scan --format json > i18n-report.json
172
264
  ```
173
265
 
174
266
  ```json
175
267
  {
176
268
  "project": {
177
- "workspaceId": "acme",
178
- "projectSlug": "web-app",
269
+ "workspaceId": "better-i18n",
270
+ "projectSlug": "landing",
179
271
  "defaultLocale": "en"
180
272
  },
181
- "files": 45,
273
+ "files": 57,
182
274
  "issues": [
183
275
  {
184
- "file": "src/components/Header.tsx",
185
- "line": 12,
186
- "column": 8,
187
- "text": "Welcome back",
276
+ "file": "components/sign-up.tsx",
277
+ "line": 24,
278
+ "column": 13,
279
+ "text": "Create an account",
188
280
  "type": "jsx-text",
189
281
  "severity": "warning",
190
- "message": "Hardcoded text in JSX"
282
+ "message": "Hardcoded text: \"Create an account\"",
283
+ "suggestedKey": "signUp.createAnAccount"
191
284
  }
192
285
  ],
193
- "duration": 234
286
+ "duration": 67
287
+ }
288
+ ```
289
+
290
+ ### JSON Schema
291
+
292
+ ```ts
293
+ interface ScanResult {
294
+ project?: {
295
+ workspaceId: string;
296
+ projectSlug: string;
297
+ defaultLocale: string;
298
+ };
299
+ files: number;
300
+ issues: Issue[];
301
+ duration: number;
194
302
  }
303
+
304
+ interface Issue {
305
+ file: string; // Relative path
306
+ line: number; // Line number
307
+ column: number; // Column number
308
+ text: string; // Hardcoded text
309
+ type: "jsx-text" | "jsx-attribute" | "ternary-locale";
310
+ severity: "error" | "warning";
311
+ message: string; // Human-readable message
312
+ suggestedKey?: string; // Auto-generated translation key
313
+ }
314
+ ```
315
+
316
+ ## Advanced Usage
317
+
318
+ ### Custom Scripts
319
+
320
+ ```bash
321
+ # Count missing translations
322
+ better-i18n scan --format json | jq '.issues | length'
323
+
324
+ # Get unique files with issues
325
+ better-i18n scan --format json | jq -r '.issues[].file' | sort -u
326
+
327
+ # Filter only errors
328
+ better-i18n scan --format json | jq '.issues[] | select(.severity == "error")'
195
329
  ```
196
330
 
197
- ## What Gets Ignored
331
+ ### Combine with Other Tools
198
332
 
199
- The CLI is smart about ignoring non-translatable content:
333
+ ```bash
334
+ # Run with TypeScript checks
335
+ tsc --noEmit && better-i18n scan --ci
336
+
337
+ # Run with ESLint
338
+ eslint . && better-i18n scan --ci
200
339
 
201
- - CSS class names: `className="flex items-center"`
202
- - URLs: `href="https://example.com"`
203
- - ✅ Numbers and constants
204
- - ✅ Import paths
205
- - ✅ Code identifiers
206
- - ✅ Single characters and punctuation
340
+ # Parallel execution
341
+ npm-run-all --parallel typecheck lint:eslint lint:i18n
342
+ ```
343
+
344
+ ## Troubleshooting
345
+
346
+ ### Config not detected
347
+
348
+ Make sure your `i18n.config.ts` exports either:
349
+ - `export const project = "org/slug"`
350
+ - `export const i18nWorkspaceConfig = { project: "org/slug" }`
351
+
352
+ ### Too many false positives
353
+
354
+ Add exclusions to your config:
355
+ ```ts
356
+ exclude: [
357
+ "**/*.stories.tsx",
358
+ "**/demo/**",
359
+ "**/examples/**",
360
+ ]
361
+ ```
362
+
363
+ ### Clickable links not working
364
+
365
+ Make sure you're using VS Code's integrated terminal. External terminals may not support clickable file paths.
207
366
 
208
367
  ## Part of Better i18n
209
368
 
210
369
  This CLI is part of the [Better i18n](https://better-i18n.com) ecosystem:
211
370
 
212
371
  - **[@better-i18n/next](https://www.npmjs.com/package/@better-i18n/next)** - Next.js i18n SDK
213
- - **[@better-i18n/cli](https://www.npmjs.com/package/@better-i18n/cli)** - This CLI
372
+ - **[@better-i18n/cli](https://www.npmjs.com/package/@better-i18n/cli)** - This CLI tool
214
373
  - **[Dashboard](https://better-i18n.com)** - Visual translation management
374
+ - **[MCP Server](https://github.com/better-i18n/better-i18n)** - AI-powered translation assistant
375
+
376
+ ## Contributing
377
+
378
+ Found a bug or have a feature request? [Open an issue](https://github.com/better-i18n/better-i18n/issues).
215
379
 
216
380
  ## License
217
381
 
@@ -1 +1 @@
1
- {"version":3,"file":"ternary-locale.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/ternary-locale.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEtD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,EAAE,CAAC,qBAAqB,EAC9B,GAAG,EAAE,WAAW,GACf,KAAK,GAAG,IAAI,CA4Cd"}
1
+ {"version":3,"file":"ternary-locale.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/ternary-locale.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEtD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,EAAE,CAAC,qBAAqB,EAC9B,GAAG,EAAE,WAAW,GACf,KAAK,GAAG,IAAI,CAgDd"}
@@ -4,7 +4,7 @@
4
4
  * Detects anti-pattern: locale === 'en' ? 'Hello' : 'Merhaba'
5
5
  */
6
6
  import ts from "typescript";
7
- import { truncate } from "../../utils/text.js";
7
+ import { generateKeyFromContext, truncate } from "../../utils/text.js";
8
8
  /**
9
9
  * Check conditional expression for locale-based ternary
10
10
  */
@@ -35,6 +35,9 @@ export function checkTernaryLocale(node, ctx) {
35
35
  const text = hasStringTrue
36
36
  ? node.whenTrue.text
37
37
  : node.whenFalse.text;
38
+ // Ignore empty strings (common in URL construction: locale === 'en' ? '' : locale + '/')
39
+ if (text.trim() === "")
40
+ return null;
38
41
  const pos = ctx.sourceFile.getLineAndCharacterOfPosition(node.getStart());
39
42
  return {
40
43
  file: ctx.filePath,
@@ -44,6 +47,7 @@ export function checkTernaryLocale(node, ctx) {
44
47
  type: "ternary-locale",
45
48
  severity: "error", // This is an anti-pattern, so error
46
49
  message: `Locale ternary pattern detected: "${truncate(text, 30)}"`,
50
+ suggestedKey: generateKeyFromContext(text, ctx.filePath),
47
51
  };
48
52
  }
49
53
  //# sourceMappingURL=ternary-locale.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ternary-locale.js","sourceRoot":"","sources":["../../../src/analyzer/rules/ternary-locale.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAG/C;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAA8B,EAC9B,GAAgB;IAEhB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IAEjC,8BAA8B;IAC9B,IAAI,CAAC,EAAE,CAAC,kBAAkB,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAEnD,iCAAiC;IACjC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC;IAC5B,IAAI,kBAAkB,GAAG,KAAK,CAAC;IAE/B,qCAAqC;IACrC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACpD,kBAAkB,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED,kEAAkE;IAClE,IAAI,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACvE,kBAAkB,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED,IAAI,CAAC,kBAAkB;QAAE,OAAO,IAAI,CAAC;IAErC,8CAA8C;IAC9C,MAAM,aAAa,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxD,MAAM,cAAc,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAE1D,IAAI,CAAC,aAAa,IAAI,CAAC,cAAc;QAAE,OAAO,IAAI,CAAC;IAEnD,uBAAuB;IACvB,MAAM,IAAI,GAAG,aAAa;QACxB,CAAC,CAAE,IAAI,CAAC,QAA6B,CAAC,IAAI;QAC1C,CAAC,CAAE,IAAI,CAAC,SAA8B,CAAC,IAAI,CAAC;IAE9C,MAAM,GAAG,GAAG,GAAG,CAAC,UAAU,CAAC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IAE1E,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,QAAQ;QAClB,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC;QAClB,MAAM,EAAE,GAAG,CAAC,SAAS,GAAG,CAAC;QACzB,IAAI;QACJ,IAAI,EAAE,gBAAgB;QACtB,QAAQ,EAAE,OAAO,EAAE,oCAAoC;QACvD,OAAO,EAAE,qCAAqC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG;KACpE,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"ternary-locale.js","sourceRoot":"","sources":["../../../src/analyzer/rules/ternary-locale.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGvE;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAA8B,EAC9B,GAAgB;IAEhB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IAEjC,8BAA8B;IAC9B,IAAI,CAAC,EAAE,CAAC,kBAAkB,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAEnD,iCAAiC;IACjC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC;IAC5B,IAAI,kBAAkB,GAAG,KAAK,CAAC;IAE/B,qCAAqC;IACrC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACpD,kBAAkB,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED,kEAAkE;IAClE,IAAI,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACvE,kBAAkB,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED,IAAI,CAAC,kBAAkB;QAAE,OAAO,IAAI,CAAC;IAErC,8CAA8C;IAC9C,MAAM,aAAa,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxD,MAAM,cAAc,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAE1D,IAAI,CAAC,aAAa,IAAI,CAAC,cAAc;QAAE,OAAO,IAAI,CAAC;IAEnD,uBAAuB;IACvB,MAAM,IAAI,GAAG,aAAa;QACxB,CAAC,CAAE,IAAI,CAAC,QAA6B,CAAC,IAAI;QAC1C,CAAC,CAAE,IAAI,CAAC,SAA8B,CAAC,IAAI,CAAC;IAE9C,yFAAyF;IACzF,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAEpC,MAAM,GAAG,GAAG,GAAG,CAAC,UAAU,CAAC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IAE1E,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,QAAQ;QAClB,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC;QAClB,MAAM,EAAE,GAAG,CAAC,SAAS,GAAG,CAAC;QACzB,IAAI;QACJ,IAAI,EAAE,gBAAgB;QACtB,QAAQ,EAAE,OAAO,EAAE,oCAAoC;QACvD,OAAO,EAAE,qCAAqC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG;QACnE,YAAY,EAAE,sBAAsB,CAAC,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC;KACzD,CAAC;AACJ,CAAC"}
@@ -18,6 +18,7 @@ export interface RuleContext {
18
18
  export interface ScanOptions {
19
19
  dir?: string;
20
20
  format: "eslint" | "json";
21
+ maxIssues?: number;
21
22
  fix?: boolean;
22
23
  ci?: boolean;
23
24
  staged?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/analyzer/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,eAAe,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;IAC1E,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,YAAY,EAAE,UAAU,CAAC;CAC7C;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC1B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,KAAK,CAAC,CAAC;IACpD,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/analyzer/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,eAAe,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;IAC1E,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,YAAY,EAAE,UAAU,CAAC;CAC7C;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,KAAK,CAAC,CAAC;IACpD,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB"}
@@ -1 +1 @@
1
- {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAS,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAM/D,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA2ErE"}
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAS,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAM/D,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA6ErE"}
@@ -58,7 +58,9 @@ export async function scanCommand(options) {
58
58
  });
59
59
  }
60
60
  else {
61
- reportEslintStyle(allIssues, rootDir);
61
+ // Default max issues to 100 if not specified
62
+ const maxIssues = options.maxIssues ?? 100;
63
+ reportEslintStyle(allIssues, rootDir, maxIssues);
62
64
  // Summary
63
65
  console.log();
64
66
  if (allIssues.length === 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -16,6 +16,7 @@ program
16
16
  .description("Scan source files for untranslated strings")
17
17
  .option("-d, --dir <path>", "Directory to scan (default: current directory)")
18
18
  .option("-f, --format <type>", "Output format: eslint, json", "eslint")
19
+ .option("--max-issues <number>", "Maximum number of issues to display (default: 100)", parseInt)
19
20
  .option("--fix", "Auto-fix: wrap hardcoded text with t()")
20
21
  .option("--ci", "CI mode: exit with error code if issues found")
21
22
  .option("--staged", "Only scan git staged files")
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CAAC,oDAAoD,CAAC;KACjE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,4CAA4C,CAAC;KACzD,MAAM,CAAC,kBAAkB,EAAE,gDAAgD,CAAC;KAC5E,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,EAAE,QAAQ,CAAC;KACtE,MAAM,CAAC,OAAO,EAAE,wCAAwC,CAAC;KACzD,MAAM,CAAC,MAAM,EAAE,+CAA+C,CAAC;KAC/D,MAAM,CAAC,UAAU,EAAE,4BAA4B,CAAC;KAChD,MAAM,CAAC,WAAW,EAAE,sBAAsB,CAAC;KAC3C,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CAAC,oDAAoD,CAAC;KACjE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,4CAA4C,CAAC;KACzD,MAAM,CAAC,kBAAkB,EAAE,gDAAgD,CAAC;KAC5E,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,EAAE,QAAQ,CAAC;KACtE,MAAM,CACL,uBAAuB,EACvB,oDAAoD,EACpD,QAAQ,CACT;KACA,MAAM,CAAC,OAAO,EAAE,wCAAwC,CAAC;KACzD,MAAM,CAAC,MAAM,EAAE,+CAA+C,CAAC;KAC/D,MAAM,CAAC,UAAU,EAAE,4BAA4B,CAAC;KAChD,MAAM,CAAC,WAAW,EAAE,sBAAsB,CAAC;KAC3C,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -7,5 +7,5 @@ import type { Issue } from "../analyzer/types.js";
7
7
  /**
8
8
  * Report issues in ESLint-style format
9
9
  */
10
- export declare function reportEslintStyle(issues: Issue[], rootDir: string): void;
10
+ export declare function reportEslintStyle(issues: Issue[], rootDir: string, maxIssues?: number): void;
11
11
  //# sourceMappingURL=eslint-style.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"eslint-style.d.ts","sourceRoot":"","sources":["../../src/reporters/eslint-style.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAGlD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAyDxE"}
1
+ {"version":3,"file":"eslint-style.d.ts","sourceRoot":"","sources":["../../src/reporters/eslint-style.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAGlD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,KAAK,EAAE,EACf,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,IAAI,CA4EN"}
@@ -8,12 +8,15 @@ import { bold, cyan, dim, red, yellow } from "../utils/colors.js";
8
8
  /**
9
9
  * Report issues in ESLint-style format
10
10
  */
11
- export function reportEslintStyle(issues, rootDir) {
11
+ export function reportEslintStyle(issues, rootDir, maxIssues) {
12
12
  if (issues.length === 0)
13
13
  return;
14
+ const totalIssues = issues.length;
15
+ const displayIssues = maxIssues ? issues.slice(0, maxIssues) : issues;
16
+ const hasMore = maxIssues && totalIssues > maxIssues;
14
17
  // Group by file
15
18
  const byFile = new Map();
16
- for (const issue of issues) {
19
+ for (const issue of displayIssues) {
17
20
  const existing = byFile.get(issue.file) || [];
18
21
  existing.push(issue);
19
22
  byFile.set(issue.file, existing);
@@ -43,13 +46,21 @@ export function reportEslintStyle(issues, rootDir) {
43
46
  }
44
47
  }
45
48
  }
46
- // Summary
47
- const total = errorCount + missingCount;
49
+ // Show "and X more" message if truncated
50
+ if (hasMore) {
51
+ const remaining = totalIssues - maxIssues;
52
+ console.log();
53
+ console.log(dim(`... and ${remaining} more problem${remaining > 1 ? "s" : ""}`));
54
+ }
55
+ // Summary - use total counts, not just displayed
56
+ const totalErrorCount = issues.filter((i) => i.severity === "error").length;
57
+ const totalMissingCount = issues.filter((i) => i.severity === "warning").length;
58
+ const total = totalErrorCount + totalMissingCount;
48
59
  const summary = [];
49
- if (errorCount > 0)
50
- summary.push(red(`${errorCount} error${errorCount > 1 ? "s" : ""}`));
51
- if (missingCount > 0)
52
- summary.push(yellow(`${missingCount} missing translation${missingCount > 1 ? "s" : ""}`));
60
+ if (totalErrorCount > 0)
61
+ summary.push(red(`${totalErrorCount} error${totalErrorCount > 1 ? "s" : ""}`));
62
+ if (totalMissingCount > 0)
63
+ summary.push(yellow(`${totalMissingCount} missing translation${totalMissingCount > 1 ? "s" : ""}`));
53
64
  console.log(bold(`✖ ${total} problem${total > 1 ? "s" : ""} (${summary.join(", ")})`));
54
65
  }
55
66
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"eslint-style.js","sourceRoot":"","sources":["../../src/reporters/eslint-style.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"eslint-style.js","sourceRoot":"","sources":["../../src/reporters/eslint-style.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-i18n/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "CLI tool for detecting hardcoded strings in React/Next.js apps",
5
5
  "license": "MIT",
6
6
  "type": "module",