@umituz/react-native-localization 3.5.3 → 3.5.4
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/package.json +5 -5
- package/src/scripts/prepublish.js +34 -0
- package/src/scripts/setup-languages.js +55 -0
- package/src/scripts/sync-translations.js +68 -0
- package/src/scripts/translate-missing.js +75 -0
- package/src/scripts/utils/file-parser.js +80 -0
- package/src/scripts/utils/sync-helper.js +49 -0
- package/src/scripts/utils/translation-config.js +128 -0
- package/src/scripts/utils/translator.js +97 -0
- package/src/scripts/prepublish.ts +0 -48
- package/src/scripts/setup-languages.ts +0 -56
- package/src/scripts/sync-translations.ts +0 -277
- package/src/scripts/translate-missing.ts +0 -403
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
|
|
4
|
-
// Default path if not provided
|
|
5
|
-
const targetDir = process.argv[2] || 'src/domains/localization/infrastructure/locales';
|
|
6
|
-
const localesDir = path.resolve(process.cwd(), targetDir);
|
|
7
|
-
|
|
8
|
-
console.log(`Setting up languages in: ${localesDir}`);
|
|
9
|
-
|
|
10
|
-
if (!fs.existsSync(localesDir)) {
|
|
11
|
-
console.error(`❌ Locales directory not found: ${localesDir}`);
|
|
12
|
-
process.exit(1);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
// Find all language files (e.g., en-US.ts, tr-TR.ts)
|
|
17
|
-
const files = fs.readdirSync(localesDir)
|
|
18
|
-
.filter(f => f.match(/^[a-z]{2}-[A-Z]{2}\.ts$/))
|
|
19
|
-
.sort();
|
|
20
|
-
|
|
21
|
-
const imports = [];
|
|
22
|
-
const exports = [];
|
|
23
|
-
|
|
24
|
-
files.forEach(file => {
|
|
25
|
-
const code = file.replace('.ts', '');
|
|
26
|
-
// Remove hyphens for variable names (en-US -> enUS)
|
|
27
|
-
const varName = code.replace(/-([a-z0-9])/g, (g) => g[1].toUpperCase()).replace('-', '');
|
|
28
|
-
|
|
29
|
-
imports.push(`import ${varName} from "./${code}";`);
|
|
30
|
-
exports.push(` "${code}": ${varName},`);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
const content = `/**
|
|
34
|
-
* Localization Index
|
|
35
|
-
* Exports all available translation files
|
|
36
|
-
* Auto-generated by scripts/setup-languages.js
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
|
-
${imports.join('\n')}
|
|
40
|
-
|
|
41
|
-
export const translations = {
|
|
42
|
-
${exports.join('\n')}
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export type TranslationKey = keyof typeof translations;
|
|
46
|
-
|
|
47
|
-
export default translations;
|
|
48
|
-
`;
|
|
49
|
-
|
|
50
|
-
fs.writeFileSync(path.join(localesDir, 'index.ts'), content);
|
|
51
|
-
console.log(`✅ Generated index.ts with ${files.length} languages`);
|
|
52
|
-
|
|
53
|
-
} catch (error) {
|
|
54
|
-
console.error('❌ Error setting up languages:', error);
|
|
55
|
-
process.exit(1);
|
|
56
|
-
}
|
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/* eslint-disable no-console */
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Sync Translations Script
|
|
6
|
-
*
|
|
7
|
-
* Synchronizes translation keys from en-US.ts to all other language files.
|
|
8
|
-
* - Adds missing keys (with English values as placeholders)
|
|
9
|
-
* - Removes extra keys not in en-US
|
|
10
|
-
* - Maintains existing translations
|
|
11
|
-
*
|
|
12
|
-
* Usage: node scripts/sync-translations.js [locales-dir]
|
|
13
|
-
* Default: src/domains/localization/infrastructure/locales
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
const fs = require('fs');
|
|
17
|
-
const path = require('path');
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Parse TypeScript translation file and extract the object
|
|
21
|
-
*/
|
|
22
|
-
function parseTypeScriptFile(filePath) {
|
|
23
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
24
|
-
|
|
25
|
-
// Extract the object from "export default { ... };"
|
|
26
|
-
const match = content.match(/export\s+default\s+(\{[\s\S]*\});?\s*$/);
|
|
27
|
-
if (!match) {
|
|
28
|
-
throw new Error(`Could not parse TypeScript file: ${filePath}`);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const objectStr = match[1].replace(/;$/, '');
|
|
32
|
-
|
|
33
|
-
try {
|
|
34
|
-
// eslint-disable-next-line no-eval
|
|
35
|
-
return eval(`(${objectStr})`);
|
|
36
|
-
} catch (error) {
|
|
37
|
-
throw new Error(`Failed to parse object in ${filePath}: ${error.message}`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Generate TypeScript file content from object
|
|
43
|
-
*/
|
|
44
|
-
function generateTypeScriptContent(obj, langCode) {
|
|
45
|
-
const langName = getLangDisplayName(langCode);
|
|
46
|
-
|
|
47
|
-
function stringifyValue(value, indent = 2) {
|
|
48
|
-
if (typeof value === 'string') {
|
|
49
|
-
const escaped = value
|
|
50
|
-
.replace(/\\/g, '\\\\')
|
|
51
|
-
.replace(/"/g, '\\"')
|
|
52
|
-
.replace(/\n/g, '\\n');
|
|
53
|
-
return `"${escaped}"`;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (Array.isArray(value)) {
|
|
57
|
-
if (value.length === 0) return '[]';
|
|
58
|
-
const items = value.map(v => stringifyValue(v, indent + 2));
|
|
59
|
-
return `[${items.join(', ')}]`;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (typeof value === 'object' && value !== null) {
|
|
63
|
-
const spaces = ' '.repeat(indent);
|
|
64
|
-
const innerSpaces = ' '.repeat(indent + 2);
|
|
65
|
-
const entries = Object.entries(value)
|
|
66
|
-
.map(([k, v]) => {
|
|
67
|
-
const key = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(k) ? k : `"${k}"`;
|
|
68
|
-
return `${innerSpaces}${key}: ${stringifyValue(v, indent + 2)}`;
|
|
69
|
-
})
|
|
70
|
-
.join(',\n');
|
|
71
|
-
return `{\n${entries},\n${spaces}}`;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return String(value);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const objString = stringifyValue(obj, 0);
|
|
78
|
-
|
|
79
|
-
return `/**
|
|
80
|
-
* ${langName} Translations
|
|
81
|
-
* Auto-synced from en-US.ts
|
|
82
|
-
*/
|
|
83
|
-
|
|
84
|
-
export default ${objString};
|
|
85
|
-
`;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Get display name for language code
|
|
90
|
-
*/
|
|
91
|
-
function getLangDisplayName(code) {
|
|
92
|
-
const names = {
|
|
93
|
-
'ar-SA': 'Arabic (Saudi Arabia)',
|
|
94
|
-
'bg-BG': 'Bulgarian',
|
|
95
|
-
'cs-CZ': 'Czech',
|
|
96
|
-
'da-DK': 'Danish',
|
|
97
|
-
'de-DE': 'German',
|
|
98
|
-
'el-GR': 'Greek',
|
|
99
|
-
'en-AU': 'English (Australia)',
|
|
100
|
-
'en-CA': 'English (Canada)',
|
|
101
|
-
'en-GB': 'English (UK)',
|
|
102
|
-
'en-US': 'English (US)',
|
|
103
|
-
'es-ES': 'Spanish (Spain)',
|
|
104
|
-
'es-MX': 'Spanish (Mexico)',
|
|
105
|
-
'fi-FI': 'Finnish',
|
|
106
|
-
'fr-CA': 'French (Canada)',
|
|
107
|
-
'fr-FR': 'French (France)',
|
|
108
|
-
'hi-IN': 'Hindi',
|
|
109
|
-
'hr-HR': 'Croatian',
|
|
110
|
-
'hu-HU': 'Hungarian',
|
|
111
|
-
'id-ID': 'Indonesian',
|
|
112
|
-
'it-IT': 'Italian',
|
|
113
|
-
'ja-JP': 'Japanese',
|
|
114
|
-
'ko-KR': 'Korean',
|
|
115
|
-
'ms-MY': 'Malay',
|
|
116
|
-
'nl-NL': 'Dutch',
|
|
117
|
-
'no-NO': 'Norwegian',
|
|
118
|
-
'pl-PL': 'Polish',
|
|
119
|
-
'pt-BR': 'Portuguese (Brazil)',
|
|
120
|
-
'pt-PT': 'Portuguese (Portugal)',
|
|
121
|
-
'ro-RO': 'Romanian',
|
|
122
|
-
'ru-RU': 'Russian',
|
|
123
|
-
'sk-SK': 'Slovak',
|
|
124
|
-
'sv-SE': 'Swedish',
|
|
125
|
-
'th-TH': 'Thai',
|
|
126
|
-
'tl-PH': 'Tagalog',
|
|
127
|
-
'tr-TR': 'Turkish',
|
|
128
|
-
'uk-UA': 'Ukrainian',
|
|
129
|
-
'vi-VN': 'Vietnamese',
|
|
130
|
-
'zh-CN': 'Chinese (Simplified)',
|
|
131
|
-
'zh-TW': 'Chinese (Traditional)',
|
|
132
|
-
};
|
|
133
|
-
return names[code] || code;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Add missing keys from en-US to target
|
|
138
|
-
*/
|
|
139
|
-
function addMissingKeys(enObj, targetObj, stats = { added: 0 }) {
|
|
140
|
-
for (const key in enObj) {
|
|
141
|
-
if (!Object.prototype.hasOwnProperty.call(targetObj, key)) {
|
|
142
|
-
targetObj[key] = enObj[key];
|
|
143
|
-
stats.added++;
|
|
144
|
-
} else if (
|
|
145
|
-
typeof enObj[key] === 'object' &&
|
|
146
|
-
enObj[key] !== null &&
|
|
147
|
-
!Array.isArray(enObj[key])
|
|
148
|
-
) {
|
|
149
|
-
if (!targetObj[key] || typeof targetObj[key] !== 'object') {
|
|
150
|
-
targetObj[key] = {};
|
|
151
|
-
}
|
|
152
|
-
addMissingKeys(enObj[key], targetObj[key], stats);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
return stats;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Remove extra keys not in en-US
|
|
160
|
-
*/
|
|
161
|
-
function removeExtraKeys(enObj, targetObj, stats = { removed: 0 }) {
|
|
162
|
-
for (const key in targetObj) {
|
|
163
|
-
if (!Object.prototype.hasOwnProperty.call(enObj, key)) {
|
|
164
|
-
delete targetObj[key];
|
|
165
|
-
stats.removed++;
|
|
166
|
-
} else if (
|
|
167
|
-
typeof enObj[key] === 'object' &&
|
|
168
|
-
enObj[key] !== null &&
|
|
169
|
-
!Array.isArray(enObj[key]) &&
|
|
170
|
-
typeof targetObj[key] === 'object' &&
|
|
171
|
-
targetObj[key] !== null &&
|
|
172
|
-
!Array.isArray(targetObj[key])
|
|
173
|
-
) {
|
|
174
|
-
removeExtraKeys(enObj[key], targetObj[key], stats);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return stats;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Sync a single language file
|
|
182
|
-
*/
|
|
183
|
-
function syncLanguageFile(enUSPath, targetPath, langCode) {
|
|
184
|
-
const enUS = parseTypeScriptFile(enUSPath);
|
|
185
|
-
let target;
|
|
186
|
-
|
|
187
|
-
try {
|
|
188
|
-
target = parseTypeScriptFile(targetPath);
|
|
189
|
-
} catch {
|
|
190
|
-
target = {};
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const addStats = { added: 0 };
|
|
194
|
-
const removeStats = { removed: 0 };
|
|
195
|
-
|
|
196
|
-
addMissingKeys(enUS, target, addStats);
|
|
197
|
-
removeExtraKeys(enUS, target, removeStats);
|
|
198
|
-
|
|
199
|
-
const changed = addStats.added > 0 || removeStats.removed > 0;
|
|
200
|
-
|
|
201
|
-
if (changed) {
|
|
202
|
-
const content = generateTypeScriptContent(target, langCode);
|
|
203
|
-
fs.writeFileSync(targetPath, content);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return {
|
|
207
|
-
added: addStats.added,
|
|
208
|
-
removed: removeStats.removed,
|
|
209
|
-
changed,
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Main function
|
|
215
|
-
*/
|
|
216
|
-
function main() {
|
|
217
|
-
const targetDir = process.argv[2] || 'src/domains/localization/infrastructure/locales';
|
|
218
|
-
const localesDir = path.resolve(process.cwd(), targetDir);
|
|
219
|
-
|
|
220
|
-
console.log('🚀 Starting translation synchronization...\n');
|
|
221
|
-
console.log(`📂 Locales directory: ${localesDir}\n`);
|
|
222
|
-
|
|
223
|
-
if (!fs.existsSync(localesDir)) {
|
|
224
|
-
console.error(`❌ Locales directory not found: ${localesDir}`);
|
|
225
|
-
process.exit(1);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const enUSPath = path.join(localesDir, 'en-US.ts');
|
|
229
|
-
if (!fs.existsSync(enUSPath)) {
|
|
230
|
-
console.error(`❌ Base file not found: ${enUSPath}`);
|
|
231
|
-
process.exit(1);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Find all language files
|
|
235
|
-
const files = fs.readdirSync(localesDir)
|
|
236
|
-
.filter(f => f.match(/^[a-z]{2}-[A-Z]{2}\.ts$/) && f !== 'en-US.ts')
|
|
237
|
-
.sort();
|
|
238
|
-
|
|
239
|
-
console.log(`📊 Languages to sync: ${files.length}\n`);
|
|
240
|
-
|
|
241
|
-
let totalAdded = 0;
|
|
242
|
-
let totalRemoved = 0;
|
|
243
|
-
let totalChanged = 0;
|
|
244
|
-
|
|
245
|
-
for (const file of files) {
|
|
246
|
-
const langCode = file.replace('.ts', '');
|
|
247
|
-
const targetPath = path.join(localesDir, file);
|
|
248
|
-
|
|
249
|
-
console.log(`🌍 Syncing ${langCode}...`);
|
|
250
|
-
|
|
251
|
-
const result = syncLanguageFile(enUSPath, targetPath, langCode);
|
|
252
|
-
|
|
253
|
-
if (result.changed) {
|
|
254
|
-
console.log(` ✏️ +${result.added} keys, -${result.removed} keys`);
|
|
255
|
-
totalAdded += result.added;
|
|
256
|
-
totalRemoved += result.removed;
|
|
257
|
-
totalChanged++;
|
|
258
|
-
} else {
|
|
259
|
-
console.log(` ✅ Already synchronized`);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
console.log(`\n📊 Summary:`);
|
|
264
|
-
console.log(` Languages processed: ${files.length}`);
|
|
265
|
-
console.log(` Files changed: ${totalChanged}`);
|
|
266
|
-
console.log(` Keys added: ${totalAdded}`);
|
|
267
|
-
console.log(` Keys removed: ${totalRemoved}`);
|
|
268
|
-
|
|
269
|
-
if (totalChanged > 0) {
|
|
270
|
-
console.log(`\n✅ Synchronization completed!`);
|
|
271
|
-
console.log(` Next: Run 'node scripts/translate-missing.js' to translate new keys`);
|
|
272
|
-
} else {
|
|
273
|
-
console.log(`\n✅ All languages were already synchronized!`);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
main();
|