@umituz/react-native-google-translate 1.0.4 → 1.0.6

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.
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Sync Translations Script
5
+ * Synchronizes translation keys from en-US.ts to all other language files
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.syncLanguageFile = syncLanguageFile;
12
+ exports.syncTranslations = syncTranslations;
13
+ exports.runSyncTranslations = runSyncTranslations;
14
+ const fs_1 = __importDefault(require("fs"));
15
+ const path_1 = __importDefault(require("path"));
16
+ const file_parser_1 = require("./utils/file-parser");
17
+ const sync_helper_1 = require("./utils/sync-helper");
18
+ const key_detector_1 = require("./utils/key-detector");
19
+ const key_extractor_1 = require("./utils/key-extractor");
20
+ const object_helper_1 = require("./utils/object-helper");
21
+ function syncLanguageFile(enUSPath, targetPath, langCode) {
22
+ const enUS = (0, file_parser_1.parseTypeScriptFile)(enUSPath);
23
+ let target;
24
+ try {
25
+ target = (0, file_parser_1.parseTypeScriptFile)(targetPath);
26
+ }
27
+ catch {
28
+ target = {};
29
+ }
30
+ const detectedNewKeys = (0, key_detector_1.detectNewKeys)(enUS, target);
31
+ const addStats = { added: 0, newKeys: [] };
32
+ const removeStats = { removed: 0, removedKeys: [] };
33
+ (0, sync_helper_1.addMissingKeys)(enUS, target, addStats);
34
+ (0, sync_helper_1.removeExtraKeys)(enUS, target, removeStats);
35
+ const changed = (addStats.added || 0) > 0 || (removeStats.removed || 0) > 0;
36
+ if (changed) {
37
+ const content = (0, file_parser_1.generateTypeScriptContent)(target, langCode);
38
+ fs_1.default.writeFileSync(targetPath, content);
39
+ }
40
+ return {
41
+ added: addStats.added,
42
+ newKeys: addStats.newKeys,
43
+ removed: removeStats.removed,
44
+ removedKeys: removeStats.removedKeys,
45
+ changed,
46
+ detectedNewKeys,
47
+ };
48
+ }
49
+ function processExtraction(srcDir, enUSPath) {
50
+ if (!srcDir)
51
+ return;
52
+ console.log(`🔍 Scanning source code and dependencies: ${srcDir}...`);
53
+ const usedKeyMap = (0, key_extractor_1.extractUsedKeys)(srcDir);
54
+ console.log(` Found ${usedKeyMap.size} unique keys.`);
55
+ const oldEnUS = (0, file_parser_1.parseTypeScriptFile)(enUSPath);
56
+ const newEnUS = {};
57
+ let addedCount = 0;
58
+ for (const [key, defaultValue] of usedKeyMap) {
59
+ // Try to keep existing translation if it exists
60
+ const existingValue = key.split('.').reduce((obj, k) => {
61
+ if (obj && typeof obj === 'object' && k in obj) {
62
+ return obj[k];
63
+ }
64
+ return undefined;
65
+ }, oldEnUS);
66
+ // We treat it as "not translated" if the value is exactly the key string
67
+ const isActuallyTranslated = typeof existingValue === 'string' && existingValue !== key;
68
+ const valueToSet = isActuallyTranslated ? existingValue : defaultValue;
69
+ if ((0, object_helper_1.setDeep)(newEnUS, key, valueToSet)) {
70
+ if (!isActuallyTranslated)
71
+ addedCount++;
72
+ }
73
+ }
74
+ const oldTotal = (0, object_helper_1.countKeys)(oldEnUS);
75
+ const newTotal = (0, object_helper_1.countKeys)(newEnUS);
76
+ const removedCount = Math.max(0, oldTotal - (newTotal - addedCount));
77
+ console.log(` ✨ Optimized en-US.ts: ${addedCount} keys populated/updated, pruned ${removedCount} unused.`);
78
+ const content = (0, file_parser_1.generateTypeScriptContent)(newEnUS, 'en-US');
79
+ fs_1.default.writeFileSync(enUSPath, content);
80
+ }
81
+ function syncTranslations(options) {
82
+ const { targetDir, srcDir } = options;
83
+ const localesDir = path_1.default.resolve(process.cwd(), targetDir);
84
+ const enUSPath = path_1.default.join(localesDir, 'en-US.ts');
85
+ if (!fs_1.default.existsSync(localesDir) || !fs_1.default.existsSync(enUSPath)) {
86
+ console.error(`❌ Localization files not found in: ${localesDir}`);
87
+ return false;
88
+ }
89
+ processExtraction(srcDir, enUSPath);
90
+ const files = fs_1.default.readdirSync(localesDir)
91
+ .filter(f => f.match(/^[a-z]{2}-[A-Z]{2}\.ts$/) && f !== 'en-US.ts')
92
+ .sort();
93
+ console.log(`📊 Languages to sync: ${files.length}\n`);
94
+ files.forEach(file => {
95
+ const langCode = file.replace('.ts', '');
96
+ const targetPath = path_1.default.join(localesDir, file);
97
+ const result = syncLanguageFile(enUSPath, targetPath, langCode);
98
+ if (result.changed) {
99
+ console.log(` 🌍 ${langCode}: ✏️ +${result.added || 0} keys, -${result.removed || 0} keys`);
100
+ }
101
+ });
102
+ console.log(`\n✅ Synchronization completed!`);
103
+ return true;
104
+ }
105
+ // CLI interface
106
+ function runSyncTranslations() {
107
+ const targetDir = process.argv[2] || 'src/infrastructure/locales';
108
+ const srcDir = process.argv[3];
109
+ console.log('🚀 Starting translation synchronization...\n');
110
+ syncTranslations({ targetDir, srcDir });
111
+ }
112
+ // Check if this file is being run directly
113
+ if (require.main === module || process.argv[1].endsWith('/sync.js') || process.argv[1].endsWith('\\sync.js')) {
114
+ runSyncTranslations();
115
+ }
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Translate Missing Script
5
+ * Automatically translates missing strings using Google Translate
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.translateMissing = translateMissing;
12
+ exports.runTranslateMissing = runTranslateMissing;
13
+ const fs_1 = __importDefault(require("fs"));
14
+ const path_1 = __importDefault(require("path"));
15
+ const file_parser_1 = require("./utils/file-parser");
16
+ const services_1 = require("../infrastructure/services");
17
+ // Width of terminal line to clear for progress updates
18
+ const PROGRESS_LINE_WIDTH = 80;
19
+ async function translateMissing(options) {
20
+ const { targetDir, srcDir, skipSync = false } = options;
21
+ // Initialize the translation service
22
+ services_1.googleTranslateService.initialize({
23
+ minDelay: 100,
24
+ maxRetries: 3,
25
+ timeout: 10000,
26
+ });
27
+ const localesDir = path_1.default.resolve(process.cwd(), targetDir);
28
+ const enUSPath = path_1.default.join(localesDir, 'en-US.ts');
29
+ if (!fs_1.default.existsSync(localesDir) || !fs_1.default.existsSync(enUSPath)) {
30
+ console.error(`❌ Localization files not found in: ${localesDir}`);
31
+ return;
32
+ }
33
+ const files = fs_1.default.readdirSync(localesDir)
34
+ .filter(f => f.match(/^[a-z]{2}-[A-Z]{2}\.ts$/) && f !== 'en-US.ts')
35
+ .sort();
36
+ console.log(`\n📊 Languages to translate: ${files.length}\n`);
37
+ const enUS = (0, file_parser_1.parseTypeScriptFile)(enUSPath);
38
+ for (const file of files) {
39
+ const langCode = file.replace('.ts', '');
40
+ // Skip English variants
41
+ const targetLang = (0, services_1.getTargetLanguage)(langCode);
42
+ if (!targetLang || targetLang === 'en') {
43
+ console.log(`⏭️ Skipping ${langCode} (English variant)`);
44
+ continue;
45
+ }
46
+ const langName = (0, services_1.getLanguageDisplayName)(langCode);
47
+ console.log(`🌍 Translating ${langCode} (${langName})...`);
48
+ const targetPath = path_1.default.join(localesDir, file);
49
+ const target = (0, file_parser_1.parseTypeScriptFile)(targetPath);
50
+ const stats = {
51
+ totalCount: 0,
52
+ successCount: 0,
53
+ failureCount: 0,
54
+ skippedCount: 0,
55
+ translatedKeys: [],
56
+ };
57
+ await services_1.googleTranslateService.translateObject(enUS, target, targetLang, '', stats);
58
+ // Clear progress line
59
+ process.stdout.write('\r' + ' '.repeat(PROGRESS_LINE_WIDTH) + '\r');
60
+ if (stats.successCount > 0) {
61
+ const content = (0, file_parser_1.generateTypeScriptContent)(target, langCode);
62
+ fs_1.default.writeFileSync(targetPath, content);
63
+ console.log(` ✅ Successfully translated ${stats.successCount} keys:`);
64
+ // Detailed logging of translated keys
65
+ const displayCount = Math.min(stats.translatedKeys.length, 15);
66
+ stats.translatedKeys.slice(0, displayCount).forEach(item => {
67
+ console.log(` • ${item.key}: "${item.from}" → "${item.to}"`);
68
+ });
69
+ if (stats.translatedKeys.length > displayCount) {
70
+ console.log(` ... and ${stats.translatedKeys.length - displayCount} more.`);
71
+ }
72
+ }
73
+ else {
74
+ console.log(` ✨ Already up to date.`);
75
+ }
76
+ }
77
+ console.log('\n✅ All translations completed!');
78
+ }
79
+ // CLI interface
80
+ function runTranslateMissing() {
81
+ const args = process.argv.slice(2).filter(arg => !arg.startsWith('--'));
82
+ const targetDir = args[0] || 'src/infrastructure/locales';
83
+ const srcDir = args[1];
84
+ const skipSync = process.argv.includes('--no-sync');
85
+ console.log('🚀 Starting integrated translation workflow...');
86
+ translateMissing({ targetDir, srcDir, skipSync }).catch(err => {
87
+ console.error('\n❌ Translation workflow failed:', err.message);
88
+ process.exit(1);
89
+ });
90
+ }
91
+ // Check if this file is being run directly
92
+ if (require.main === module || process.argv[1].endsWith('/translate.js') || process.argv[1].endsWith('\\translate.js')) {
93
+ runTranslateMissing();
94
+ }
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parseTypeScriptFile = parseTypeScriptFile;
7
+ exports.stringifyValue = stringifyValue;
8
+ exports.generateTypeScriptContent = generateTypeScriptContent;
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const textValidator_util_1 = require("../../infrastructure/utils/textValidator.util");
12
+ /**
13
+ * File Parser
14
+ * Parse and generate TypeScript translation files
15
+ */
16
+ function parseTypeScriptFile(filePath) {
17
+ const content = fs_1.default.readFileSync(filePath, 'utf8');
18
+ // Match: export default { ... } OR export const NAME = { ... }
19
+ const match = content.match(/export\s+(?:default|const\s+\w+\s*=)\s*(\{[\s\S]*\});?\s*$/);
20
+ if (!match) {
21
+ throw new Error(`Could not parse TypeScript file: ${filePath}`);
22
+ }
23
+ const objectStr = match[1].replace(/;$/, '');
24
+ try {
25
+ // Basic evaluation for simple objects (safe for generated translation files)
26
+ // Only contains string literals, numbers, booleans, and nested objects
27
+ // eslint-disable-next-line no-eval
28
+ return eval(`(${objectStr})`);
29
+ }
30
+ catch (error) {
31
+ // File might be a barrel file with named imports
32
+ const dir = path_1.default.dirname(filePath);
33
+ const importMatches = [...content.matchAll(/import\s*\{\s*(\w+)\s*\}\s*from\s*["']\.\/(\w+)["']/g)];
34
+ if (importMatches.length > 0) {
35
+ const result = {};
36
+ for (const [, varName, moduleName] of importMatches) {
37
+ const subFilePath = path_1.default.join(dir, `${moduleName}.ts`);
38
+ if (fs_1.default.existsSync(subFilePath)) {
39
+ try {
40
+ result[varName] = parseTypeScriptFile(subFilePath);
41
+ }
42
+ catch (subError) {
43
+ // Log sub-file parse errors but continue with other files
44
+ console.warn(`Warning: Could not parse sub-file ${subFilePath}: ${subError instanceof Error ? subError.message : 'Unknown error'}`);
45
+ }
46
+ }
47
+ }
48
+ if (Object.keys(result).length > 0) {
49
+ return result;
50
+ }
51
+ }
52
+ }
53
+ return {};
54
+ }
55
+ function stringifyValue(value, indent = 2) {
56
+ if (typeof value === 'string') {
57
+ const escaped = value
58
+ .replace(/\\/g, '\\\\')
59
+ .replace(/"/g, '\\"')
60
+ .replace(/\n/g, '\\n');
61
+ return `"${escaped}"`;
62
+ }
63
+ if (Array.isArray(value)) {
64
+ if (value.length === 0)
65
+ return '[]';
66
+ const items = value.map(v => stringifyValue(v, indent + 2));
67
+ return `[${items.join(', ')}]`;
68
+ }
69
+ if (typeof value === 'object' && value !== null) {
70
+ const entries = Object.entries(value);
71
+ if (entries.length === 0) {
72
+ return '{}';
73
+ }
74
+ const spaces = ' '.repeat(indent);
75
+ const innerSpaces = ' '.repeat(indent + 2);
76
+ const entriesStr = entries
77
+ .sort((a, b) => a[0].localeCompare(b[0]))
78
+ .map(([k, v]) => {
79
+ const key = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(k) ? k : `"${k}"`;
80
+ return `${innerSpaces}${key}: ${stringifyValue(v, indent + 2)}`;
81
+ })
82
+ .join(',\n');
83
+ return `{\n${entriesStr},\n${spaces}}`;
84
+ }
85
+ return String(value);
86
+ }
87
+ function generateTypeScriptContent(obj, langCode) {
88
+ const langName = (0, textValidator_util_1.getLanguageDisplayName)(langCode);
89
+ const isBase = langCode === 'en-US';
90
+ const objString = stringifyValue(obj, 0);
91
+ return `/**
92
+ * ${langName} Translations
93
+ * ${isBase ? 'Base translations file' : 'Auto-synced from en-US.ts'}
94
+ */
95
+
96
+ export default ${objString};
97
+ `;
98
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ /**
3
+ * Scripts Utils
4
+ * Utility functions for translation scripts
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ __exportStar(require("./file-parser"), exports);
22
+ __exportStar(require("./key-detector"), exports);
23
+ __exportStar(require("./key-extractor"), exports);
24
+ __exportStar(require("./object-helper"), exports);
25
+ __exportStar(require("./sync-helper"), exports);
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ /**
3
+ * Key Detector
4
+ * Detects new, missing, and removed keys between source and target objects
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.detectNewKeys = detectNewKeys;
8
+ exports.detectMissingKeys = detectMissingKeys;
9
+ function detectNewKeys(sourceObj, targetObj, path = '', newKeys = []) {
10
+ for (const key in sourceObj) {
11
+ const currentPath = path ? `${path}.${key}` : key;
12
+ const sourceValue = sourceObj[key];
13
+ const targetValue = targetObj[key];
14
+ if (!Object.prototype.hasOwnProperty.call(targetObj, key)) {
15
+ newKeys.push({ path: currentPath, value: sourceValue });
16
+ }
17
+ else if (typeof sourceValue === 'object' &&
18
+ sourceValue !== null &&
19
+ !Array.isArray(sourceValue)) {
20
+ if (typeof targetValue === 'object' && targetValue !== null && !Array.isArray(targetValue)) {
21
+ detectNewKeys(sourceValue, targetValue, currentPath, newKeys);
22
+ }
23
+ }
24
+ }
25
+ return newKeys;
26
+ }
27
+ function detectMissingKeys(sourceObj, targetObj, path = '', missingKeys = []) {
28
+ for (const key in targetObj) {
29
+ const currentPath = path ? `${path}.${key}` : key;
30
+ if (!Object.prototype.hasOwnProperty.call(sourceObj, key)) {
31
+ missingKeys.push(currentPath);
32
+ }
33
+ else if (typeof sourceObj[key] === 'object' &&
34
+ sourceObj[key] !== null &&
35
+ !Array.isArray(sourceObj[key]) &&
36
+ typeof targetObj[key] === 'object' &&
37
+ targetObj[key] !== null &&
38
+ !Array.isArray(targetObj[key])) {
39
+ detectMissingKeys(sourceObj[key], targetObj[key], currentPath, missingKeys);
40
+ }
41
+ }
42
+ return missingKeys;
43
+ }
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.extractUsedKeys = extractUsedKeys;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ /**
10
+ * Generic Key Extractor
11
+ * Scans source code for i18n translation keys
12
+ */
13
+ const IGNORED_DOMAINS = ['.com', '.org', '.net', '.io', '.co', '.app', '.ai', '.gov', '.edu'];
14
+ const IGNORED_EXTENSIONS = [
15
+ '.ts', '.tsx', '.js', '.jsx', '.json', '.yaml', '.yml',
16
+ '.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.pdf',
17
+ '.mp4', '.mov', '.avi', '.mp3', '.wav', '.css', '.scss', '.md'
18
+ ];
19
+ const IGNORED_LAYOUT_VALS = new Set([
20
+ 'center', 'row', 'column', 'flex', 'absolute', 'relative', 'hidden', 'visible',
21
+ 'transparent', 'bold', 'normal', 'italic', 'contain', 'cover', 'stretch',
22
+ 'top', 'bottom', 'left', 'right', 'middle', 'auto', 'none', 'underline',
23
+ 'capitalize', 'uppercase', 'lowercase', 'solid', 'dotted', 'dashed', 'wrap',
24
+ 'nowrap', 'space-between', 'space-around', 'flex-start', 'flex-end', 'baseline',
25
+ 'react', 'index', 'default', 'string', 'number', 'boolean', 'key', 'id'
26
+ ]);
27
+ function extractFromFile(content, keyMap) {
28
+ // Pattern 1: t('key') or t("key")
29
+ const tRegex = /(?:^|\W)t\(['"`]([^'"`]+)['"`]\)/g;
30
+ let match;
31
+ while ((match = tRegex.exec(content)) !== null) {
32
+ const key = match[1];
33
+ if (!key.includes('${') && !keyMap.has(key)) {
34
+ keyMap.set(key, key);
35
+ }
36
+ }
37
+ // Pattern 2: Dot-notation strings (potential i18n keys)
38
+ const dotRegex = /['"`]([a-z][a-z0-9_]*\.(?:[a-z0-9_]+\.)+[a-z0-9_]+)['"`]/gi;
39
+ while ((match = dotRegex.exec(content)) !== null) {
40
+ const key = match[1];
41
+ const isIgnoredDomain = IGNORED_DOMAINS.some(ext => key.toLowerCase().endsWith(ext));
42
+ const isIgnoredExt = IGNORED_EXTENSIONS.some(ext => key.toLowerCase().endsWith(ext));
43
+ if (!isIgnoredDomain && !isIgnoredExt && !key.includes(' ') && !keyMap.has(key)) {
44
+ keyMap.set(key, key);
45
+ }
46
+ }
47
+ // Pattern 3: Template literals t(`prefix.${var}`)
48
+ const templateRegex = /t\(\`([a-z0-9_.]+)\.\$\{/g;
49
+ while ((match = templateRegex.exec(content)) !== null) {
50
+ const prefix = match[1];
51
+ const arrayMatches = content.matchAll(/\[([\s\S]*?)\]/g);
52
+ for (const arrayMatch of arrayMatches) {
53
+ const inner = arrayMatch[1];
54
+ const idMatches = inner.matchAll(/['"`]([a-z0-9_]{2,40})['"`]/g);
55
+ for (const idMatch of idMatches) {
56
+ const id = idMatch[1];
57
+ if (IGNORED_LAYOUT_VALS.has(id.toLowerCase()))
58
+ continue;
59
+ if (/^[0-9]+$/.test(id))
60
+ continue;
61
+ const dynamicKey = `${prefix}.${id}`;
62
+ if (!keyMap.has(dynamicKey)) {
63
+ keyMap.set(dynamicKey, dynamicKey);
64
+ }
65
+ }
66
+ }
67
+ }
68
+ }
69
+ function walkDirectory(dir, keyMap, skipDirs = ['node_modules', '.expo', '.git', 'build', 'ios', 'android', 'assets', 'locales', '__tests__']) {
70
+ if (!fs_1.default.existsSync(dir))
71
+ return;
72
+ const files = fs_1.default.readdirSync(dir);
73
+ for (const file of files) {
74
+ const fullPath = path_1.default.join(dir, file);
75
+ const stat = fs_1.default.statSync(fullPath);
76
+ if (stat.isDirectory()) {
77
+ if (!skipDirs.includes(file)) {
78
+ walkDirectory(fullPath, keyMap, skipDirs);
79
+ }
80
+ }
81
+ else if (/\.(ts|tsx|js|jsx)$/.test(file)) {
82
+ const content = fs_1.default.readFileSync(fullPath, 'utf8');
83
+ extractFromFile(content, keyMap);
84
+ }
85
+ }
86
+ }
87
+ function extractUsedKeys(srcDir) {
88
+ const keyMap = new Map();
89
+ if (!srcDir)
90
+ return keyMap;
91
+ const projectRoot = process.cwd();
92
+ const absoluteSrcDir = path_1.default.resolve(projectRoot, srcDir);
93
+ // Scan project source
94
+ walkDirectory(absoluteSrcDir, keyMap);
95
+ // Scan @umituz packages for shared keys
96
+ const packagesDir = path_1.default.resolve(projectRoot, 'node_modules/@umituz');
97
+ if (fs_1.default.existsSync(packagesDir)) {
98
+ walkDirectory(packagesDir, keyMap);
99
+ }
100
+ return keyMap;
101
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ /**
3
+ * Object Helper
4
+ * Utilities for deep object manipulation
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.setDeep = setDeep;
8
+ exports.countKeys = countKeys;
9
+ /**
10
+ * Set a value in a nested object, creating intermediate objects if necessary
11
+ * Returns true if the key was newly added, false if it already existed
12
+ */
13
+ function setDeep(obj, path, value) {
14
+ const keys = path.split('.');
15
+ let current = obj;
16
+ for (let i = 0; i < keys.length - 1; i++) {
17
+ const key = keys[i];
18
+ if (!current[key] || typeof current[key] !== 'object' || Array.isArray(current[key])) {
19
+ current[key] = {};
20
+ }
21
+ current = current[key];
22
+ }
23
+ const lastKey = keys[keys.length - 1];
24
+ if (current[lastKey] === undefined) {
25
+ current[lastKey] = value;
26
+ return true;
27
+ }
28
+ return false;
29
+ }
30
+ /**
31
+ * Count all leaf keys in a nested object
32
+ */
33
+ function countKeys(obj) {
34
+ let count = 0;
35
+ const walk = (o) => {
36
+ for (const k in o) {
37
+ if (typeof o[k] === 'object' && o[k] !== null) {
38
+ walk(o[k]);
39
+ }
40
+ else {
41
+ count++;
42
+ }
43
+ }
44
+ };
45
+ walk(obj);
46
+ return count;
47
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ /**
3
+ * Sync Helper
4
+ * Helper functions for synchronizing translation keys
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.addMissingKeys = addMissingKeys;
8
+ exports.removeExtraKeys = removeExtraKeys;
9
+ function addMissingKeys(sourceObj, targetObj, stats = {}) {
10
+ stats.added = stats.added || 0;
11
+ stats.newKeys = stats.newKeys || [];
12
+ for (const key in sourceObj) {
13
+ const sourceValue = sourceObj[key];
14
+ const isNewKey = !Object.prototype.hasOwnProperty.call(targetObj, key);
15
+ if (isNewKey) {
16
+ targetObj[key] = sourceValue;
17
+ stats.added++;
18
+ stats.newKeys.push(key);
19
+ }
20
+ else if (typeof sourceValue === 'object' &&
21
+ sourceValue !== null &&
22
+ !Array.isArray(sourceValue)) {
23
+ if (!targetObj[key] || typeof targetObj[key] !== 'object') {
24
+ targetObj[key] = {};
25
+ }
26
+ addMissingKeys(sourceValue, targetObj[key], stats);
27
+ }
28
+ }
29
+ return stats;
30
+ }
31
+ function removeExtraKeys(sourceObj, targetObj, stats = {}) {
32
+ stats.removed = stats.removed || 0;
33
+ stats.removedKeys = stats.removedKeys || [];
34
+ for (const key in targetObj) {
35
+ const isExtraKey = !Object.prototype.hasOwnProperty.call(sourceObj, key);
36
+ if (isExtraKey) {
37
+ delete targetObj[key];
38
+ stats.removed++;
39
+ stats.removedKeys.push(key);
40
+ }
41
+ else if (typeof sourceObj[key] === 'object' &&
42
+ sourceObj[key] !== null &&
43
+ !Array.isArray(sourceObj[key]) &&
44
+ typeof targetObj[key] === 'object' &&
45
+ targetObj[key] !== null &&
46
+ !Array.isArray(targetObj[key])) {
47
+ removeExtraKeys(sourceObj[key], targetObj[key], stats);
48
+ }
49
+ }
50
+ return stats;
51
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-google-translate",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "Google Translate integration for React Native apps with rate limiting, batch translation, and TypeScript support",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -16,10 +16,12 @@
16
16
  "./*": "./src/*/index.ts"
17
17
  },
18
18
  "scripts": {
19
- "setup": "node src/scripts/setup.ts",
20
- "translate": "node src/scripts/translate.ts",
21
- "sync": "node src/scripts/sync.ts",
22
- "i18n:setup": "node src/scripts/setup.ts",
19
+ "build:scripts": "tsc -p tsconfig.scripts.json",
20
+ "setup": "node dist/scripts/setup.js",
21
+ "translate": "node dist/scripts/translate.js",
22
+ "sync": "node dist/scripts/sync.js",
23
+ "i18n:setup": "node dist/scripts/setup.js",
24
+ "prepublishOnly": "npm run build:scripts",
23
25
  "typecheck": "tsc --noEmit",
24
26
  "lint": "echo 'Lint passed'",
25
27
  "version:patch": "npm version patch -m 'chore: release v%s'",
@@ -56,6 +58,7 @@
56
58
  },
57
59
  "files": [
58
60
  "src",
61
+ "dist",
59
62
  "README.md",
60
63
  "LICENSE"
61
64
  ]
@@ -51,8 +51,8 @@ export function setupLanguages(options: SetupLanguagesOptions): boolean {
51
51
  .filter(f => f.match(/^[a-z]{2}-[A-Z]{2}\.ts$/))
52
52
  .sort();
53
53
 
54
- const imports = [];
55
- const exports = [];
54
+ const imports: string[] = [];
55
+ const exports: string[] = [];
56
56
 
57
57
  files.forEach(file => {
58
58
  const code = file.replace('.ts', '');
@@ -90,6 +90,7 @@ export function runSetupLanguages(): void {
90
90
  setupLanguages({ targetDir });
91
91
  }
92
92
 
93
- if (import.meta.url === `file://${process.argv[1]}`) {
93
+ // Check if this file is being run directly
94
+ if (require.main === module || process.argv[1].endsWith('/setup.js') || process.argv[1].endsWith('\\setup.js')) {
94
95
  runSetupLanguages();
95
96
  }
@@ -148,6 +148,7 @@ export function runSyncTranslations(): void {
148
148
  syncTranslations({ targetDir, srcDir });
149
149
  }
150
150
 
151
- if (import.meta.url === `file://${process.argv[1]}`) {
151
+ // Check if this file is being run directly
152
+ if (require.main === module || process.argv[1].endsWith('/sync.js') || process.argv[1].endsWith('\\sync.js')) {
152
153
  runSyncTranslations();
153
154
  }
@@ -121,6 +121,7 @@ export function runTranslateMissing(): void {
121
121
  });
122
122
  }
123
123
 
124
- if (import.meta.url === `file://${process.argv[1]}`) {
124
+ // Check if this file is being run directly
125
+ if (require.main === module || process.argv[1].endsWith('/translate.js') || process.argv[1].endsWith('\\translate.js')) {
125
126
  runTranslateMissing();
126
127
  }