i18next-cli 1.33.5 → 1.34.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.
Files changed (65) hide show
  1. package/README.md +2 -1
  2. package/dist/cjs/cli.js +271 -1
  3. package/dist/cjs/config.js +211 -1
  4. package/dist/cjs/extractor/core/ast-visitors.js +364 -1
  5. package/dist/cjs/extractor/core/extractor.js +245 -1
  6. package/dist/cjs/extractor/core/key-finder.js +132 -1
  7. package/dist/cjs/extractor/core/translation-manager.js +745 -1
  8. package/dist/cjs/extractor/parsers/ast-utils.js +85 -1
  9. package/dist/cjs/extractor/parsers/call-expression-handler.js +941 -1
  10. package/dist/cjs/extractor/parsers/comment-parser.js +375 -1
  11. package/dist/cjs/extractor/parsers/expression-resolver.js +362 -1
  12. package/dist/cjs/extractor/parsers/jsx-handler.js +492 -1
  13. package/dist/cjs/extractor/parsers/jsx-parser.js +355 -1
  14. package/dist/cjs/extractor/parsers/scope-manager.js +408 -1
  15. package/dist/cjs/extractor/plugin-manager.js +106 -1
  16. package/dist/cjs/heuristic-config.js +99 -1
  17. package/dist/cjs/index.js +28 -1
  18. package/dist/cjs/init.js +174 -1
  19. package/dist/cjs/linter.js +431 -1
  20. package/dist/cjs/locize.js +269 -1
  21. package/dist/cjs/migrator.js +196 -1
  22. package/dist/cjs/rename-key.js +354 -1
  23. package/dist/cjs/status.js +336 -1
  24. package/dist/cjs/syncer.js +120 -1
  25. package/dist/cjs/types-generator.js +165 -1
  26. package/dist/cjs/utils/default-value.js +43 -1
  27. package/dist/cjs/utils/file-utils.js +136 -1
  28. package/dist/cjs/utils/funnel-msg-tracker.js +75 -1
  29. package/dist/cjs/utils/logger.js +36 -1
  30. package/dist/cjs/utils/nested-object.js +124 -1
  31. package/dist/cjs/utils/validation.js +71 -1
  32. package/dist/esm/cli.js +269 -1
  33. package/dist/esm/config.js +206 -1
  34. package/dist/esm/extractor/core/ast-visitors.js +362 -1
  35. package/dist/esm/extractor/core/extractor.js +241 -1
  36. package/dist/esm/extractor/core/key-finder.js +130 -1
  37. package/dist/esm/extractor/core/translation-manager.js +743 -1
  38. package/dist/esm/extractor/parsers/ast-utils.js +80 -1
  39. package/dist/esm/extractor/parsers/call-expression-handler.js +939 -1
  40. package/dist/esm/extractor/parsers/comment-parser.js +373 -1
  41. package/dist/esm/extractor/parsers/expression-resolver.js +360 -1
  42. package/dist/esm/extractor/parsers/jsx-handler.js +490 -1
  43. package/dist/esm/extractor/parsers/jsx-parser.js +334 -1
  44. package/dist/esm/extractor/parsers/scope-manager.js +406 -1
  45. package/dist/esm/extractor/plugin-manager.js +103 -1
  46. package/dist/esm/heuristic-config.js +97 -1
  47. package/dist/esm/index.js +11 -1
  48. package/dist/esm/init.js +172 -1
  49. package/dist/esm/linter.js +425 -1
  50. package/dist/esm/locize.js +265 -1
  51. package/dist/esm/migrator.js +194 -1
  52. package/dist/esm/rename-key.js +352 -1
  53. package/dist/esm/status.js +334 -1
  54. package/dist/esm/syncer.js +118 -1
  55. package/dist/esm/types-generator.js +163 -1
  56. package/dist/esm/utils/default-value.js +41 -1
  57. package/dist/esm/utils/file-utils.js +131 -1
  58. package/dist/esm/utils/funnel-msg-tracker.js +72 -1
  59. package/dist/esm/utils/logger.js +34 -1
  60. package/dist/esm/utils/nested-object.js +120 -1
  61. package/dist/esm/utils/validation.js +68 -1
  62. package/package.json +4 -2
  63. package/types/extractor/core/extractor.d.ts.map +1 -1
  64. package/types/extractor/parsers/jsx-parser.d.ts.map +1 -1
  65. package/types/locize.d.ts.map +1 -1
@@ -1 +1,132 @@
1
- "use strict";var e=require("glob"),r=require("./extractor.js"),t=require("../../utils/logger.js"),o=require("../plugin-manager.js"),n=require("./ast-visitors.js"),s=require("../parsers/expression-resolver.js");exports.findKeys=async function(i,a=new t.ConsoleLogger){const{plugins:l,...c}=i,u=l||[],g=await async function(r){const t=["node_modules/**"],o=Array.isArray(r.extract.ignore)?r.extract.ignore:r.extract.ignore?[r.extract.ignore]:[];return await e.glob(r.extract.input,{ignore:[...t,...o],cwd:process.cwd()})}(i),x=new Map,p=o.createPluginContext(x,u,c,a),d={onBeforeVisitNode:e=>{for(const r of u)try{r.onVisitNode?.(e,p)}catch(e){a.warn(`Plugin ${r.name} onVisitNode failed:`,e)}},resolvePossibleKeyStringValues:e=>u.flatMap(r=>{try{return r.extractKeysFromExpression?.(e,i,a)??[]}catch(e){return a.warn(`Plugin ${r.name} extractKeysFromExpression failed:`,e),[]}}),resolvePossibleContextStringValues:e=>u.flatMap(r=>{try{return r.extractContextFromExpression?.(e,i,a)??[]}catch(e){return a.warn(`Plugin ${r.name} extractContextFromExpression failed:`,e),[]}})},f=new s.ExpressionResolver(d),w=new n.ASTVisitors(c,p,a,d,f);p.getVarFromScope=w.getVarFromScope.bind(w),await o.initializePlugins(u);for(const e of g)await r.processFile(e,u,w,p,c,a);for(const e of u)await(e.onEnd?.(x));const y=c.extract?.pluralSeparator??"_",m=["zero","one","two","few","many","other"];for(const e of x.values()){const r=String(e.key).split(y),t=r[r.length-1],o=r.length>=3&&"ordinal"===r[r.length-2];(m.includes(t)||o&&m.includes(t))&&(e.isExpandedPlural=!0)}return{allKeys:x,objectKeys:w.objectKeys}};
1
+ 'use strict';
2
+
3
+ var glob = require('glob');
4
+ var extractor = require('./extractor.js');
5
+ var logger = require('../../utils/logger.js');
6
+ var pluginManager = require('../plugin-manager.js');
7
+ var astVisitors = require('./ast-visitors.js');
8
+ var expressionResolver = require('../parsers/expression-resolver.js');
9
+
10
+ /**
11
+ * Main function for finding translation keys across all source files in a project.
12
+ *
13
+ * This function orchestrates the key extraction process:
14
+ * 1. Processes source files based on input patterns
15
+ * 2. Initializes and manages plugins
16
+ * 3. Processes each file through AST parsing and key extraction
17
+ * 4. Runs plugin lifecycle hooks
18
+ * 5. Returns a deduplicated map of all found keys
19
+ *
20
+ * @param config - The i18next toolkit configuration object
21
+ * @param logger - Logger instance for output (defaults to ConsoleLogger)
22
+ * @returns Promise resolving to a Map of unique translation keys with metadata
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const config = {
27
+ * extract: {
28
+ * input: ['src/**\/*.{ts,tsx}'],
29
+ * functions: ['t', '*.t'],
30
+ * transComponents: ['Trans']
31
+ * }
32
+ * }
33
+ *
34
+ * const keys = await findKeys(config)
35
+ * console.log(`Found ${keys.size} unique translation keys`)
36
+ * ```
37
+ */
38
+ async function findKeys(config, logger$1 = new logger.ConsoleLogger()) {
39
+ const { plugins: pluginsOrUndefined, ...otherConfig } = config;
40
+ const plugins = pluginsOrUndefined || [];
41
+ const sourceFiles = await processSourceFiles(config);
42
+ const allKeys = new Map();
43
+ // 1. Create the base context with config and logger.
44
+ const pluginContext = pluginManager.createPluginContext(allKeys, plugins, otherConfig, logger$1);
45
+ // 2. Create hooks for plugins to hook into AST
46
+ const hooks = {
47
+ onBeforeVisitNode: (node) => {
48
+ for (const plugin of plugins) {
49
+ try {
50
+ plugin.onVisitNode?.(node, pluginContext);
51
+ }
52
+ catch (err) {
53
+ logger$1.warn(`Plugin ${plugin.name} onVisitNode failed:`, err);
54
+ }
55
+ }
56
+ },
57
+ resolvePossibleKeyStringValues: (expression) => {
58
+ return plugins.flatMap(plugin => {
59
+ try {
60
+ return plugin.extractKeysFromExpression?.(expression, config, logger$1) ?? [];
61
+ }
62
+ catch (err) {
63
+ logger$1.warn(`Plugin ${plugin.name} extractKeysFromExpression failed:`, err);
64
+ return [];
65
+ }
66
+ });
67
+ },
68
+ resolvePossibleContextStringValues: (expression) => {
69
+ return plugins.flatMap(plugin => {
70
+ try {
71
+ return plugin.extractContextFromExpression?.(expression, config, logger$1) ?? [];
72
+ }
73
+ catch (err) {
74
+ logger$1.warn(`Plugin ${plugin.name} extractContextFromExpression failed:`, err);
75
+ return [];
76
+ }
77
+ });
78
+ },
79
+ };
80
+ // 3. Create the visitor instance, passing it the context.
81
+ // Use a shared ExpressionResolver so captured enums/objects in one file are available when resolving MemberExpressions
82
+ const sharedExpressionResolver = new expressionResolver.ExpressionResolver(hooks);
83
+ const astVisitors$1 = new astVisitors.ASTVisitors(otherConfig, pluginContext, logger$1, hooks, sharedExpressionResolver);
84
+ // 4. "Wire up" the visitor's scope method to the context.
85
+ // This avoids a circular dependency while giving plugins access to the scope.
86
+ pluginContext.getVarFromScope = astVisitors$1.getVarFromScope.bind(astVisitors$1);
87
+ // 5. Initialize plugins
88
+ await pluginManager.initializePlugins(plugins);
89
+ // 6. Process each file
90
+ for (const file of sourceFiles) {
91
+ await extractor.processFile(file, plugins, astVisitors$1, pluginContext, otherConfig, logger$1);
92
+ }
93
+ // 7. Run onEnd hooks
94
+ for (const plugin of plugins) {
95
+ await plugin.onEnd?.(allKeys);
96
+ }
97
+ // Normalization: mark already-expanded plural keys
98
+ const pluralSeparator = otherConfig.extract?.pluralSeparator ?? '_';
99
+ const categories = ['zero', 'one', 'two', 'few', 'many', 'other'];
100
+ for (const ek of allKeys.values()) {
101
+ const parts = String(ek.key).split(pluralSeparator);
102
+ const last = parts[parts.length - 1];
103
+ const isOrdinal = parts.length >= 3 && parts[parts.length - 2] === 'ordinal';
104
+ if (categories.includes(last) || (isOrdinal && categories.includes(last))) {
105
+ ek.isExpandedPlural = true;
106
+ }
107
+ }
108
+ return { allKeys, objectKeys: astVisitors$1.objectKeys };
109
+ }
110
+ /**
111
+ * Processes source files using glob patterns from configuration.
112
+ * Excludes node_modules by default and resolves relative to current working directory.
113
+ *
114
+ * @param config - The i18next toolkit configuration object
115
+ * @returns Promise resolving to array of file paths to process
116
+ *
117
+ * @internal
118
+ */
119
+ async function processSourceFiles(config) {
120
+ const defaultIgnore = ['node_modules/**'];
121
+ // Normalize the user's ignore option into an array
122
+ const userIgnore = Array.isArray(config.extract.ignore)
123
+ ? config.extract.ignore
124
+ : config.extract.ignore ? [config.extract.ignore] : [];
125
+ return await glob.glob(config.extract.input, {
126
+ // Combine default ignore patterns with user-configured ones
127
+ ignore: [...defaultIgnore, ...userIgnore],
128
+ cwd: process.cwd(),
129
+ });
130
+ }
131
+
132
+ exports.findKeys = findKeys;