@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-localization",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "description": "Universal localization system for React Native apps with i18n support",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -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
- console.warn(
111
- `⚠️ Translation failed for "${text}" to ${targetLang}:`,
112
- error.message
113
- );
114
- resolve(text); // Fallback to original
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
- console.warn(
120
- `⚠️ Network error translating "${text}" to ${targetLang}:`,
121
- err.message
122
- );
123
- resolve(text); // Fallback to original
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 (200ms between requests)
280
- await delay(200);
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++;