i18ntk 1.2.0 → 1.2.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.
package/CHANGELOG.md CHANGED
@@ -2,7 +2,26 @@
2
2
 
3
3
  All notable changes to the I18N Management Toolkit are documented here. This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
4
 
5
- **Current Version:** 1.2.0 (2025-08-02) - **UI SIMPLIFICATION & ORGANIZATION RELEASE** 🧹
5
+ **Current Version:** 1.2.1 (2025-08-02) - **DIRECTORY PATH FIXES & CONFIGURATION IMPROVEMENTS** 🎯
6
+
7
+ ## [1.2.1] - 2025-08-02
8
+
9
+ ### 🎯 Directory Path Configuration Fixes
10
+ - **Fixed**: Scripts now correctly respect directory settings from configuration instead of using hardcoded paths
11
+ - **Enhanced**: Added interactive prompt to detect existing translation directories before creating new ones
12
+ - **Improved**: Users can now specify existing translation file locations during initialization
13
+ - **Fixed**: Prevented creation of redundant `/locales` directories when existing files are already configured
14
+ - **Enhanced**: All scripts now prioritize settings configuration over auto-detection
15
+
16
+ ### 🌐 Translation Updates
17
+ - **Added**: New translation keys for directory detection prompts in all supported languages
18
+ - **Enhanced**: English, German, Spanish, French, Russian, Japanese, and Chinese translations for new prompts
19
+ - **Fixed**: Missing `analyze.issueType.same_as_source` translation key across all locale files
20
+
21
+ ### 🔧 Configuration Improvements
22
+ - **Enhanced**: `i18ntk-init.js` now detects existing translation directories and prompts users
23
+ - **Fixed**: `i18ntk-usage.js` and `i18ntk-manage.js` now respect settings configuration over auto-detection
24
+ - **Improved**: Settings-based directory configuration takes precedence over hardcoded defaults
6
25
 
7
26
  ## [1.2.0] - 2025-08-02
8
27
 
package/README.md CHANGED
@@ -220,7 +220,7 @@ npm run i18ntk:debug
220
220
 
221
221
  ---
222
222
 
223
- **Version:** 1.2.0Enhanced CLI experience with proper version command and improved documentation! 🚀
223
+ **Version:** 1.2.1Directory path fixes and configuration improvements! 🎯
224
224
  ## 📄 License
225
225
 
226
226
  This project is licensed under the MIT License - see the `LICENSE` file for details.
@@ -164,8 +164,85 @@ class I18nInitializer {
164
164
  return parsed;
165
165
  }
166
166
 
167
+ // Detect existing translation directories and prompt user
168
+ async detectExistingDirectories() {
169
+ const possibleLocations = [
170
+ './locales',
171
+ './src/locales',
172
+ './src/i18n/locales',
173
+ './app/locales',
174
+ './public/locales',
175
+ './translations',
176
+ './lang',
177
+ './i18n/locales',
178
+ './assets/locales',
179
+ './client/locales',
180
+ './frontend/locales'
181
+ ];
182
+
183
+ const existingLocations = [];
184
+
185
+ // Check for existing translation directories
186
+ for (const location of possibleLocations) {
187
+ if (fs.existsSync(location)) {
188
+ try {
189
+ const items = fs.readdirSync(location);
190
+ const hasLanguageDirs = items.some(item => {
191
+ const itemPath = path.join(location, item);
192
+ if (fs.statSync(itemPath).isDirectory()) {
193
+ return ['en', 'de', 'es', 'fr', 'ru', 'ja', 'zh'].includes(item);
194
+ }
195
+ return item.endsWith('.json');
196
+ });
197
+ if (hasLanguageDirs) {
198
+ existingLocations.push(location);
199
+ }
200
+ } catch (error) {
201
+ // Continue checking other locations
202
+ }
203
+ }
204
+ }
205
+
206
+ if (existingLocations.length > 0) {
207
+ console.log('\n' + this.ui.t('init.existingDirectoriesFound'));
208
+ console.log('=' .repeat(50));
209
+
210
+ existingLocations.forEach((location, index) => {
211
+ console.log(` ${index + 1}. ${location}`);
212
+ });
213
+
214
+ const answer = await this.prompt('\n' + this.ui.t('init.useExistingDirectoryPrompt'));
215
+ const selectedIndex = parseInt(answer) - 1;
216
+
217
+ if (selectedIndex >= 0 && selectedIndex < existingLocations.length) {
218
+ const selectedDir = existingLocations[selectedIndex];
219
+ console.log(this.ui.t('init.usingExistingDirectory', { dir: selectedDir }));
220
+
221
+ // Update settings to use the existing directory
222
+ this.config.sourceDir = selectedDir;
223
+ this.sourceDir = path.resolve(selectedDir);
224
+ this.sourceLanguageDir = path.join(this.sourceDir, this.config.sourceLanguage);
225
+
226
+ // Save to settings
227
+ settingsManager.setDirectories({ sourceDir: selectedDir });
228
+
229
+ return true;
230
+ }
231
+ }
232
+
233
+ return false;
234
+ }
235
+
167
236
  // Setup initial directory structure if needed
168
237
  async setupInitialStructure() {
238
+ // First, detect if there are existing translation directories
239
+ const usedExisting = await this.detectExistingDirectories();
240
+
241
+ if (usedExisting) {
242
+ console.log(this.ui.t('init.usingExistingStructure', { dir: this.sourceDir }));
243
+ return;
244
+ }
245
+
169
246
  // Validate paths
170
247
  const validatedSourceDir = SecurityUtils.validatePath(this.sourceDir, process.cwd());
171
248
  const validatedSourceLanguageDir = SecurityUtils.validatePath(this.sourceLanguageDir, process.cwd());
@@ -175,14 +252,14 @@ class I18nInitializer {
175
252
  throw new Error('Invalid directory paths detected');
176
253
  }
177
254
 
178
- // Create source directory if it doesn't exist
255
+ // Create source directory only if it doesn't exist and no existing was detected
179
256
  if (!fs.existsSync(validatedSourceDir)) {
180
257
  console.log(this.ui.t('init.creatingSourceDirectory', { dir: validatedSourceDir }));
181
258
  fs.mkdirSync(validatedSourceDir, { recursive: true });
182
259
  SecurityUtils.logSecurityEvent('Source directory created', 'info', { dir: validatedSourceDir });
183
260
  }
184
261
 
185
- // Create source language directory if it doesn't exist
262
+ // Create source language directory only if it doesn't exist
186
263
  if (!fs.existsSync(validatedSourceLanguageDir)) {
187
264
  console.log(this.ui.t('init.creatingSourceLanguageDirectory', { dir: validatedSourceLanguageDir }));
188
265
  fs.mkdirSync(validatedSourceLanguageDir, { recursive: true });
@@ -96,8 +96,17 @@ class I18nManager {
96
96
  }
97
97
  }
98
98
 
99
- // Auto-detect i18n directory from common locations
99
+ // Auto-detect i18n directory from common locations only if not configured in settings
100
100
  detectI18nDirectory() {
101
+ const settings = settingsManager.getSettings();
102
+
103
+ // Use settings configuration if available
104
+ if (settings.directories?.sourceDir) {
105
+ this.config.sourceDir = settings.directories.sourceDir;
106
+ return;
107
+ }
108
+
109
+ // Only auto-detect if no settings are configured
101
110
  for (const possiblePath of this.config.possibleI18nPaths) {
102
111
  const resolvedPath = path.resolve(possiblePath);
103
112
  if (fs.existsSync(resolvedPath)) {
@@ -29,85 +29,88 @@ const settingsManager = require('../settings/settings-manager');
29
29
  const SecurityUtils = require('../utils/security');
30
30
  const AdminCLI = require('../utils/admin-cli');
31
31
 
32
- // Enhanced configuration with multiple source directory detection
32
+ // Enhanced configuration that prioritizes settings over auto-detection
33
33
  async function getConfig() {
34
34
  try {
35
35
  const settings = settingsManager.getSettings();
36
36
 
37
- // Multiple possible source directories to check
38
- const possibleSourceDirs = [
39
- './main', // Primary source directory for this project
40
- './src',
41
- './app',
42
- './components',
43
- './pages',
44
- './views',
45
- './client',
46
- './frontend',
47
- './' // Current directory as fallback
48
- ];
37
+ // Only use auto-detection if no settings are configured
38
+ let sourceDir = settings.directories?.sourceDir;
39
+ let i18nDir = settings.directories?.i18nDir;
49
40
 
50
- // Auto-detect source directory
51
- let detectedSourceDir = './src'; // Default
52
- for (const dir of possibleSourceDirs) {
53
- if (fs.existsSync(dir)) {
54
- // Check if directory contains code files
55
- try {
56
- const files = fs.readdirSync(dir);
57
- const hasCodeFiles = files.some(file =>
58
- ['.js', '.jsx', '.ts', '.tsx', '.vue', '.svelte'].includes(path.extname(file))
59
- );
60
- if (hasCodeFiles) {
61
- detectedSourceDir = dir;
62
- break;
41
+ // Auto-detect only if settings don't specify directories
42
+ if (!sourceDir) {
43
+ const possibleSourceDirs = [
44
+ './main', // Primary source directory for this project
45
+ './src',
46
+ './app',
47
+ './components',
48
+ './pages',
49
+ './views',
50
+ './client',
51
+ './frontend',
52
+ './' // Current directory as fallback
53
+ ];
54
+
55
+ for (const dir of possibleSourceDirs) {
56
+ if (fs.existsSync(dir)) {
57
+ try {
58
+ const files = fs.readdirSync(dir);
59
+ const hasCodeFiles = files.some(file =>
60
+ ['.js', '.jsx', '.ts', '.tsx', '.vue', '.svelte'].includes(path.extname(file))
61
+ );
62
+ if (hasCodeFiles) {
63
+ sourceDir = dir;
64
+ break;
65
+ }
66
+ } catch (error) {
67
+ // Continue checking
63
68
  }
64
- } catch (error) {
65
- // Continue checking
66
69
  }
67
70
  }
71
+ sourceDir = sourceDir || './src'; // Final fallback
68
72
  }
69
73
 
70
- // Multiple possible i18n directories
71
- const possibleI18nDirs = [
72
- './locales',
73
- './src/locales',
74
- './src/i18n',
75
- './src/i18n/locales',
76
- './app/locales',
77
- './app/i18n',
78
- './public/locales',
79
- './assets/locales',
80
- './translations',
81
- './lang'
82
- ];
83
-
84
- // Auto-detect i18n directory
85
- let detectedI18nDir = './locales'; // Default
86
- for (const dir of possibleI18nDirs) {
87
- if (fs.existsSync(dir)) {
88
- // Check if directory contains language subdirectories or JSON files
89
- try {
90
- const items = fs.readdirSync(dir);
91
- const hasLanguageDirs = items.some(item => {
92
- const itemPath = path.join(dir, item);
93
- if (fs.statSync(itemPath).isDirectory()) {
94
- return ['en', 'de', 'es', 'fr', 'ru', 'ja', 'zh'].includes(item);
74
+ if (!i18nDir) {
75
+ const possibleI18nDirs = [
76
+ './locales',
77
+ './src/locales',
78
+ './src/i18n',
79
+ './src/i18n/locales',
80
+ './app/locales',
81
+ './app/i18n',
82
+ './public/locales',
83
+ './assets/locales',
84
+ './translations',
85
+ './lang'
86
+ ];
87
+
88
+ for (const dir of possibleI18nDirs) {
89
+ if (fs.existsSync(dir)) {
90
+ try {
91
+ const items = fs.readdirSync(dir);
92
+ const hasLanguageDirs = items.some(item => {
93
+ const itemPath = path.join(dir, item);
94
+ if (fs.statSync(itemPath).isDirectory()) {
95
+ return ['en', 'de', 'es', 'fr', 'ru', 'ja', 'zh'].includes(item);
96
+ }
97
+ return item.endsWith('.json');
98
+ });
99
+ if (hasLanguageDirs) {
100
+ i18nDir = dir;
101
+ break;
95
102
  }
96
- return item.endsWith('.json');
97
- });
98
- if (hasLanguageDirs) {
99
- detectedI18nDir = dir;
100
- break;
103
+ } catch (error) {
104
+ // Continue checking
101
105
  }
102
- } catch (error) {
103
- // Continue checking
104
106
  }
105
107
  }
108
+ i18nDir = i18nDir || './locales'; // Final fallback
106
109
  }
107
110
 
108
111
  const config = {
109
- sourceDir: settings.directories?.sourceDir || detectedSourceDir,
110
- i18nDir: settings.directories?.i18nDir || detectedI18nDir,
112
+ sourceDir: sourceDir,
113
+ i18nDir: i18nDir,
111
114
  sourceLanguage: settings.directories?.sourceLanguage || settings.sourceLanguage || 'en',
112
115
  outputDir: settings.directories?.outputDir || settings.outputDir || './i18ntk-reports',
113
116
  excludeDirs: settings.processing?.excludeDirs || [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i18ntk",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "i18ntk (i18n Toolkit) - A comprehensive, enterprise-grade internationalization (i18n) management toolkit for JavaScript/TypeScript projects with advanced analysis, validation, and automation features",
5
5
  "keywords": [
6
6
  "i18n",
@@ -124,7 +124,7 @@
124
124
  },
125
125
  "preferGlobal": true,
126
126
  "versionInfo": {
127
- "version": "1.2.0",
127
+ "version": "1.2.1",
128
128
  "releaseDate": "02/08/2025",
129
129
  "lastUpdated": "02/08/2025",
130
130
  "maintainer": "Vladimir Noskov",
@@ -62,7 +62,8 @@
62
62
  "partial_translation": "Partial translations: {count}",
63
63
  "format_mismatch": "Format mismatches: {count}",
64
64
  "type_mismatch": "Type mismatches: {count}",
65
- "structure_mismatch": "Structure mismatches: {count}"
65
+ "structure_mismatch": "Structure mismatches: {count}",
66
+ "same_as_source": "Gleich wie Quelle: {count}"
66
67
  },
67
68
  "keysToTranslate": "📋 KEYS TO TRANSLATE",
68
69
  "key": "Schlüssel",
@@ -34,5 +34,9 @@
34
34
  "frameworks.i18next": "- i18next (i18next)",
35
35
  "frameworks.nuxt": "- Nuxt i18n (@nuxtjs/i18n)",
36
36
  "frameworks.svelte": "- Svelte i18n (svelte-i18n)",
37
- "selectOptionPrompt": "Select an option:"
37
+ "selectOptionPrompt": "Select an option:",
38
+ "existingDirectoriesFound": "📁 Vorhandene Übersetzungsverzeichnisse gefunden:",
39
+ "useExistingDirectoryPrompt": "Vorhandenes Verzeichnis verwenden? Nummer eingeben (oder Enter für neues):",
40
+ "usingExistingDirectory": "✅ Vorhandenes Verzeichnis verwenden: {dir}",
41
+ "usingExistingStructure": "✅ Vorhandene Übersetzungsstruktur verwenden in: {dir}"
38
42
  }
@@ -62,7 +62,8 @@
62
62
  "partial_translation": "Partial translations: {count}",
63
63
  "format_mismatch": "Format mismatches: {count}",
64
64
  "type_mismatch": "Type mismatches: {count}",
65
- "structure_mismatch": "Structure mismatches: {count}"
65
+ "structure_mismatch": "Structure mismatches: {count}",
66
+ "same_as_source": "Same as source: {count}"
66
67
  },
67
68
  "keysToTranslate": "📋 KEYS TO TRANSLATE",
68
69
  "key": "Key",
@@ -1,4 +1,17 @@
1
1
  {
2
2
  "success": "Success",
3
- "error": "Error"
3
+ "error": "Error",
4
+ "warning": "Warning",
5
+ "info": "Info",
6
+ "debug": "Debug",
7
+ "progress": "Progress",
8
+ "remaining": "Remaining",
9
+ "total": "Total",
10
+ "completed": "Completed",
11
+ "missing": "Missing",
12
+ "partial": "Partial",
13
+ "sameAsSource": "Same as source",
14
+ "formatMismatch": "Format mismatch",
15
+ "typeMismatch": "Type mismatch",
16
+ "structureMismatch": "Structure mismatch"
4
17
  }
@@ -3,5 +3,15 @@
3
3
  "genericError": "❌ Error: {{error}}",
4
4
  "errorGeneratingStatusSummary": "Error generating status summary: {error}",
5
5
  "errorRunningDebugTool": "Error running debug tool '{displayName}': {error}",
6
- "errorReadingDebugLogs": "Error reading debug logs: {error}"
6
+ "errorReadingDebugLogs": "Error reading debug logs: {error}",
7
+ "errorAnalyzingLogFile": "Error analyzing log file: {error}",
8
+ "errorAnalyzingTranslationKeys": "Error analyzing translation keys: {error}",
9
+ "errorAnalyzingTranslationCompleteness": "Error analyzing translation completeness: {error}",
10
+ "errorAnalyzingTranslationFormat": "Error analyzing translation format: {error}",
11
+ "errorAnalyzingTranslationType": "Error analyzing translation type: {error}",
12
+ "errorAnalyzingTranslationStructure": "Error analyzing translation structure: {error}",
13
+ "errorAnalyzingTranslationFormatMismatch": "Error analyzing translation format mismatch: {error}",
14
+ "errorAnalyzingTranslationTypeMismatch": "Error analyzing translation type mismatch: {error}",
15
+ "errorAnalyzingTranslationStructureMismatch": "Error analyzing translation structure mismatch: {error}",
16
+ "errorAnalyzingTranslationSameAsSource": "Error analyzing translation same as source: {error}"
7
17
  }
@@ -35,5 +35,9 @@
35
35
  "frameworks.i18next": "- i18next (i18next)",
36
36
  "frameworks.nuxt": "- Nuxt i18n (@nuxtjs/i18n)",
37
37
  "frameworks.svelte": "- Svelte i18n (svelte-i18n)",
38
- "selectOptionPrompt": "Select an option:"
38
+ "selectOptionPrompt": "Select an option:",
39
+ "existingDirectoriesFound": "📁 Existing translation directories found:",
40
+ "useExistingDirectoryPrompt": "Use existing directory? Enter number (or press Enter to create new):",
41
+ "usingExistingDirectory": "✅ Using existing directory: {dir}",
42
+ "usingExistingStructure": "✅ Using existing translation structure in: {dir}"
39
43
  }
@@ -32,5 +32,13 @@
32
32
  "autoDetectedI18nDirectory": "Auto-detected i18n directory: {path}",
33
33
  "executingCommand": "Executing command: {command}",
34
34
  "unknownCommand": "Unknown command: {command}",
35
- "languageOption": " {{index}}. {{displayName}}{{current}}"
35
+ "languageOption": " {{index}}. {{displayName}}{{current}}",
36
+ "debugTools": {
37
+ "1": "Log file analysis",
38
+ "2": "Translation key usage analysis",
39
+ "3": "Translation completeness analysis",
40
+ "4": "Translation format analysis",
41
+ "5": "Translation type analysis",
42
+ "6": "Translation structure analysis"
43
+ }
36
44
  }
@@ -20,5 +20,6 @@
20
20
  "inputDisallowedCharacters": "Security: Input contains disallowed characters",
21
21
  "unknownCommandArg": "Unknown command argument",
22
22
  "logMessage": "[SECURITY {level}] {timestamp}: {event}",
23
- "alertMessage": "[SECURITY ALERT] {timestamp}: {event}"
23
+ "alertMessage": "[SECURITY ALERT] {timestamp}: {event}",
24
+ "securityWarning": "[SECURITY WARNING] {timestamp}: {event}"
24
25
  }
@@ -6,5 +6,22 @@
6
6
  "nextStep4": "4. Complete missing translations:",
7
7
  "nextStep5": "5. Generate summary report:",
8
8
  "nextStep6": "6. Review and finalize translations:",
9
- "completed": "7. Completed successfully!"
9
+ "completed": "7. Completed successfully!",
10
+ "generating": "Generating summary report...",
11
+ "review": "Reviewing translations...",
12
+ "finalizing": "Finalizing translations...",
13
+ "finalized": "Finalized successfully!",
14
+ "errors": "Errors:",
15
+ "warnings": "Warnings:",
16
+ "info": "Info:",
17
+ "progress": "Progress:",
18
+ "remaining": "Remaining:",
19
+ "total": "Total:",
20
+ "completedKeys": "Completed keys:",
21
+ "missingKeys": "Missing keys:",
22
+ "partialKeys": "Partial keys:",
23
+ "sameAsSource": "Same as source:",
24
+ "formatMismatch": "Format mismatch:",
25
+ "typeMismatch": "Type mismatch:",
26
+ "structureMismatch": "Structure mismatch:"
10
27
  }
@@ -62,7 +62,8 @@
62
62
  "partial_translation": "⚠️ TRANSLATION NEEDED ⚠️",
63
63
  "format_mismatch": "⚠️ TRANSLATION NEEDED ⚠️",
64
64
  "type_mismatch": "⚠️ TRANSLATION NEEDED ⚠️",
65
- "structure_mismatch": "⚠️ TRANSLATION NEEDED ⚠️"
65
+ "structure_mismatch": "⚠️ TRANSLATION NEEDED ⚠️",
66
+ "same_as_source": "Igual que la fuente: {count}"
66
67
  },
67
68
  "keysToTranslate": "⚠️ TRANSLATION NEEDED ⚠️",
68
69
  "key": "⚠️ TRANSLATION NEEDED ⚠️",
@@ -34,5 +34,9 @@
34
34
  "frameworks.i18next": "⚠️ TRANSLATION NEEDED ⚠️",
35
35
  "frameworks.nuxt": "⚠️ TRANSLATION NEEDED ⚠️",
36
36
  "frameworks.svelte": "⚠️ TRANSLATION NEEDED ⚠️",
37
- "selectOptionPrompt": "⚠️ TRANSLATION NEEDED ⚠️"
37
+ "selectOptionPrompt": "Seleccionar opción:",
38
+ "existingDirectoriesFound": "📁 Directorios de traducción existentes encontrados:",
39
+ "useExistingDirectoryPrompt": "¿Usar directorio existente? Ingresar número (o presionar Enter para crear nuevo):",
40
+ "usingExistingDirectory": "✅ Usando directorio existente: {dir}",
41
+ "usingExistingStructure": "✅ Usando estructura de traducción existente en: {dir}"
38
42
  }
@@ -62,7 +62,8 @@
62
62
  "partial_translation": "⚠️ TRANSLATION NEEDED ⚠️",
63
63
  "format_mismatch": "⚠️ TRANSLATION NEEDED ⚠️",
64
64
  "type_mismatch": "⚠️ TRANSLATION NEEDED ⚠️",
65
- "structure_mismatch": "⚠️ TRANSLATION NEEDED ⚠️"
65
+ "structure_mismatch": "⚠️ TRANSLATION NEEDED ⚠️",
66
+ "same_as_source": "Identique à la source: {count}"
66
67
  },
67
68
  "keysToTranslate": "⚠️ TRANSLATION NEEDED ⚠️",
68
69
  "key": "⚠️ TRANSLATION NEEDED ⚠️",
@@ -34,5 +34,9 @@
34
34
  "frameworks.i18next": "⚠️ TRANSLATION NEEDED ⚠️",
35
35
  "frameworks.nuxt": "⚠️ TRANSLATION NEEDED ⚠️",
36
36
  "frameworks.svelte": "⚠️ TRANSLATION NEEDED ⚠️",
37
- "selectOptionPrompt": "⚠️ TRANSLATION NEEDED ⚠️"
37
+ "selectOptionPrompt": "Sélectionner une option:",
38
+ "existingDirectoriesFound": "📁 Répertoires de traduction existants trouvés:",
39
+ "useExistingDirectoryPrompt": "Utiliser le répertoire existant ? Entrer le numéro (ou appuyer sur Entrée pour créer un nouveau):",
40
+ "usingExistingDirectory": "✅ Utilisation du répertoire existant : {dir}",
41
+ "usingExistingStructure": "✅ Utilisation de la structure de traduction existante dans : {dir}"
38
42
  }
@@ -62,7 +62,8 @@
62
62
  "partial_translation": "⚠️ TRANSLATION NEEDED ⚠️",
63
63
  "format_mismatch": "⚠️ TRANSLATION NEEDED ⚠️",
64
64
  "type_mismatch": "⚠️ TRANSLATION NEEDED ⚠️",
65
- "structure_mismatch": "⚠️ TRANSLATION NEEDED ⚠️"
65
+ "structure_mismatch": "⚠️ TRANSLATION NEEDED ⚠️",
66
+ "same_as_source": "ソースと同じ: {count}"
66
67
  },
67
68
  "keysToTranslate": "⚠️ TRANSLATION NEEDED ⚠️",
68
69
  "key": "⚠️ TRANSLATION NEEDED ⚠️",
@@ -34,5 +34,9 @@
34
34
  "frameworks.i18next": "⚠️ TRANSLATION NEEDED ⚠️",
35
35
  "frameworks.nuxt": "⚠️ TRANSLATION NEEDED ⚠️",
36
36
  "frameworks.svelte": "⚠️ TRANSLATION NEEDED ⚠️",
37
- "selectOptionPrompt": "⚠️ TRANSLATION NEEDED ⚠️"
37
+ "selectOptionPrompt": "オプションを選択:",
38
+ "existingDirectoriesFound": "📁 既存の翻訳ディレクトリが見つかりました:",
39
+ "useExistingDirectoryPrompt": "既存のディレクトリを使用しますか?番号を入力(新規作成の場合はEnterを押してください):",
40
+ "usingExistingDirectory": "✅ 既存のディレクトリを使用: {dir}",
41
+ "usingExistingStructure": "✅ 既存の翻訳構造を使用: {dir}"
38
42
  }
@@ -57,12 +57,13 @@
57
57
  "extraKeys": "⚠️ TRANSLATION NEEDED ⚠️",
58
58
  "issues": "⚠️ TRANSLATION NEEDED ⚠️",
59
59
  "issueType": {
60
- "not_translated": "⚠️ TRANSLATION NEEDED ⚠️",
61
- "empty_value": "⚠️ TRANSLATION NEEDED ⚠️",
62
- "partial_translation": "⚠️ TRANSLATION NEEDED ⚠️",
63
- "format_mismatch": "⚠️ TRANSLATION NEEDED ⚠️",
64
- "type_mismatch": "⚠️ TRANSLATION NEEDED ⚠️",
65
- "structure_mismatch": "⚠️ TRANSLATION NEEDED ⚠️"
60
+ "not_translated": "Не переведено: {count}",
61
+ "empty_value": "Пустые значения: {count}",
62
+ "partial_translation": "Частичный перевод: {count}",
63
+ "format_mismatch": "Несоответствие формата: {count}",
64
+ "type_mismatch": "Несоответствие типа: {count}",
65
+ "structure_mismatch": "Несоответствие структуры: {count}",
66
+ "same_as_source": "Такой же как источник: {count}"
66
67
  },
67
68
  "keysToTranslate": "⚠️ TRANSLATION NEEDED ⚠️",
68
69
  "key": "⚠️ TRANSLATION NEEDED ⚠️",
@@ -34,5 +34,9 @@
34
34
  "frameworks.i18next": "⚠️ TRANSLATION NEEDED ⚠️",
35
35
  "frameworks.nuxt": "⚠️ TRANSLATION NEEDED ⚠️",
36
36
  "frameworks.svelte": "⚠️ TRANSLATION NEEDED ⚠️",
37
- "selectOptionPrompt": "⚠️ TRANSLATION NEEDED ⚠️"
37
+ "selectOptionPrompt": "Выберите опцию:",
38
+ "existingDirectoriesFound": "📁 Найдены существующие каталоги переводов:",
39
+ "useExistingDirectoryPrompt": "Использовать существующий каталог? Введите номер (или нажмите Enter для создания нового):",
40
+ "usingExistingDirectory": "✅ Используется существующий каталог: {dir}",
41
+ "usingExistingStructure": "✅ Используется существующая структура переводов в: {dir}"
38
42
  }
@@ -62,7 +62,8 @@
62
62
  "partial_translation": "部分翻译: {count}",
63
63
  "format_mismatch": "格式不匹配: {count}",
64
64
  "type_mismatch": "类型不匹配: {count}",
65
- "structure_mismatch": "结构不匹配: {count}"
65
+ "structure_mismatch": "结构不匹配: {count}",
66
+ "same_as_source": "与源文件相同: {count}"
66
67
  },
67
68
  "keysToTranslate": "📋 待翻译键",
68
69
  "key": "键",
@@ -34,5 +34,9 @@
34
34
  "frameworks.i18next": "- i18next (i18next)",
35
35
  "frameworks.nuxt": "- Nuxt i18n (@nuxtjs/i18n)",
36
36
  "frameworks.svelte": "- Svelte i18n (svelte-i18n)",
37
- "selectOptionPrompt": "选择一个选项:"
37
+ "selectOptionPrompt": "选择选项:",
38
+ "existingDirectoriesFound": "📁 找到现有的翻译目录:",
39
+ "useExistingDirectoryPrompt": "使用现有目录?输入编号(或按回车键创建新目录):",
40
+ "usingExistingDirectory": "✅ 使用现有目录: {dir}",
41
+ "usingExistingStructure": "✅ 使用现有翻译结构: {dir}"
38
42
  }