i18ntk 1.10.2 → 2.0.3

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 (108) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +141 -1191
  3. package/main/i18ntk-analyze.js +65 -84
  4. package/main/i18ntk-backup-class.js +420 -0
  5. package/main/i18ntk-backup.js +3 -3
  6. package/main/i18ntk-complete.js +90 -65
  7. package/main/i18ntk-doctor.js +123 -103
  8. package/main/i18ntk-fixer.js +61 -725
  9. package/main/i18ntk-go.js +14 -15
  10. package/main/i18ntk-init.js +77 -26
  11. package/main/i18ntk-java.js +27 -32
  12. package/main/i18ntk-js.js +70 -68
  13. package/main/i18ntk-manage.js +129 -30
  14. package/main/i18ntk-php.js +75 -75
  15. package/main/i18ntk-py.js +55 -56
  16. package/main/i18ntk-scanner.js +59 -57
  17. package/main/i18ntk-setup.js +9 -404
  18. package/main/i18ntk-sizing.js +6 -6
  19. package/main/i18ntk-summary.js +21 -18
  20. package/main/i18ntk-ui.js +11 -10
  21. package/main/i18ntk-usage.js +54 -18
  22. package/main/i18ntk-validate.js +13 -13
  23. package/main/manage/commands/AnalyzeCommand.js +1124 -0
  24. package/main/manage/commands/BackupCommand.js +62 -0
  25. package/main/manage/commands/CommandRouter.js +295 -0
  26. package/main/manage/commands/CompleteCommand.js +61 -0
  27. package/main/manage/commands/DoctorCommand.js +60 -0
  28. package/main/manage/commands/FixerCommand.js +624 -0
  29. package/main/manage/commands/InitCommand.js +62 -0
  30. package/main/manage/commands/ScannerCommand.js +654 -0
  31. package/main/manage/commands/SizingCommand.js +60 -0
  32. package/main/manage/commands/SummaryCommand.js +61 -0
  33. package/main/manage/commands/UsageCommand.js +60 -0
  34. package/main/manage/commands/ValidateCommand.js +978 -0
  35. package/main/manage/index-fixed.js +1447 -0
  36. package/main/manage/index.js +1462 -0
  37. package/main/manage/managers/DebugMenu.js +140 -0
  38. package/main/manage/managers/InteractiveMenu.js +177 -0
  39. package/main/manage/managers/LanguageMenu.js +62 -0
  40. package/main/manage/managers/SettingsMenu.js +53 -0
  41. package/main/manage/services/AuthenticationService.js +263 -0
  42. package/main/manage/services/ConfigurationService-fixed.js +449 -0
  43. package/main/manage/services/ConfigurationService.js +449 -0
  44. package/main/manage/services/FileManagementService.js +368 -0
  45. package/main/manage/services/FrameworkDetectionService.js +458 -0
  46. package/main/manage/services/InitService.js +1051 -0
  47. package/main/manage/services/SetupService.js +462 -0
  48. package/main/manage/services/SummaryService.js +450 -0
  49. package/main/manage/services/UsageService.js +1502 -0
  50. package/package.json +32 -29
  51. package/runtime/enhanced.d.ts +221 -221
  52. package/runtime/index.d.ts +29 -29
  53. package/runtime/index.full.d.ts +331 -331
  54. package/runtime/index.js +7 -6
  55. package/scripts/build-lite.js +17 -17
  56. package/scripts/deprecate-versions.js +23 -6
  57. package/scripts/export-translations.js +5 -5
  58. package/scripts/fix-all-i18n.js +3 -3
  59. package/scripts/fix-and-purify-i18n.js +3 -2
  60. package/scripts/fix-locale-control-chars.js +110 -0
  61. package/scripts/lint-locales.js +80 -0
  62. package/scripts/locale-optimizer.js +8 -8
  63. package/scripts/prepublish.js +21 -21
  64. package/scripts/security-check.js +117 -117
  65. package/scripts/sync-translations.js +4 -4
  66. package/scripts/sync-ui-locales.js +9 -8
  67. package/scripts/validate-all-translations.js +8 -7
  68. package/scripts/verify-deprecations.js +157 -161
  69. package/scripts/verify-translations.js +6 -5
  70. package/settings/i18ntk-config.json +282 -282
  71. package/settings/language-config.json +5 -5
  72. package/settings/settings-cli.js +9 -9
  73. package/settings/settings-manager.js +18 -18
  74. package/ui-locales/de.json +2417 -2348
  75. package/ui-locales/en.json +2415 -2352
  76. package/ui-locales/es.json +2425 -2353
  77. package/ui-locales/fr.json +2418 -2348
  78. package/ui-locales/ja.json +2463 -2361
  79. package/ui-locales/ru.json +2463 -2359
  80. package/ui-locales/zh.json +2418 -2351
  81. package/utils/admin-auth.js +2 -2
  82. package/utils/admin-cli.js +297 -297
  83. package/utils/admin-pin.js +9 -9
  84. package/utils/cli-helper.js +9 -9
  85. package/utils/config-helper.js +73 -104
  86. package/utils/config-manager.js +204 -171
  87. package/utils/config.js +5 -4
  88. package/utils/env-manager.js +249 -263
  89. package/utils/framework-detector.js +27 -24
  90. package/utils/i18n-helper.js +85 -41
  91. package/utils/init-helper.js +152 -94
  92. package/utils/json-output.js +98 -98
  93. package/utils/mini-commander.js +179 -0
  94. package/utils/missing-key-validator.js +5 -5
  95. package/utils/plugin-loader.js +40 -29
  96. package/utils/prompt.js +14 -44
  97. package/utils/safe-json.js +40 -0
  98. package/utils/secure-errors.js +3 -3
  99. package/utils/security-check-improved.js +390 -0
  100. package/utils/security-config.js +5 -5
  101. package/utils/security-fixed.js +607 -0
  102. package/utils/security.js +652 -602
  103. package/utils/setup-enforcer.js +136 -44
  104. package/utils/setup-validator.js +33 -32
  105. package/utils/ultra-performance-optimizer.js +11 -9
  106. package/utils/watch-locales.js +2 -1
  107. package/utils/prompt-fixed.js +0 -55
  108. package/utils/security-check.js +0 -454
@@ -1,270 +1,256 @@
1
- /**
2
- * Centralized Environment Variable Manager
3
- *
4
- * This module provides secure access to a fixed allowlist of environment variables.
5
- * Only explicitly defined environment variables are accessible, all others are ignored.
6
- * No secrets or sensitive data should ever be stored in environment variables.
7
- */
8
-
9
- const ALLOWED_ENV_VARS = {
10
- // Logging and output
11
- 'I18NTK_LOG_LEVEL': {
12
- default: 'error',
13
- validate: (value) => ['error', 'warn', 'info', 'debug', 'silent'].includes(value.toLowerCase()),
14
- transform: (value) => value.toLowerCase()
15
- },
16
-
17
- 'I18NTK_OUTDIR': {
18
- default: './i18ntk-reports',
19
- validate: (value) => typeof value === 'string' && value.length > 0,
20
- transform: (value) => value.trim()
21
- },
22
-
23
- // UI and interaction
24
- 'I18NTK_LANG': {
1
+ /**
2
+ * Centralized Environment Variable Manager
3
+ *
4
+ * This module provides secure access to a fixed allowlist of environment variables.
5
+ * Only explicitly defined environment variables are accessible, all others are ignored.
6
+ * No secrets or sensitive data should ever be stored in environment variables.
7
+ */
8
+
9
+ const ALLOWED_ENV_VARS = {
10
+ // Logging and output
11
+ 'I18NTK_LOG_LEVEL': {
12
+ default: 'error',
13
+ validate: (value) => ['error', 'warn', 'info', 'debug', 'silent'].includes(value.toLowerCase()),
14
+ transform: (value) => value.toLowerCase()
15
+ },
16
+
17
+ 'I18NTK_OUTDIR': {
18
+ default: './i18ntk-reports',
19
+ validate: (value) => typeof value === 'string' && value.length > 0,
20
+ transform: (value) => value.trim()
21
+ },
22
+
23
+ // UI and interaction
24
+ 'I18NTK_UI_LANGUAGE': {
25
25
  default: 'en',
26
26
  validate: (value) => ['en', 'de', 'es', 'fr', 'ru', 'ja', 'zh'].includes(value.toLowerCase()),
27
27
  transform: (value) => value.toLowerCase()
28
28
  },
29
-
30
- 'I18NTK_SILENT': {
31
- default: 'false',
32
- validate: (value) => ['true', 'false', '1', '0', 'yes', 'no'].includes(value.toLowerCase()),
33
- transform: (value) => {
34
- const lower = value.toLowerCase();
35
- return lower === 'true' || lower === '1' || lower === 'yes' ? 'true' : 'false';
36
- }
37
- },
38
-
39
- // Debug and development
40
- 'I18NTK_DEBUG_LOCALES': {
41
- default: '0',
42
- validate: (value) => ['0', '1', 'true', 'false'].includes(value.toLowerCase()),
43
- transform: (value) => {
44
- const lower = value.toLowerCase();
45
- return lower === '1' || lower === 'true' ? '1' : '0';
46
- }
47
- },
48
-
49
- // Runtime configuration
50
- 'I18NTK_RUNTIME_DIR': {
51
- default: null,
52
- validate: (value) => typeof value === 'string',
53
- transform: (value) => value.trim() || null
54
- },
55
-
56
- 'I18NTK_I18N_DIR': {
57
- default: './locales',
58
- validate: (value) => typeof value === 'string' && value.length > 0,
59
- transform: (value) => value.trim()
60
- },
61
-
62
- 'I18NTK_SOURCE_DIR': {
63
- default: './locales',
64
- validate: (value) => typeof value === 'string' && value.length > 0,
65
- transform: (value) => value.trim()
66
- },
67
-
68
- 'I18NTK_PROJECT_ROOT': {
69
- default: '.',
70
- validate: (value) => typeof value === 'string' && value.length > 0,
71
- transform: (value) => value.trim()
72
- },
73
-
74
- // Framework detection
75
- 'I18NTK_FRAMEWORK_PREFERENCE': {
76
- default: 'auto',
77
- validate: (value) => ['auto', 'vanilla', 'react', 'vue', 'angular', 'svelte', 'i18next', 'nuxt', 'next', 'django', 'flask', 'fastapi', 'spring-boot', 'laravel'].includes(value.toLowerCase()),
78
- transform: (value) => value.toLowerCase()
79
- },
80
-
81
- 'I18NTK_FRAMEWORK_FALLBACK': {
82
- default: 'vanilla',
83
- validate: (value) => ['vanilla', 'react', 'vue', 'angular', 'svelte', 'i18next', 'nuxt', 'next', 'django', 'flask', 'fastapi', 'spring-boot', 'laravel'].includes(value.toLowerCase()),
84
- transform: (value) => value.toLowerCase()
85
- },
86
-
87
- 'I18NTK_FRAMEWORK_DETECT': {
88
- default: 'true',
89
- validate: (value) => ['true', 'false', '1', '0', 'yes', 'no'].includes(value.toLowerCase()),
90
- transform: (value) => {
91
- const lower = value.toLowerCase();
92
- return lower === 'true' || lower === '1' || lower === 'yes' ? 'true' : 'false';
93
- }
94
- }
95
- };
96
-
97
- // Security: Block access to sensitive environment variables
98
- const BLOCKED_PATTERNS = [
99
- /^SECRET/i,
100
- /^PASSWORD/i,
101
- /^KEY/i,
102
- /^TOKEN/i,
103
- /^API_KEY/i,
104
- /^PRIVATE/i,
105
- /^AUTH/i,
106
- /^CREDENTIAL/i,
107
- /^AWS_/i,
108
- /^GITHUB_/i,
109
- /^NPM_/i,
110
- /^NODE_/i,
111
- /^PATH$/,
112
- /^HOME$/,
113
- /^USER$/,
114
- /^USERNAME$/,
115
- /^SHELL$/,
116
- /^TERM$/,
117
- /^DISPLAY$/,
118
- /^LANG$/,
119
- /^LC_/i
120
- ];
121
-
122
- class EnvironmentManager {
123
- constructor() {
124
- this._cache = new Map();
125
- this._validated = new Set();
126
- }
127
-
128
- /**
129
- * Get a validated environment variable value
130
- * @param {string} name - Environment variable name
131
- * @returns {string|null} - Validated value or null if not allowed
132
- */
133
- get(name) {
134
- // Only allow explicitly defined variables
135
- if (!ALLOWED_ENV_VARS[name]) {
136
- return null;
137
- }
138
-
139
- // Check cache first
140
- if (this._cache.has(name)) {
141
- return this._cache.get(name);
142
- }
143
-
144
- const definition = ALLOWED_ENV_VARS[name];
145
- const rawValue = process.env[name];
146
-
147
- // Use default if not set
148
- if (rawValue === undefined || rawValue === null || rawValue === '') {
149
- this._cache.set(name, definition.default);
150
- return definition.default;
151
- }
152
-
153
- // Validate and transform
154
- try {
155
- const transformed = definition.transform(rawValue);
156
-
157
- if (!definition.validate(transformed)) {
158
- console.warn(`[i18ntk] Invalid value for ${name}: "${rawValue}". Using default: ${definition.default}`);
159
- this._cache.set(name, definition.default);
160
- return definition.default;
161
- }
162
-
163
- this._cache.set(name, transformed);
164
- this._validated.add(name);
165
- return transformed;
166
- } catch (error) {
167
- console.warn(`[i18ntk] Error processing ${name}: ${error.message}. Using default: ${definition.default}`);
168
- this._cache.set(name, definition.default);
169
- return definition.default;
170
- }
171
- }
172
-
173
- /**
174
- * Check if an environment variable is allowed
175
- * @param {string} name - Environment variable name
176
- * @returns {boolean} - True if allowed
177
- */
178
- isAllowed(name) {
179
- return !!ALLOWED_ENV_VARS[name];
180
- }
181
-
182
- /**
183
- * Get all allowed environment variables with their current values
184
- * @returns {Object} - Object with variable names as keys and values
185
- */
186
- getAll() {
187
- const result = {};
188
- for (const name of Object.keys(ALLOWED_ENV_VARS)) {
189
- result[name] = this.get(name);
190
- }
191
- return result;
192
- }
193
-
194
- /**
195
- * Get documentation for all allowed environment variables
196
- * @returns {Array} - Array of documentation objects
197
- */
198
- getDocumentation() {
199
- return Object.entries(ALLOWED_ENV_VARS).map(([name, definition]) => ({
200
- name,
201
- default: definition.default,
202
- description: this._getDescription(name)
203
- }));
204
- }
205
-
206
- /**
207
- * Clear the cache (for testing)
208
- */
209
- clearCache() {
210
- this._cache.clear();
211
- this._validated.clear();
212
- }
213
-
214
- /**
215
- * Check if a variable name matches blocked patterns
216
- * @param {string} name - Variable name to check
217
- * @returns {boolean} - True if blocked
218
- */
219
- isBlocked(name) {
220
- return BLOCKED_PATTERNS.some(pattern => pattern.test(name));
221
- }
222
-
223
- /**
224
- * Get human-readable description for an environment variable
225
- * @param {string} name - Environment variable name
226
- * @returns {string} - Description
227
- */
228
- _getDescription(name) {
229
- const descriptions = {
230
- 'I18NTK_LOG_LEVEL': 'Logging level (error, warn, info, debug, silent)',
231
- 'I18NTK_OUTDIR': 'Output directory for reports and generated files',
232
- 'I18NTK_LANG': 'UI language (en, de, es, fr, ru, ja, zh)',
233
- 'I18NTK_SILENT': 'Run in silent mode without interactive prompts',
234
- 'I18NTK_DEBUG_LOCALES': 'Enable debug logging for locale loading',
235
- 'I18NTK_RUNTIME_DIR': 'Custom runtime directory path',
236
- 'I18NTK_I18N_DIR': 'Directory containing i18n/locale files',
237
- 'I18NTK_SOURCE_DIR': 'Source directory for scanning',
238
- 'I18NTK_PROJECT_ROOT': 'Project root directory',
239
- 'I18NTK_FRAMEWORK_PREFERENCE': 'Preferred framework (auto, react, vue, etc.)',
240
- 'I18NTK_FRAMEWORK_FALLBACK': 'Fallback framework when auto-detection fails',
241
- 'I18NTK_FRAMEWORK_DETECT': 'Enable automatic framework detection'
242
- };
243
-
244
- return descriptions[name] || 'Configuration option';
245
- }
246
- }
247
-
248
- // Create singleton instance
249
- const envManager = new EnvironmentManager();
250
-
251
- // Security check: Log any attempts to access blocked variables
252
- if (process.env.NODE_ENV === 'development' || process.env.DEBUG) {
253
- const originalEnv = process.env;
254
- process.env = new Proxy(originalEnv, {
255
- get(target, prop) {
256
- if (typeof prop === 'string' && envManager.isBlocked(prop)) {
257
- console.warn(`[i18ntk] Security: Blocked access to sensitive environment variable: ${prop}`);
258
- return undefined;
259
- }
260
- return target[prop];
261
- }
262
- });
263
- }
264
-
29
+
30
+ 'I18NTK_SILENT': {
31
+ default: 'false',
32
+ validate: (value) => ['true', 'false', '1', '0', 'yes', 'no'].includes(value.toLowerCase()),
33
+ transform: (value) => {
34
+ const lower = value.toLowerCase();
35
+ return lower === 'true' || lower === '1' || lower === 'yes' ? 'true' : 'false';
36
+ }
37
+ },
38
+
39
+ // Debug and development
40
+ 'I18NTK_DEBUG_LOCALES': {
41
+ default: '0',
42
+ validate: (value) => ['0', '1', 'true', 'false'].includes(value.toLowerCase()),
43
+ transform: (value) => {
44
+ const lower = value.toLowerCase();
45
+ return lower === '1' || lower === 'true' ? '1' : '0';
46
+ }
47
+ },
48
+
49
+ // Runtime configuration
50
+ 'I18NTK_RUNTIME_DIR': {
51
+ default: null,
52
+ validate: (value) => typeof value === 'string',
53
+ transform: (value) => value.trim() || null
54
+ },
55
+
56
+ 'I18NTK_I18N_DIR': {
57
+ default: './locales',
58
+ validate: (value) => typeof value === 'string' && value.length > 0,
59
+ transform: (value) => value.trim()
60
+ },
61
+
62
+ 'I18NTK_SOURCE_DIR': {
63
+ default: './locales',
64
+ validate: (value) => typeof value === 'string' && value.length > 0,
65
+ transform: (value) => value.trim()
66
+ },
67
+
68
+ 'I18NTK_PROJECT_ROOT': {
69
+ default: '.',
70
+ validate: (value) => typeof value === 'string' && value.length > 0,
71
+ transform: (value) => value.trim()
72
+ },
73
+
74
+ // Framework detection
75
+ 'I18NTK_FRAMEWORK_PREFERENCE': {
76
+ default: 'auto',
77
+ validate: (value) => ['auto', 'vanilla', 'react', 'vue', 'angular', 'svelte', 'i18next', 'nuxt', 'next', 'django', 'flask', 'fastapi', 'spring-boot', 'laravel'].includes(value.toLowerCase()),
78
+ transform: (value) => value.toLowerCase()
79
+ },
80
+
81
+ 'I18NTK_FRAMEWORK_FALLBACK': {
82
+ default: 'vanilla',
83
+ validate: (value) => ['vanilla', 'react', 'vue', 'angular', 'svelte', 'i18next', 'nuxt', 'next', 'django', 'flask', 'fastapi', 'spring-boot', 'laravel'].includes(value.toLowerCase()),
84
+ transform: (value) => value.toLowerCase()
85
+ },
86
+
87
+ 'I18NTK_FRAMEWORK_DETECT': {
88
+ default: 'true',
89
+ validate: (value) => ['true', 'false', '1', '0', 'yes', 'no'].includes(value.toLowerCase()),
90
+ transform: (value) => {
91
+ const lower = value.toLowerCase();
92
+ return lower === 'true' || lower === '1' || lower === 'yes' ? 'true' : 'false';
93
+ }
94
+ }
95
+ };
96
+
97
+ // Security: Block access to sensitive environment variables
98
+ const BLOCKED_PATTERNS = [
99
+ /^SECRET/i,
100
+ /^PASSWORD/i,
101
+ /^KEY/i,
102
+ /^TOKEN/i,
103
+ /^API_KEY/i,
104
+ /^PRIVATE/i,
105
+ /^AUTH/i,
106
+ /^CREDENTIAL/i,
107
+ /^AWS_/i,
108
+ /^GITHUB_/i,
109
+ /^NPM_/i,
110
+ /^NODE_/i,
111
+ /^PATH$/,
112
+ /^HOME$/,
113
+ /^USER$/,
114
+ /^USERNAME$/,
115
+ /^SHELL$/,
116
+ /^TERM$/,
117
+ /^DISPLAY$/,
118
+ /^LANG$/,
119
+ /^LC_/i
120
+ ];
121
+
122
+ class EnvironmentManager {
123
+ constructor() {
124
+ this._cache = new Map();
125
+ this._validated = new Set();
126
+ }
127
+
128
+ /**
129
+ * Get a validated environment variable value
130
+ * @param {string} name - Environment variable name
131
+ * @returns {string|null} - Validated value or null if not allowed
132
+ */
133
+ get(name) {
134
+ // Only allow explicitly defined variables
135
+ if (!ALLOWED_ENV_VARS[name]) {
136
+ return null;
137
+ }
138
+
139
+ // Check cache first
140
+ if (this._cache.has(name)) {
141
+ return this._cache.get(name);
142
+ }
143
+
144
+ const definition = ALLOWED_ENV_VARS[name];
145
+ const rawValue = process.env[name];
146
+
147
+ // Use default if not set
148
+ if (rawValue === undefined || rawValue === null || rawValue === '') {
149
+ this._cache.set(name, definition.default);
150
+ return definition.default;
151
+ }
152
+
153
+ // Validate and transform
154
+ try {
155
+ const transformed = definition.transform(rawValue);
156
+
157
+ if (!definition.validate(transformed)) {
158
+ console.warn(`[i18ntk] Invalid value for ${name}: "${rawValue}". Using default: ${definition.default}`);
159
+ this._cache.set(name, definition.default);
160
+ return definition.default;
161
+ }
162
+
163
+ this._cache.set(name, transformed);
164
+ this._validated.add(name);
165
+ return transformed;
166
+ } catch (error) {
167
+ console.warn(`[i18ntk] Error processing ${name}: ${error.message}. Using default: ${definition.default}`);
168
+ this._cache.set(name, definition.default);
169
+ return definition.default;
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Check if an environment variable is allowed
175
+ * @param {string} name - Environment variable name
176
+ * @returns {boolean} - True if allowed
177
+ */
178
+ isAllowed(name) {
179
+ return !!ALLOWED_ENV_VARS[name];
180
+ }
181
+
182
+ /**
183
+ * Get all allowed environment variables with their current values
184
+ * @returns {Object} - Object with variable names as keys and values
185
+ */
186
+ getAll() {
187
+ const result = {};
188
+ for (const name of Object.keys(ALLOWED_ENV_VARS)) {
189
+ result[name] = this.get(name);
190
+ }
191
+ return result;
192
+ }
193
+
194
+ /**
195
+ * Get documentation for all allowed environment variables
196
+ * @returns {Array} - Array of documentation objects
197
+ */
198
+ getDocumentation() {
199
+ return Object.entries(ALLOWED_ENV_VARS).map(([name, definition]) => ({
200
+ name,
201
+ default: definition.default,
202
+ description: this._getDescription(name)
203
+ }));
204
+ }
205
+
206
+ /**
207
+ * Clear the cache (for testing)
208
+ */
209
+ clearCache() {
210
+ this._cache.clear();
211
+ this._validated.clear();
212
+ }
213
+
214
+ /**
215
+ * Check if a variable name matches blocked patterns
216
+ * @param {string} name - Variable name to check
217
+ * @returns {boolean} - True if blocked
218
+ */
219
+ isBlocked(name) {
220
+ return BLOCKED_PATTERNS.some(pattern => pattern.test(name));
221
+ }
222
+
223
+ /**
224
+ * Get human-readable description for an environment variable
225
+ * @param {string} name - Environment variable name
226
+ * @returns {string} - Description
227
+ */
228
+ _getDescription(name) {
229
+ const descriptions = {
230
+ 'I18NTK_LOG_LEVEL': 'Logging level (error, warn, info, debug, silent)',
231
+ 'I18NTK_OUTDIR': 'Output directory for reports and generated files',
232
+ 'I18NTK_UI_LANGUAGE': 'UI language (en, de, es, fr, ru, ja, zh)',
233
+ 'I18NTK_SILENT': 'Run in silent mode without interactive prompts',
234
+ 'I18NTK_DEBUG_LOCALES': 'Enable debug logging for locale loading',
235
+ 'I18NTK_RUNTIME_DIR': 'Custom runtime directory path',
236
+ 'I18NTK_I18N_DIR': 'Directory containing i18n/locale files',
237
+ 'I18NTK_SOURCE_DIR': 'Source directory for scanning',
238
+ 'I18NTK_PROJECT_ROOT': 'Project root directory',
239
+ 'I18NTK_FRAMEWORK_PREFERENCE': 'Preferred framework (auto, react, vue, etc.)',
240
+ 'I18NTK_FRAMEWORK_FALLBACK': 'Fallback framework when auto-detection fails',
241
+ 'I18NTK_FRAMEWORK_DETECT': 'Enable automatic framework detection'
242
+ };
243
+
244
+ return descriptions[name] || 'Configuration option';
245
+ }
246
+ }
247
+
248
+ // Create singleton instance
249
+ const envManager = new EnvironmentManager();
250
+
265
251
  module.exports = {
266
252
  EnvironmentManager,
267
253
  envManager,
268
- ALLOWED_ENV_VARS,
269
- BLOCKED_PATTERNS
270
- };
254
+ ALLOWED_ENV_VARS,
255
+ BLOCKED_PATTERNS
256
+ };
@@ -1,6 +1,6 @@
1
- const fs = require('fs');
2
1
  const path = require('path');
3
2
  const { gte } = require('./version-utils');
3
+ const SecurityUtils = require('./security');
4
4
 
5
5
  // Framework compatibility information
6
6
  const FRAMEWORK_COMPATIBILITY = {
@@ -38,9 +38,9 @@ const FRAMEWORKS = {
38
38
  configFilePatterns: [
39
39
  /i18n\.(js|ts)$/,
40
40
  /i18ntk\.config\.(js|ts)$/,
41
- /\.i18nrc(\.(js|json))?$/
41
+ /\.i18nrc(\.(js|json))?$/,
42
42
  ],
43
- setupGuide: 'https://github.com/vladnosiv/i18n-management-toolkit',
43
+ setupGuide: 'Refer to the official i18ntk documentation on GitHub for setup instructions.',
44
44
  priority: 100, // Higher priority to detect before other frameworks
45
45
  ignore: [
46
46
  'node_modules/**',
@@ -52,7 +52,7 @@ const FRAMEWORKS = {
52
52
  '**/*.test.{js,jsx,ts,tsx}'
53
53
  ]
54
54
  },
55
-
55
+
56
56
  // Vue i18n has highest specificity due to its unique syntax
57
57
  'vue-i18n': {
58
58
  name: 'vue-i18n',
@@ -66,7 +66,7 @@ const FRAMEWORKS = {
66
66
  ],
67
67
  ignore: ['node_modules/**']
68
68
  },
69
-
69
+
70
70
  // React i18next has medium specificity
71
71
  'react-i18next': {
72
72
  name: 'React i18next',
@@ -76,9 +76,9 @@ const FRAMEWORKS = {
76
76
  regex: /\b(?:useTranslation|withTranslation|Trans|I18n|i18n\.t|t\(?=\s*[`'"])/,
77
77
  configFile: 'i18n.js',
78
78
  configFilePatterns: [/i18n\.(js|ts)$/, /i18next\.config\.(js|ts)$/],
79
- setupGuide: 'https://react.i18next.com/'
79
+ setupGuide: 'Refer to the official react-i18next documentation for setup instructions.'
80
80
  },
81
-
81
+
82
82
  // Base i18next has lowest specificity
83
83
  'i18next': {
84
84
  name: 'i18next',
@@ -246,10 +246,10 @@ const FRAMEWORKS = {
246
246
  'test/tmp/**'
247
247
  ]
248
248
  },
249
- go: {
250
- name: 'go',
251
- deps: ['golang.org/x/text/language', 'github.com/nicksnyder/go-i18n/v2/i18n'],
252
- globs: ['**/*.go'],
249
+ go: {
250
+ name: 'go',
251
+ deps: ['go-i18n', 'x-text'],
252
+ globs: ['**/*.go'],
253
253
  patterns: [
254
254
  /i18n\.NewMessage\([^,]+,\s*["`]([^"`]+)["`]/g,
255
255
  /i18n\.NewLocalizer\([^)]+\)\.MustLocalize\([^,]+,\s*["`]([^"`]+)["`]/g,
@@ -277,11 +277,6 @@ const FRAMEWORKS = {
277
277
  }
278
278
  };
279
279
 
280
- /**
281
- * Detect the i18n framework being used in the project
282
- * @param {string} projectRoot - Path to the project root
283
- * @returns {Promise<Object>} Object containing framework info and detection confidence
284
- */
285
280
  /**
286
281
  * Detects the i18n framework being used in the project
287
282
  * @param {string} projectRoot - Path to the project root
@@ -294,23 +289,31 @@ async function detectFramework(projectRoot) {
294
289
 
295
290
  const packageJsonPath = path.join(projectRoot, 'package.json');
296
291
  const detectedFrameworks = [];
297
-
292
+
298
293
  // Only proceed if package.json exists
299
- if (!fs.existsSync(packageJsonPath)) {
294
+ if (!SecurityUtils.safeExistsSync(packageJsonPath, projectRoot)) {
300
295
  return null;
301
296
  }
302
297
 
303
298
  try {
304
299
  // Read and parse package.json
305
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
306
- const deps = {
307
- ...(packageJson.dependencies || {}),
300
+ const packageJsonContent = SecurityUtils.safeReadFileSync(packageJsonPath, projectRoot, 'utf8');
301
+ if (!packageJsonContent) {
302
+ return null;
303
+ }
304
+ const packageJson = SecurityUtils.safeParseJSON(packageJsonContent);
305
+ if (!packageJson) {
306
+ return null;
307
+ }
308
+
309
+ const deps = {
310
+ ...(packageJson.dependencies || {}),
308
311
  ...(packageJson.devDependencies || {}),
309
312
  ...(packageJson.peerDependencies || {})
310
313
  };
311
314
 
312
315
  // Sort frameworks by priority (highest first)
313
- const sortedFrameworks = Object.entries(FRAMEWORKS).sort((a, b) =>
316
+ const sortedFrameworks = Object.entries(FRAMEWORKS).sort((a, b) =>
314
317
  (b[1].priority || 0) - (a[1].priority || 0)
315
318
  );
316
319
 
@@ -350,7 +353,7 @@ async function detectFramework(projectRoot) {
350
353
  // First sort by confidence
351
354
  const confidenceDiff = b.confidence - a.confidence;
352
355
  if (confidenceDiff !== 0) return confidenceDiff;
353
-
356
+
354
357
  // If confidence is equal, sort by priority
355
358
  return (b.priority || 0) - (a.priority || 0);
356
359
  })[0];
@@ -363,4 +366,4 @@ async function detectFramework(projectRoot) {
363
366
  }
364
367
  }
365
368
 
366
- module.exports = { detectFramework, FRAMEWORKS };
369
+ module.exports = { detectFramework, FRAMEWORKS };