i18next-cli 1.24.13 → 1.24.14

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.
Files changed (39) hide show
  1. package/dist/cjs/cli.js +1 -1
  2. package/dist/esm/cli.js +1 -1
  3. package/package.json +6 -6
  4. package/types/cli.d.ts +3 -1
  5. package/types/cli.d.ts.map +1 -1
  6. package/CHANGELOG.md +0 -599
  7. package/src/cli.ts +0 -283
  8. package/src/config.ts +0 -215
  9. package/src/extractor/core/ast-visitors.ts +0 -259
  10. package/src/extractor/core/extractor.ts +0 -250
  11. package/src/extractor/core/key-finder.ts +0 -142
  12. package/src/extractor/core/translation-manager.ts +0 -750
  13. package/src/extractor/index.ts +0 -7
  14. package/src/extractor/parsers/ast-utils.ts +0 -87
  15. package/src/extractor/parsers/call-expression-handler.ts +0 -793
  16. package/src/extractor/parsers/comment-parser.ts +0 -424
  17. package/src/extractor/parsers/expression-resolver.ts +0 -391
  18. package/src/extractor/parsers/jsx-handler.ts +0 -488
  19. package/src/extractor/parsers/jsx-parser.ts +0 -1463
  20. package/src/extractor/parsers/scope-manager.ts +0 -445
  21. package/src/extractor/plugin-manager.ts +0 -116
  22. package/src/extractor.ts +0 -15
  23. package/src/heuristic-config.ts +0 -92
  24. package/src/index.ts +0 -22
  25. package/src/init.ts +0 -175
  26. package/src/linter.ts +0 -345
  27. package/src/locize.ts +0 -263
  28. package/src/migrator.ts +0 -208
  29. package/src/rename-key.ts +0 -398
  30. package/src/status.ts +0 -380
  31. package/src/syncer.ts +0 -133
  32. package/src/types-generator.ts +0 -139
  33. package/src/types.ts +0 -577
  34. package/src/utils/default-value.ts +0 -45
  35. package/src/utils/file-utils.ts +0 -167
  36. package/src/utils/funnel-msg-tracker.ts +0 -84
  37. package/src/utils/logger.ts +0 -36
  38. package/src/utils/nested-object.ts +0 -135
  39. package/src/utils/validation.ts +0 -72
package/src/types.ts DELETED
@@ -1,577 +0,0 @@
1
- import type { Expression, Node, ObjectExpression } from '@swc/core'
2
-
3
- /**
4
- * Main configuration interface for the i18next toolkit.
5
- * Defines all available options for extraction, type generation, synchronization, and integrations.
6
- *
7
- * @example
8
- * ```typescript
9
- * const config: I18nextToolkitConfig = {
10
- * locales: ['en', 'de', 'fr'],
11
- * extract: {
12
- * input: ['src/**\/*.{ts,tsx}'],
13
- * output: 'locales/{{language}}/{{namespace}}.json',
14
- * functions: ['t', 'i18n.t'],
15
- * transComponents: ['Trans', 'Translation']
16
- * },
17
- * types: {
18
- * input: ['locales/en/*.json'],
19
- * output: 'src/types/i18next.d.ts'
20
- * }
21
- * }
22
- * ```
23
- */
24
- export interface I18nextToolkitConfig {
25
- /** Array of supported locale codes (e.g., ['en', 'de', 'fr']) */
26
- locales: string[];
27
-
28
- /** Configuration options for translation key extraction */
29
- extract: {
30
- /** Glob pattern(s) for source files to scan for translation keys */
31
- input: string | string[];
32
-
33
- /** Glob pattern(s) for files to ignore during extraction */
34
- ignore?: string | string[];
35
-
36
- /** Output path template with placeholders: {{language}} for locale, {{namespace}} for namespace */
37
- output: string | ((language: string, namespace?: string) => string);
38
-
39
- /**
40
- * Default namespace when none is specified (default: 'translation').
41
- * Set to false will not generate any namespace, useful if i.e. the output is a single language json with 1 namespace (and no nesting).
42
- */
43
- defaultNS?: string | false;
44
-
45
- /** Separator for nested keys, or false for flat keys (default: '.') */
46
- keySeparator?: string | false | null;
47
-
48
- /** Separator between namespace and key, or false to disable (default: ':') */
49
- nsSeparator?: string | false | null;
50
-
51
- /** Separator for context variants (default: '_') */
52
- contextSeparator?: string;
53
-
54
- /** Separator for plural variants (default: '_') */
55
- pluralSeparator?: string;
56
-
57
- /** Function names to extract translation calls from (default: ['t', '*.t']) */
58
- functions?: string[];
59
-
60
- /** JSX component names to extract translations from (default: ['Trans']) */
61
- transComponents?: string[];
62
-
63
- /**
64
- * Hook function names that return translation functions.
65
- * Can be a string for default behavior (ns: arg 0, keyPrefix: arg 1)
66
- * or an object for custom argument positions.
67
- * (default: ['useTranslation', 'getT', 'useT'])
68
- */
69
- useTranslationNames?: Array<string | {
70
- name: string;
71
- nsArg?: number;
72
- keyPrefixArg?: number;
73
- }>;
74
-
75
- /** A list of JSX attribute names to ignore when linting for hardcoded strings. */
76
- ignoredAttributes?: string[];
77
-
78
- /** A list of JSX tag names whose content should be ignored when linting (e.g., 'code', 'pre'). */
79
- ignoredTags?: string[];
80
-
81
- /** HTML tags to preserve in Trans component serialization (default: ['br', 'strong', 'i']) */
82
- transKeepBasicHtmlNodesFor?: string[];
83
-
84
- /** Glob patterns for keys to preserve even if not found in source (for dynamic keys) */
85
- preservePatterns?: string[];
86
-
87
- /**
88
- * When true, preserves all context variants of keys that use context parameters.
89
- * For example, if 'friend' is used with context, all variants like 'friend_male',
90
- * 'friend_female', etc. are preserved even if not explicitly found in source code.
91
- * (default: false)
92
- */
93
- preserveContextVariants?: boolean;
94
-
95
- /** Whether to sort keys alphabetically in output files, or a comparator function to customize the order (default: true) */
96
- sort?: boolean | ((a: ExtractedKey, b: ExtractedKey) => number);
97
-
98
- /** Number of spaces for JSON indentation (default: 2) */
99
- indentation?: number | string;
100
-
101
- /** Default value to use for missing translations in secondary languages */
102
- defaultValue?: string | ((key: string, namespace: string, language: string, value: string) => string);
103
-
104
- /** Primary language that provides default values (default: first locale) */
105
- primaryLanguage?: string;
106
-
107
- /** Secondary languages that get empty values initially */
108
- secondaryLanguages?: string[];
109
-
110
- /**
111
- * The format of the output translation files.
112
- * 'json': Standard JSON file (default)
113
- * 'js': JavaScript file with ES Module syntax (export default)
114
- * 'js-esm': JavaScript file with ES Module syntax (export default)
115
- * 'js-cjs': JavaScript file with CommonJS syntax (module.exports)
116
- * 'ts': TypeScript file with ES Module syntax and `as const` for type safety
117
- */
118
- outputFormat?: 'json' | 'js' | 'js-esm' | 'js-esm' | 'js-cjs' | 'ts';
119
-
120
- /**
121
- * If true, all namespaces will be merged into a single file per language.
122
- * The `output` path should not contain the `{{namespace}}` placeholder.
123
- * Example output: `locales/en.js`
124
- * (default: false)
125
- */
126
- mergeNamespaces?: boolean;
127
-
128
- /** If true, keys that are not found in the source code will be removed from translation files. (default: true) */
129
- removeUnusedKeys?: boolean;
130
-
131
- // New option to control whether base plural forms are generated when context is present
132
- generateBasePluralForms?: boolean
133
-
134
- // New option to completely disable plural generation
135
- disablePlurals?: boolean
136
- };
137
-
138
- /** Configuration options for TypeScript type generation */
139
- types?: {
140
- /** Glob pattern(s) for translation files to generate types from */
141
- input: string | string[];
142
-
143
- /** Output path for the main TypeScript definition file */
144
- output: string;
145
-
146
- /** Enable type-safe selector API (boolean or 'optimize' for smaller types) */
147
- enableSelector?: boolean | 'optimize';
148
-
149
- /** Path for the separate resources interface file */
150
- resourcesFile?: string;
151
-
152
- /**
153
- * Number of spaces or string to use for indentation when generating
154
- * TypeScript definitions. Falls back to `extract.indentation` when unset.
155
- */
156
- indentation?: number | string;
157
- };
158
-
159
- /** Array of plugins to extend functionality */
160
- plugins?: Plugin[];
161
-
162
- /** Configuration for Locize integration */
163
- locize?: {
164
- /** Locize project ID */
165
- projectId?: string;
166
-
167
- /** Locize API key (recommended to use environment variables) */
168
- apiKey?: string;
169
-
170
- /** Version to sync with (default: 'latest') */
171
- version?: string;
172
-
173
- /** Whether to update existing translation values on Locize */
174
- updateValues?: boolean;
175
-
176
- /** Only sync the source language to Locize */
177
- sourceLanguageOnly?: boolean;
178
-
179
- /** Compare modification times when syncing */
180
- compareModificationTime?: boolean;
181
-
182
- /** Preview changes without making them */
183
- dryRun?: boolean;
184
- };
185
- }
186
-
187
- /**
188
- * Plugin interface for extending the i18next toolkit functionality.
189
- * Plugins can hook into various stages of the extraction process.
190
- *
191
- * @example
192
- * ```typescript
193
- * const myPlugin = (): Plugin => ({
194
- * name: 'my-custom-plugin',
195
- *
196
- * setup: async () => {
197
- * console.log('Plugin initialized')
198
- * },
199
- *
200
- * onLoad: (code, filePath) => {
201
- * // Transform code before parsing
202
- * return code.replace(/OLD_PATTERN/g, 'NEW_PATTERN')
203
- * },
204
- *
205
- * onVisitNode: (node, context) => {
206
- * if (node.type === 'CallExpression') {
207
- * // Custom extraction logic
208
- * context.addKey({ key: 'custom.key', defaultValue: 'Custom Value' })
209
- * }
210
- * },
211
- *
212
- * onEnd: async (allKeys) => {
213
- * console.log(`Found ${allKeys.size} total keys`)
214
- * }
215
- * })
216
- * ```
217
- */
218
- export interface Plugin {
219
- /** Unique name for the plugin */
220
- name: string;
221
-
222
- /**
223
- * Custom function to extract keys from an AST expression. Useful
224
- * for plugins that need to extract key patterns from `t(..., options)`
225
- * or `<Trans i18nKey={...} />`.
226
- *
227
- * @param expression - An expression to extract keys from
228
- * @param config - The i18next toolkit configuration object
229
- * @param logger - Logger instance for output
230
- *
231
- * @returns An array of extracted keys
232
- */
233
- extractKeysFromExpression?: (expression: Expression, config: Omit<I18nextToolkitConfig, 'plugins'>, logger: Logger) => string[];
234
-
235
- /**
236
- * Custom function to extract context from an AST expression. Useful
237
- * for plugins that need to extract context patterns from `t('key', { context: ... })`
238
- * or `<Trans i18nKey="key" context={...} />`.
239
- *
240
- * @param expression - An expression to extract context from
241
- * @param config - The i18next toolkit configuration object
242
- * @param logger - Logger instance for output
243
- *
244
- * @returns An array of extracted context values
245
- */
246
- extractContextFromExpression?: (expression: Expression, config: Omit<I18nextToolkitConfig, 'plugins'>, logger: Logger) => string[];
247
-
248
- /**
249
- * Hook called once at the beginning of the extraction process.
250
- * Use for initialization tasks like setting up resources or validating configuration.
251
- */
252
- setup?: () => void | Promise<void>;
253
-
254
- /**
255
- * Hook called for each source file before it's parsed.
256
- * Allows transformation of source code before AST generation.
257
- *
258
- * @param code - The source code content
259
- * @param path - The file path being processed
260
- * @returns The transformed code (or undefined to keep original)
261
- */
262
- onLoad?: (code: string, path: string) => string | Promise<string>;
263
-
264
- /**
265
- * Hook called for each AST node during traversal.
266
- * Enables custom extraction logic by examining syntax nodes.
267
- *
268
- * @param node - The current AST node being visited
269
- * @param context - Context object with helper methods
270
- */
271
- onVisitNode?: (node: Node, context: PluginContext) => void;
272
-
273
- /**
274
- * Hook called after all files have been processed.
275
- * Useful for post-processing, validation, or reporting.
276
- *
277
- * @param keys - Final map of all extracted keys
278
- */
279
- onEnd?: (keys: ExtractedKeysMap) => void | Promise<void>;
280
-
281
- /**
282
- * Hook called after all files have been processed and translation files have been generated.
283
- * Useful for post-processing, validation, or reporting based on the final results.
284
- *
285
- * @param results - Array of translation results with update status and content.
286
- * @param config - The i18next toolkit configuration object.
287
- */
288
- afterSync?: (results: TranslationResult[], config: I18nextToolkitConfig) => void | Promise<void>;
289
- }
290
-
291
- /**
292
- * Represents an extracted translation key with its metadata.
293
- * Contains all information needed to generate translation files.
294
- *
295
- * @example
296
- * ```typescript
297
- * const extractedKey: ExtractedKey = {
298
- * key: 'user.profile.name',
299
- * defaultValue: 'Full Name',
300
- * ns: 'common',
301
- * hasCount: false
302
- * }
303
- * ```
304
- */
305
- export interface ExtractedKey {
306
- /** The translation key (may be nested with separators) */
307
- key: string;
308
-
309
- /** Default value to use in the primary language */
310
- defaultValue?: string;
311
-
312
- /** Namespace this key belongs to */
313
- ns?: string | false;
314
-
315
- /**
316
- * Whether the namespace was implicit (i.e. no explicit ns on the source).
317
- * When true and config.extract.defaultNS === false the key should be treated
318
- * as "no namespace" for output generation (top-level file).
319
- */
320
- nsIsImplicit?: boolean;
321
-
322
- /** Whether this key is used with pluralization (count parameter) */
323
- hasCount?: boolean;
324
-
325
- /** Whether this key is used with ordinal pluralization */
326
- isOrdinal?: boolean;
327
-
328
- /** AST node for options object, used for advanced plural handling in Trans */
329
- optionsNode?: ObjectExpression;
330
-
331
- /** hold the raw context expression from the AST */
332
- contextExpression?: Expression;
333
-
334
- /** Whether the defaultValue was explicitly provided in source code (vs derived from children/key) */
335
- explicitDefault?: boolean;
336
-
337
- /** True when the extractor returned an already-expanded plural form (e.g. "key_one") */
338
- isExpandedPlural?: boolean
339
-
340
- /** Source locations where this key was found (optional, populated by plugins) */
341
- locations?: Array<{
342
- file: string
343
- line?: number
344
- column?: number
345
- }>
346
-
347
- /**
348
- * The base key (without context/plural suffixes) when this key accepts context.
349
- * For example, if the key is 'friend_male' and it has context, this would be 'friend'.
350
- * This is used to preserve all context variants in translation files.
351
- * Empty/undefined if the key doesn't use context.
352
- */
353
- keyAcceptingContext?: string;
354
- }
355
-
356
- /**
357
- * Result of processing translation files for a specific locale and namespace.
358
- * Contains the generated translations and metadata about changes.
359
- *
360
- * @example
361
- * ```typescript
362
- * const result: TranslationResult = {
363
- * path: '/project/locales/en/common.json',
364
- * updated: true,
365
- * newTranslations: { button: { save: 'Save', cancel: 'Cancel' } },
366
- * existingTranslations: { button: { save: 'Save' } }
367
- * }
368
- * ```
369
- */
370
- export interface TranslationResult {
371
- /** Full file system path where the translation file will be written */
372
- path: string;
373
-
374
- /** Whether the file content changed and needs to be written */
375
- updated: boolean;
376
-
377
- /** The new translation object to be written to the file */
378
- newTranslations: Record<string, any>;
379
-
380
- /** The existing translation object that was read from the file */
381
- existingTranslations: Record<string, any>;
382
- }
383
-
384
- /**
385
- * Logger interface for consistent output formatting across the toolkit.
386
- * Implementations can customize how messages are displayed or stored.
387
- *
388
- * @example
389
- * ```typescript
390
- * class FileLogger implements Logger {
391
- * info(message: string) { fs.appendFileSync('info.log', message) }
392
- * warn(message: string) { fs.appendFileSync('warn.log', message) }
393
- * error(message: string) { fs.appendFileSync('error.log', message) }
394
- * }
395
- * ```
396
- */
397
- export interface Logger {
398
- /**
399
- * Logs an informational message.
400
- * @param message - The message to log
401
- */
402
- info(message: string): void;
403
-
404
- /**
405
- * Logs a warning message.
406
- * @param message - The warning message to log
407
- */
408
- warn(message: string, more?: any): void;
409
-
410
- /**
411
- * Logs an error message.
412
- * @param message - The error message to log
413
- */
414
- error(message: string | any): void;
415
- }
416
-
417
- /**
418
- * Context object provided to plugins during AST traversal.
419
- * Provides helper methods for plugins to interact with the extraction process.
420
- *
421
- * @example
422
- * ```typescript
423
- * // Inside a plugin's onVisitNode hook:
424
- * onVisitNode(node, context) {
425
- * if (isCustomTranslationCall(node)) {
426
- * context.addKey({
427
- * key: extractKeyFromNode(node),
428
- * defaultValue: extractDefaultFromNode(node),
429
- * ns: 'custom'
430
- * })
431
- * }
432
- * }
433
- * ```
434
- */
435
- export interface PluginContext {
436
- /**
437
- * Adds a translation key to the extraction results.
438
- * Keys are automatically deduplicated by their namespace:key combination.
439
- *
440
- * @param keyInfo - The extracted key information
441
- */
442
- addKey: (keyInfo: ExtractedKey) => void;
443
-
444
- /** The fully resolved i18next-cli configuration. */
445
- config: I18nextToolkitConfig;
446
-
447
- /** The shared logger instance. */
448
- logger: Logger;
449
-
450
- /**
451
- * Retrieves variable information from the current scope chain.
452
- * Searches from the innermost scope outwards.
453
- * @param name - The variable name to look up (e.g., 't').
454
- * @returns Scope information if found, otherwise undefined.
455
- */
456
- getVarFromScope: (name: string) => ScopeInfo | undefined;
457
- }
458
-
459
- /**
460
- * Represents variable scope information tracked during AST traversal.
461
- * Used to maintain context about translation functions and their configuration.
462
- */
463
- export interface ScopeInfo {
464
- /** Default namespace for translation calls in this scope */
465
- defaultNs?: string;
466
- /** Key prefix to prepend to all translation keys in this scope */
467
- keyPrefix?: string;
468
- }
469
-
470
- /**
471
- * Configuration for useTranslation hook patterns.
472
- * Defines how to extract namespace and key prefix information from hook calls.
473
- *
474
- * @example
475
- * ```typescript
476
- * // For: const { t } = useTranslation('common', { keyPrefix: 'user' })
477
- * const config: UseTranslationHookConfig = {
478
- * name: 'useTranslation',
479
- * nsArg: 0, // namespace is first argument
480
- * keyPrefixArg: 1 // keyPrefix is in second argument (options object)
481
- * }
482
- * ```
483
- */
484
- export interface UseTranslationHookConfig {
485
- /** The name of the hook function (e.g., 'useTranslation', 'getT') */
486
- name: string;
487
- /** Zero-based index of the argument containing the namespace */
488
- nsArg: number;
489
- /** Zero-based index of the argument containing options with keyPrefix */
490
- keyPrefixArg: number;
491
- }
492
-
493
- /**
494
- * Optional hooks for customizing AST visitor behavior during extraction.
495
- * Allows plugins and external code to extend the visitor's capabilities.
496
- *
497
- * @example
498
- * ```typescript
499
- * const hooks: ASTVisitorHooks = {
500
- * onBeforeVisitNode: (node) => {
501
- * console.log(`Visiting ${node.type}`)
502
- * },
503
- *
504
- * resolvePossibleKeyStringValues: (expression) => {
505
- * // Custom logic to extract keys from complex expressions
506
- * if (isCustomKeyExpression(expression)) {
507
- * return ['custom.key.1', 'custom.key.2']
508
- * }
509
- * return []
510
- * }
511
- * }
512
- * ```
513
- */
514
- export interface ASTVisitorHooks {
515
- /**
516
- * Called before visiting each AST node during traversal.
517
- * Useful for logging, debugging, or pre-processing nodes.
518
- *
519
- * @param node - The AST node about to be visited
520
- */
521
- onBeforeVisitNode?: (node: Node) => void
522
-
523
- /**
524
- * Called after visiting each AST node during traversal.
525
- * Useful for cleanup, post-processing, or collecting statistics.
526
- *
527
- * @param node - The AST node that was just visited
528
- */
529
- onAfterVisitNode?: (node: Node) => void
530
-
531
- /**
532
- * Custom resolver for extracting context values from expressions.
533
- * Supplements the built-in expression resolution with plugin-specific logic.
534
- *
535
- * @param expression - The expression to extract context from
536
- * @param returnEmptyStrings - Whether to include empty strings in results
537
- * @returns Array of possible context string values
538
- */
539
- resolvePossibleContextStringValues?: (expression: Expression, returnEmptyStrings?: boolean) => string[]
540
-
541
- /**
542
- * Custom resolver for extracting translation keys from expressions.
543
- * Supplements the built-in expression resolution with plugin-specific logic.
544
- *
545
- * @param expression - The expression to extract keys from
546
- * @param returnEmptyStrings - Whether to include empty strings in results
547
- * @returns Array of possible translation key values
548
- */
549
- resolvePossibleKeyStringValues?: (expression: Expression, returnEmptyStrings?: boolean) => string[]
550
- }
551
-
552
- /**
553
- * Map of extracted translation keys with their metadata.
554
- * Used in plugin hooks like `onEnd` to access all extracted keys.
555
- *
556
- * @example
557
- * ```typescript
558
- * const myPlugin = (): Plugin => ({
559
- * name: 'my-plugin',
560
- * async onEnd(keys: ExtractedKeysMap) {
561
- * console.log(`Found ${keys.size} keys`)
562
- * for (const [uniqueKey, extractedKey] of keys.entries()) {
563
- * // Process each key
564
- * }
565
- * }
566
- * })
567
- * ```
568
- */
569
- export type ExtractedKeysMap = Map<string, ExtractedKey>
570
-
571
- export interface RenameKeyResult {
572
- success: boolean
573
- sourceFiles: Array<{ path: string; changes: number }>
574
- translationFiles: Array<{ path: string; updated: boolean }>
575
- conflicts?: string[]
576
- error?: string
577
- }
@@ -1,45 +0,0 @@
1
- /**
2
- * Resolves the default value for a missing key in secondary languages.
3
- * Supports both string and function-based default values.
4
- *
5
- * @param defaultValue - The configured default value (string or function)
6
- * @param key - The translation key
7
- * @param namespace - The namespace for the key
8
- * @param language - The target language
9
- * @returns The resolved default value
10
- *
11
- * @example
12
- * ```typescript
13
- * // String-based default value
14
- * const result1 = resolveDefaultValue('[MISSING]', 'user.name', 'common', 'de', 'Alice')
15
- * // Returns: '[MISSING]'
16
- *
17
- * // Function-based default value
18
- * const defaultValueFn = (key, ns, lang) => `${lang.toUpperCase()}_${ns}_${key}`
19
- * const result2 = resolveDefaultValue(defaultValueFn, 'user.name', 'common', 'de', 'Alice')
20
- * // Returns: 'DE_common_user.name_Alice'
21
- *
22
- * // Error handling - function throws
23
- * const errorFn = () => { throw new Error('Oops') }
24
- * const result3 = resolveDefaultValue(errorFn, 'user.name', 'common', 'de', 'Alice')
25
- * // Returns: '' (fallback to empty string)
26
- * ```
27
- */
28
- export function resolveDefaultValue (
29
- defaultValue: string | ((key: string, namespace: string, language: string, value: string) => string) | undefined,
30
- key: string,
31
- namespace: string,
32
- language: string,
33
- value?: string
34
- ): string {
35
- if (typeof defaultValue === 'function') {
36
- try {
37
- return defaultValue(key, namespace, language, value || key)
38
- } catch (error) {
39
- // If the function throws an error, fall back to empty string
40
- return ''
41
- }
42
- }
43
-
44
- return defaultValue || ''
45
- }