@umituz/react-native-localization 2.0.1 ā 2.2.0
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 +1 -1
- package/scripts/prepublish.js +7 -52
- package/src/infrastructure/config/I18nInitializer.ts +33 -28
- package/src/infrastructure/config/TranslationLoader.ts +1 -12
- package/src/infrastructure/config/i18n.ts +5 -7
- package/scripts/analyze-keys.js +0 -230
- package/scripts/check-translations.js +0 -354
- package/scripts/createLocaleLoaders.js +0 -187
- package/scripts/remove-unused-keys.js +0 -216
- package/scripts/setup-languages.js +0 -290
- package/scripts/translate-missing.js +0 -619
- package/scripts/utils/findLocalesDir.js +0 -79
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/* eslint-disable no-console */
|
|
3
|
-
|
|
4
|
-
const fs = require('fs');
|
|
5
|
-
const path = require('path');
|
|
6
|
-
const { getLocalesDir } = require('./utils/findLocalesDir');
|
|
7
|
-
|
|
8
|
-
// Function to get all keys from an object recursively
|
|
9
|
-
function getAllKeys(obj, prefix = '') {
|
|
10
|
-
let keys = [];
|
|
11
|
-
for (const key in obj) {
|
|
12
|
-
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
13
|
-
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
14
|
-
if (
|
|
15
|
-
typeof obj[key] === 'object' &&
|
|
16
|
-
obj[key] !== null &&
|
|
17
|
-
!Array.isArray(obj[key])
|
|
18
|
-
) {
|
|
19
|
-
keys = keys.concat(getAllKeys(obj[key], fullKey));
|
|
20
|
-
} else {
|
|
21
|
-
keys.push(fullKey);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return keys;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Function to remove a key from an object by path
|
|
29
|
-
function removeKeyByPath(obj, keyPath) {
|
|
30
|
-
const keys = keyPath.split('.');
|
|
31
|
-
let current = obj;
|
|
32
|
-
|
|
33
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
34
|
-
if (!current[keys[i]] || typeof current[keys[i]] !== 'object') {
|
|
35
|
-
return false; // Path doesn't exist
|
|
36
|
-
}
|
|
37
|
-
current = current[keys[i]];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const lastKey = keys[keys.length - 1];
|
|
41
|
-
if (current.hasOwnProperty(lastKey)) {
|
|
42
|
-
delete current[keys[keys.length - 1]];
|
|
43
|
-
|
|
44
|
-
// Clean up empty parent objects
|
|
45
|
-
if (keys.length > 1) {
|
|
46
|
-
let parent = obj;
|
|
47
|
-
for (let i = 0; i < keys.length - 2; i++) {
|
|
48
|
-
parent = parent[keys[i]];
|
|
49
|
-
}
|
|
50
|
-
const parentKey = keys[keys.length - 2];
|
|
51
|
-
if (Object.keys(parent[parentKey]).length === 0) {
|
|
52
|
-
delete parent[parentKey];
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return true;
|
|
57
|
-
}
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Function to remove unused keys from a translation file
|
|
62
|
-
function removeUnusedKeys(enUS, targetLang, filePath, langCode, dryRun = false) {
|
|
63
|
-
const enKeys = getAllKeys(enUS);
|
|
64
|
-
const targetKeys = getAllKeys(targetLang);
|
|
65
|
-
|
|
66
|
-
const extraKeys = targetKeys.filter(key => !enKeys.includes(key));
|
|
67
|
-
|
|
68
|
-
if (extraKeys.length === 0) {
|
|
69
|
-
return { removed: 0, keys: [] };
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Create a deep copy to modify
|
|
73
|
-
const cleanedLang = JSON.parse(JSON.stringify(targetLang));
|
|
74
|
-
|
|
75
|
-
let removedCount = 0;
|
|
76
|
-
for (const key of extraKeys) {
|
|
77
|
-
if (removeKeyByPath(cleanedLang, key)) {
|
|
78
|
-
removedCount++;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (!dryRun && removedCount > 0) {
|
|
83
|
-
// Write cleaned file
|
|
84
|
-
const targetFile = filePath;
|
|
85
|
-
fs.writeFileSync(targetFile, JSON.stringify(cleanedLang, null, 2) + '\n', 'utf8');
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return { removed: removedCount, keys: extraKeys };
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Main function
|
|
92
|
-
function main() {
|
|
93
|
-
const args = process.argv.slice(2);
|
|
94
|
-
const targetLanguage = args.find(arg => !arg.startsWith('--'));
|
|
95
|
-
const dryRun = args.includes('--dry-run') || args.includes('-d');
|
|
96
|
-
const allLanguages = args.includes('--all') || args.includes('-a');
|
|
97
|
-
|
|
98
|
-
if (!targetLanguage && !allLanguages) {
|
|
99
|
-
console.log('Usage: npm run i18n:remove-unused <language-code> [--dry-run]');
|
|
100
|
-
console.log('Example: npm run i18n:remove-unused tr-TR');
|
|
101
|
-
console.log('Example: npm run i18n:remove-unused tr-TR --dry-run (preview only, no removal)');
|
|
102
|
-
console.log('Example: npm run i18n:remove-unused --all (all languages)');
|
|
103
|
-
process.exit(1);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Find project's locales directory
|
|
107
|
-
const localesDir = getLocalesDir();
|
|
108
|
-
const enUSDir = path.join(localesDir, 'en-US');
|
|
109
|
-
|
|
110
|
-
// Auto-discover all JSON files
|
|
111
|
-
const files = fs
|
|
112
|
-
.readdirSync(enUSDir)
|
|
113
|
-
.filter(file => file.endsWith('.json'))
|
|
114
|
-
.sort();
|
|
115
|
-
|
|
116
|
-
if (files.length === 0) {
|
|
117
|
-
console.error('ā No JSON files found in en-US directory!');
|
|
118
|
-
process.exit(1);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Get language directories
|
|
122
|
-
const allLanguageDirs = fs
|
|
123
|
-
.readdirSync(localesDir)
|
|
124
|
-
.filter(dir => {
|
|
125
|
-
const fullPath = path.join(localesDir, dir);
|
|
126
|
-
return fs.statSync(fullPath).isDirectory() && dir !== 'en-US';
|
|
127
|
-
})
|
|
128
|
-
.sort();
|
|
129
|
-
|
|
130
|
-
// Determine which languages to process
|
|
131
|
-
let languageDirs = allLanguageDirs;
|
|
132
|
-
if (!allLanguages) {
|
|
133
|
-
if (targetLanguage === 'spanish' || targetLanguage === 'es') {
|
|
134
|
-
languageDirs = allLanguageDirs.filter(dir => dir.startsWith('es-'));
|
|
135
|
-
} else if (allLanguageDirs.includes(targetLanguage)) {
|
|
136
|
-
languageDirs = [targetLanguage];
|
|
137
|
-
} else {
|
|
138
|
-
console.log(`ā Language ${targetLanguage} not found. Available: ${allLanguageDirs.join(', ')}`);
|
|
139
|
-
process.exit(1);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (dryRun) {
|
|
144
|
-
console.log('š DRY RUN MODE - No files will be modified\n');
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
let totalRemoved = 0;
|
|
148
|
-
let totalFiles = 0;
|
|
149
|
-
|
|
150
|
-
console.log(`š§¹ Removing unused keys from ${languageDirs.length} language(s)...\n`);
|
|
151
|
-
|
|
152
|
-
languageDirs.forEach(langCode => {
|
|
153
|
-
const langDir = path.join(localesDir, langCode);
|
|
154
|
-
let langRemoved = 0;
|
|
155
|
-
let langFiles = 0;
|
|
156
|
-
|
|
157
|
-
console.log(`\nš Processing ${langCode}...`);
|
|
158
|
-
|
|
159
|
-
files.forEach(file => {
|
|
160
|
-
const enUSPath = path.join(enUSDir, file);
|
|
161
|
-
const langPath = path.join(langDir, file);
|
|
162
|
-
|
|
163
|
-
if (!fs.existsSync(enUSPath)) {
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
if (!fs.existsSync(langPath)) {
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
try {
|
|
172
|
-
const enUS = JSON.parse(fs.readFileSync(enUSPath, 'utf8'));
|
|
173
|
-
const langData = JSON.parse(fs.readFileSync(langPath, 'utf8'));
|
|
174
|
-
|
|
175
|
-
const result = removeUnusedKeys(enUS, langData, langPath, langCode, dryRun);
|
|
176
|
-
|
|
177
|
-
if (result.removed > 0) {
|
|
178
|
-
langRemoved += result.removed;
|
|
179
|
-
langFiles++;
|
|
180
|
-
totalRemoved += result.removed;
|
|
181
|
-
totalFiles++;
|
|
182
|
-
|
|
183
|
-
if (dryRun) {
|
|
184
|
-
console.log(` š ${file}: Would remove ${result.removed} key(s): ${result.keys.slice(0, 5).join(', ')}${result.keys.length > 5 ? '...' : ''}`);
|
|
185
|
-
} else {
|
|
186
|
-
console.log(` ā
${file}: Removed ${result.removed} unused key(s): ${result.keys.slice(0, 5).join(', ')}${result.keys.length > 5 ? '...' : ''}`);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
} catch (error) {
|
|
190
|
-
console.log(` ā Error processing ${file}: ${error.message}`);
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
if (langRemoved === 0) {
|
|
195
|
-
console.log(` ā
${langCode}: No unused keys found`);
|
|
196
|
-
} else {
|
|
197
|
-
console.log(` š ${langCode}: Removed ${langRemoved} unused key(s) from ${langFiles} file(s)`);
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
console.log('\nš Summary:');
|
|
202
|
-
console.log(` Languages processed: ${languageDirs.length}`);
|
|
203
|
-
console.log(` Files modified: ${totalFiles}`);
|
|
204
|
-
console.log(` Total keys removed: ${totalRemoved}`);
|
|
205
|
-
|
|
206
|
-
if (dryRun) {
|
|
207
|
-
console.log('\nš” Run without --dry-run to actually remove the keys.');
|
|
208
|
-
} else if (totalRemoved > 0) {
|
|
209
|
-
console.log('\nā
Unused keys removed successfully!');
|
|
210
|
-
} else {
|
|
211
|
-
console.log('\nā
No unused keys found!');
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
main();
|
|
216
|
-
|
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/* eslint-disable no-console */
|
|
3
|
-
|
|
4
|
-
const fs = require("fs");
|
|
5
|
-
const path = require("path");
|
|
6
|
-
const { getLocalesDir } = require('./utils/findLocalesDir');
|
|
7
|
-
|
|
8
|
-
// All 38 languages (excluding en-US)
|
|
9
|
-
const LANGUAGES = [
|
|
10
|
-
"ar-SA", // Arabic
|
|
11
|
-
"bg-BG", // Bulgarian
|
|
12
|
-
"cs-CZ", // Czech
|
|
13
|
-
"da-DK", // Danish
|
|
14
|
-
"de-DE", // German
|
|
15
|
-
"el-GR", // Greek
|
|
16
|
-
"en-AU", // English (Australia)
|
|
17
|
-
"en-CA", // English (Canada)
|
|
18
|
-
"en-GB", // English (UK)
|
|
19
|
-
"es-ES", // Spanish (Spain)
|
|
20
|
-
"es-MX", // Spanish (Mexico)
|
|
21
|
-
"fi-FI", // Finnish
|
|
22
|
-
"fr-CA", // French (Canada)
|
|
23
|
-
"fr-FR", // French (France)
|
|
24
|
-
"hi-IN", // Hindi
|
|
25
|
-
"hr-HR", // Croatian
|
|
26
|
-
"hu-HU", // Hungarian
|
|
27
|
-
"id-ID", // Indonesian
|
|
28
|
-
"it-IT", // Italian
|
|
29
|
-
"ja-JP", // Japanese
|
|
30
|
-
"ko-KR", // Korean
|
|
31
|
-
"ms-MY", // Malay
|
|
32
|
-
"nl-NL", // Dutch
|
|
33
|
-
"no-NO", // Norwegian
|
|
34
|
-
"pl-PL", // Polish
|
|
35
|
-
"pt-BR", // Portuguese (Brazil)
|
|
36
|
-
"pt-PT", // Portuguese (Portugal)
|
|
37
|
-
"ro-RO", // Romanian
|
|
38
|
-
"ru-RU", // Russian
|
|
39
|
-
"sk-SK", // Slovak
|
|
40
|
-
"sv-SE", // Swedish
|
|
41
|
-
"th-TH", // Thai
|
|
42
|
-
"tl-PH", // Tagalog
|
|
43
|
-
"tr-TR", // Turkish
|
|
44
|
-
"uk-UA", // Ukrainian
|
|
45
|
-
"vi-VN", // Vietnamese
|
|
46
|
-
"zh-CN", // Chinese Simplified
|
|
47
|
-
"zh-TW", // Chinese Traditional
|
|
48
|
-
];
|
|
49
|
-
|
|
50
|
-
// Default translation files from package
|
|
51
|
-
const DEFAULT_FILES = [
|
|
52
|
-
'auth.json',
|
|
53
|
-
'branding.json',
|
|
54
|
-
'datetime.json',
|
|
55
|
-
'errors.json',
|
|
56
|
-
'flashcards.json',
|
|
57
|
-
'general.json',
|
|
58
|
-
'navigation.json',
|
|
59
|
-
'onboarding.json',
|
|
60
|
-
'settings.json',
|
|
61
|
-
];
|
|
62
|
-
|
|
63
|
-
// Get path to package's default en-US files
|
|
64
|
-
function getPackageEnUSPath() {
|
|
65
|
-
// Script is in: node_modules/@umituz/react-native-localization/scripts/setup-languages.js
|
|
66
|
-
// Package en-US is in: node_modules/@umituz/react-native-localization/src/infrastructure/locales/en-US
|
|
67
|
-
const scriptDir = __dirname;
|
|
68
|
-
const packageRoot = path.resolve(scriptDir, '..');
|
|
69
|
-
return path.join(packageRoot, 'src/infrastructure/locales/en-US');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async function setupLanguages() {
|
|
73
|
-
// Find or create project's locales directory
|
|
74
|
-
const localesDir = getLocalesDir(true); // Create if not exists
|
|
75
|
-
const enUSDir = path.join(localesDir, "en-US");
|
|
76
|
-
const packageEnUSPath = getPackageEnUSPath();
|
|
77
|
-
|
|
78
|
-
console.log("š Setting up language directories and files...\n");
|
|
79
|
-
|
|
80
|
-
// Create en-US directory if it doesn't exist
|
|
81
|
-
if (!fs.existsSync(enUSDir)) {
|
|
82
|
-
fs.mkdirSync(enUSDir, { recursive: true });
|
|
83
|
-
console.log(`š Created directory: en-US/`);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Check if en-US directory has any JSON files
|
|
87
|
-
let files = [];
|
|
88
|
-
if (fs.existsSync(enUSDir)) {
|
|
89
|
-
files = fs
|
|
90
|
-
.readdirSync(enUSDir)
|
|
91
|
-
.filter((file) => file.endsWith(".json"))
|
|
92
|
-
.sort();
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// If no files found, copy default files from package
|
|
96
|
-
if (files.length === 0) {
|
|
97
|
-
console.log("š¦ No JSON files found in en-US directory.");
|
|
98
|
-
console.log(" Copying default files from package...\n");
|
|
99
|
-
|
|
100
|
-
if (!fs.existsSync(packageEnUSPath)) {
|
|
101
|
-
console.error("ā Package default files not found!");
|
|
102
|
-
console.error(" Expected path:", packageEnUSPath);
|
|
103
|
-
console.error(" Please ensure @umituz/react-native-localization is installed.");
|
|
104
|
-
process.exit(1);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Copy default files from package
|
|
108
|
-
for (const file of DEFAULT_FILES) {
|
|
109
|
-
const packageFile = path.join(packageEnUSPath, file);
|
|
110
|
-
const targetFile = path.join(enUSDir, file);
|
|
111
|
-
|
|
112
|
-
if (fs.existsSync(packageFile)) {
|
|
113
|
-
const content = fs.readFileSync(packageFile, "utf8");
|
|
114
|
-
fs.writeFileSync(targetFile, content);
|
|
115
|
-
console.log(` š Created: en-US/${file}`);
|
|
116
|
-
files.push(file);
|
|
117
|
-
} else {
|
|
118
|
-
console.warn(` ā ļø Warning: Default file not found in package: ${file}`);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (files.length === 0) {
|
|
123
|
-
console.error("ā Failed to copy default files from package!");
|
|
124
|
-
process.exit(1);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
console.log("");
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
console.log(`š Found ${files.length} translation files in en-US:`);
|
|
131
|
-
files.forEach((file) => console.log(` - ${file}`));
|
|
132
|
-
console.log("");
|
|
133
|
-
|
|
134
|
-
let createdDirs = 0;
|
|
135
|
-
let createdFiles = 0;
|
|
136
|
-
|
|
137
|
-
for (const langCode of LANGUAGES) {
|
|
138
|
-
const langDir = path.join(localesDir, langCode);
|
|
139
|
-
|
|
140
|
-
// Create language directory if it doesn't exist
|
|
141
|
-
if (!fs.existsSync(langDir)) {
|
|
142
|
-
fs.mkdirSync(langDir, { recursive: true });
|
|
143
|
-
console.log(`š Created directory: ${langCode}/`);
|
|
144
|
-
createdDirs++;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Copy each file from en-US
|
|
148
|
-
for (const file of files) {
|
|
149
|
-
const enUSFile = path.join(enUSDir, file);
|
|
150
|
-
const targetFile = path.join(langDir, file);
|
|
151
|
-
|
|
152
|
-
if (!fs.existsSync(targetFile)) {
|
|
153
|
-
// Copy the en-US file as a starting point
|
|
154
|
-
const content = fs.readFileSync(enUSFile, "utf8");
|
|
155
|
-
fs.writeFileSync(targetFile, content);
|
|
156
|
-
console.log(` š Created: ${langCode}/${file}`);
|
|
157
|
-
createdFiles++;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Create index.ts files for all languages (including en-US)
|
|
163
|
-
console.log(`\nš Creating index.ts loaders for all languages...`);
|
|
164
|
-
let createdIndexFiles = 0;
|
|
165
|
-
|
|
166
|
-
// Create index.ts for en-US
|
|
167
|
-
const enUSIndexPath = path.join(enUSDir, 'index.ts');
|
|
168
|
-
if (!fs.existsSync(enUSIndexPath)) {
|
|
169
|
-
const enUSIndexContent = `/**
|
|
170
|
-
* Auto-loader for en-US translation modules
|
|
171
|
-
*
|
|
172
|
-
* AUTOMATIC TRANSLATION FILE DETECTION:
|
|
173
|
-
* - Uses Metro bundler's require.context to auto-discover .json files
|
|
174
|
-
* - Adding new translation file = just create .json file (zero manual updates)
|
|
175
|
-
* - Build-time resolution (fast, no runtime overhead)
|
|
176
|
-
* - Works for all languages automatically
|
|
177
|
-
*
|
|
178
|
-
* OFFLINE-ONLY TRANSLATIONS (All domains work without backend):
|
|
179
|
-
* - Automatically imports ALL .json files in this directory
|
|
180
|
-
* - Alphabetically sorted for consistency
|
|
181
|
-
* - Type-safe with TypeScript
|
|
182
|
-
*
|
|
183
|
-
* USAGE:
|
|
184
|
-
* 1. Create new translation file: my_domain.json
|
|
185
|
-
* 2. File is auto-discovered and loaded
|
|
186
|
-
* 3. Access via t('my_domain.key')
|
|
187
|
-
*
|
|
188
|
-
* This file is automatically generated by setup-languages.js
|
|
189
|
-
* but can be manually edited if needed.
|
|
190
|
-
*/
|
|
191
|
-
|
|
192
|
-
// Metro bundler require.context - auto-discover all .json files
|
|
193
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
194
|
-
const translationContext = (require as any).context('./', false, /\\.json$/);
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Load all JSON modules automatically
|
|
198
|
-
* Extracts module name from path (e.g., './auth.json' -> 'auth')
|
|
199
|
-
*/
|
|
200
|
-
const translations: Record<string, any> = {};
|
|
201
|
-
|
|
202
|
-
translationContext.keys().forEach((key: string) => {
|
|
203
|
-
// Extract module name from path: './auth.json' -> 'auth'
|
|
204
|
-
const match = key.match(/\\.\\/([^/]+)\\.json$/);
|
|
205
|
-
if (match) {
|
|
206
|
-
const moduleName = match[1];
|
|
207
|
-
translations[moduleName] = translationContext(key);
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
export default translations;
|
|
212
|
-
`;
|
|
213
|
-
fs.writeFileSync(enUSIndexPath, enUSIndexContent, 'utf8');
|
|
214
|
-
console.log(` š Created: en-US/index.ts`);
|
|
215
|
-
createdIndexFiles++;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Create index.ts for all other languages
|
|
219
|
-
for (const langCode of LANGUAGES) {
|
|
220
|
-
const langDir = path.join(localesDir, langCode);
|
|
221
|
-
const indexPath = path.join(langDir, 'index.ts');
|
|
222
|
-
|
|
223
|
-
if (fs.existsSync(langDir) && !fs.existsSync(indexPath)) {
|
|
224
|
-
const indexContent = `/**
|
|
225
|
-
* Auto-loader for ${langCode} translation modules
|
|
226
|
-
*
|
|
227
|
-
* AUTOMATIC TRANSLATION FILE DETECTION:
|
|
228
|
-
* - Uses Metro bundler's require.context to auto-discover .json files
|
|
229
|
-
* - Adding new translation file = just create .json file (zero manual updates)
|
|
230
|
-
* - Build-time resolution (fast, no runtime overhead)
|
|
231
|
-
* - Works for all languages automatically
|
|
232
|
-
*
|
|
233
|
-
* OFFLINE-ONLY TRANSLATIONS (All domains work without backend):
|
|
234
|
-
* - Automatically imports ALL .json files in this directory
|
|
235
|
-
* - Alphabetically sorted for consistency
|
|
236
|
-
* - Type-safe with TypeScript
|
|
237
|
-
*
|
|
238
|
-
* USAGE:
|
|
239
|
-
* 1. Create new translation file: my_domain.json
|
|
240
|
-
* 2. File is auto-discovered and loaded
|
|
241
|
-
* 3. Access via t('my_domain.key')
|
|
242
|
-
*
|
|
243
|
-
* This file is automatically generated by setup-languages.js
|
|
244
|
-
* but can be manually edited if needed.
|
|
245
|
-
*/
|
|
246
|
-
|
|
247
|
-
// Metro bundler require.context - auto-discover all .json files
|
|
248
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
249
|
-
const translationContext = (require as any).context('./', false, /\\.json$/);
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Load all JSON modules automatically
|
|
253
|
-
* Extracts module name from path (e.g., './auth.json' -> 'auth')
|
|
254
|
-
*/
|
|
255
|
-
const translations: Record<string, any> = {};
|
|
256
|
-
|
|
257
|
-
translationContext.keys().forEach((key: string) => {
|
|
258
|
-
// Extract module name from path: './auth.json' -> 'auth'
|
|
259
|
-
const match = key.match(/\\.\\/([^/]+)\\.json$/);
|
|
260
|
-
if (match) {
|
|
261
|
-
const moduleName = match[1];
|
|
262
|
-
translations[moduleName] = translationContext(key);
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
export default translations;
|
|
267
|
-
`;
|
|
268
|
-
fs.writeFileSync(indexPath, indexContent, 'utf8');
|
|
269
|
-
console.log(` š Created: ${langCode}/index.ts`);
|
|
270
|
-
createdIndexFiles++;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
console.log(`\nā
Setup completed!`);
|
|
275
|
-
console.log(` Directories created: ${createdDirs}`);
|
|
276
|
-
console.log(` Files created: ${createdFiles}`);
|
|
277
|
-
console.log(` Index files created: ${createdIndexFiles}`);
|
|
278
|
-
console.log(` Total languages: ${LANGUAGES.length + 1} (including en-US)`);
|
|
279
|
-
console.log(
|
|
280
|
-
`\nš Next steps:`,
|
|
281
|
-
);
|
|
282
|
-
console.log(` 1. Add your translation keys to en-US/*.json files`);
|
|
283
|
-
console.log(` 2. Run 'npm run i18n:translate' to auto-translate all languages`);
|
|
284
|
-
console.log(` 3. Run 'npm run i18n:check all' to verify completeness`);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
setupLanguages().catch((error) => {
|
|
288
|
-
console.error("ā Setup failed:", error);
|
|
289
|
-
process.exit(1);
|
|
290
|
-
});
|