@umituz/react-native-localization 1.7.0 → 1.7.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/package.json +1 -1
- package/scripts/translate-missing.js +85 -13
package/package.json
CHANGED
|
@@ -81,8 +81,12 @@ const SKIP_WORDS = new Set([
|
|
|
81
81
|
/**
|
|
82
82
|
* Simple Google Translate API call using free endpoint
|
|
83
83
|
* Note: This uses Google's unofficial API. For production, use official API with key.
|
|
84
|
+
* Includes retry mechanism for rate limiting and HTML error responses.
|
|
84
85
|
*/
|
|
85
|
-
async function translateText(text, targetLang) {
|
|
86
|
+
async function translateText(text, targetLang, retryCount = 0) {
|
|
87
|
+
const MAX_RETRIES = 3;
|
|
88
|
+
const RETRY_DELAY = 1000; // 1 second
|
|
89
|
+
|
|
86
90
|
return new Promise((resolve, _reject) => {
|
|
87
91
|
if (SKIP_WORDS.has(text)) {
|
|
88
92
|
resolve(text);
|
|
@@ -99,28 +103,96 @@ async function translateText(text, targetLang) {
|
|
|
99
103
|
data += chunk;
|
|
100
104
|
});
|
|
101
105
|
res.on('end', () => {
|
|
106
|
+
// Check if response is HTML (error page)
|
|
107
|
+
if (data.trim().startsWith('<') || data.trim().startsWith('<!')) {
|
|
108
|
+
// HTML response - likely rate limit or error page
|
|
109
|
+
if (retryCount < MAX_RETRIES) {
|
|
110
|
+
if (options.verbose) {
|
|
111
|
+
console.warn(
|
|
112
|
+
` ⚠️ HTML response received for "${text}" to ${targetLang}, retrying... (${retryCount + 1}/${MAX_RETRIES})`
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
// Retry after delay
|
|
116
|
+
setTimeout(() => {
|
|
117
|
+
translateText(text, targetLang, retryCount + 1).then(resolve);
|
|
118
|
+
}, RETRY_DELAY * (retryCount + 1)); // Exponential backoff
|
|
119
|
+
return;
|
|
120
|
+
} else {
|
|
121
|
+
console.warn(
|
|
122
|
+
`⚠️ Translation failed for "${text}" to ${targetLang}: HTML response (rate limit or API error)`
|
|
123
|
+
);
|
|
124
|
+
resolve(text); // Fallback to original
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Check HTTP status code
|
|
130
|
+
if (res.statusCode !== 200) {
|
|
131
|
+
if (retryCount < MAX_RETRIES) {
|
|
132
|
+
if (options.verbose) {
|
|
133
|
+
console.warn(
|
|
134
|
+
` ⚠️ HTTP ${res.statusCode} for "${text}" to ${targetLang}, retrying... (${retryCount + 1}/${MAX_RETRIES})`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
setTimeout(() => {
|
|
138
|
+
translateText(text, targetLang, retryCount + 1).then(resolve);
|
|
139
|
+
}, RETRY_DELAY * (retryCount + 1));
|
|
140
|
+
return;
|
|
141
|
+
} else {
|
|
142
|
+
console.warn(
|
|
143
|
+
`⚠️ Translation failed for "${text}" to ${targetLang}: HTTP ${res.statusCode}`
|
|
144
|
+
);
|
|
145
|
+
resolve(text);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
102
150
|
try {
|
|
103
151
|
const parsed = JSON.parse(data);
|
|
152
|
+
if (!parsed || !parsed[0] || !Array.isArray(parsed[0])) {
|
|
153
|
+
throw new Error('Invalid response format');
|
|
154
|
+
}
|
|
104
155
|
const translated = parsed[0]
|
|
105
156
|
.map(item => item[0])
|
|
106
157
|
.join('')
|
|
107
158
|
.trim();
|
|
108
159
|
resolve(translated || text);
|
|
109
160
|
} catch (error) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
161
|
+
// JSON parse error - might be HTML or malformed response
|
|
162
|
+
if (retryCount < MAX_RETRIES) {
|
|
163
|
+
if (options.verbose) {
|
|
164
|
+
console.warn(
|
|
165
|
+
` ⚠️ Parse error for "${text}" to ${targetLang}, retrying... (${retryCount + 1}/${MAX_RETRIES}): ${error.message}`
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
setTimeout(() => {
|
|
169
|
+
translateText(text, targetLang, retryCount + 1).then(resolve);
|
|
170
|
+
}, RETRY_DELAY * (retryCount + 1));
|
|
171
|
+
} else {
|
|
172
|
+
console.warn(
|
|
173
|
+
`⚠️ Translation failed for "${text}" to ${targetLang}: ${error.message}`
|
|
174
|
+
);
|
|
175
|
+
resolve(text); // Fallback to original
|
|
176
|
+
}
|
|
115
177
|
}
|
|
116
178
|
});
|
|
117
179
|
})
|
|
118
180
|
.on('error', err => {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
181
|
+
if (retryCount < MAX_RETRIES) {
|
|
182
|
+
if (options.verbose) {
|
|
183
|
+
console.warn(
|
|
184
|
+
` ⚠️ Network error for "${text}" to ${targetLang}, retrying... (${retryCount + 1}/${MAX_RETRIES}): ${err.message}`
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
setTimeout(() => {
|
|
188
|
+
translateText(text, targetLang, retryCount + 1).then(resolve);
|
|
189
|
+
}, RETRY_DELAY * (retryCount + 1));
|
|
190
|
+
} else {
|
|
191
|
+
console.warn(
|
|
192
|
+
`⚠️ Network error translating "${text}" to ${targetLang}: ${err.message}`
|
|
193
|
+
);
|
|
194
|
+
resolve(text); // Fallback to original
|
|
195
|
+
}
|
|
124
196
|
});
|
|
125
197
|
});
|
|
126
198
|
}
|
|
@@ -276,8 +348,8 @@ async function translateObject(enObj, targetObj, targetLang, path = '') {
|
|
|
276
348
|
translatedCount++;
|
|
277
349
|
stats.translated++;
|
|
278
350
|
|
|
279
|
-
// Add delay to avoid rate limiting (
|
|
280
|
-
await delay(
|
|
351
|
+
// Add delay to avoid rate limiting (300ms between requests - increased for stability)
|
|
352
|
+
await delay(300);
|
|
281
353
|
} catch (error) {
|
|
282
354
|
console.error(` ❌ Failed to translate "${currentPath}":`, error.message);
|
|
283
355
|
stats.errors++;
|