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

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.
@@ -84,6 +84,8 @@ class GoogleTranslateService {
84
84
  translatedKeys: [],
85
85
  };
86
86
  }
87
+ // Use batch API call for better performance
88
+ const batchSize = 50;
87
89
  const stats = {
88
90
  totalCount: requests.length,
89
91
  successCount: 0,
@@ -91,23 +93,52 @@ class GoogleTranslateService {
91
93
  skippedCount: 0,
92
94
  translatedKeys: [],
93
95
  };
94
- for (const request of requests) {
95
- const result = await this.translate(request);
96
- if (result.success) {
97
- if (result.translatedText === result.originalText) {
98
- stats.skippedCount++;
99
- }
100
- else {
101
- stats.successCount++;
102
- stats.translatedKeys.push({
103
- key: request.text,
104
- from: result.originalText,
105
- to: result.translatedText,
106
- });
96
+ for (let i = 0; i < requests.length; i += batchSize) {
97
+ const batch = requests.slice(i, i + batchSize);
98
+ // Wait for rate limiter once per batch instead of once per request
99
+ await this.rateLimiter.waitForSlot();
100
+ try {
101
+ const translations = await this.callTranslateAPIBatch(batch, requests[0].targetLanguage);
102
+ for (let j = 0; j < batch.length; j++) {
103
+ const request = batch[j];
104
+ const translatedText = translations[j];
105
+ if (translatedText && translatedText !== request.text) {
106
+ stats.successCount++;
107
+ stats.translatedKeys.push({
108
+ key: request.text,
109
+ from: request.text,
110
+ to: translatedText,
111
+ });
112
+ }
113
+ else if (!translatedText) {
114
+ stats.failureCount++;
115
+ }
116
+ else {
117
+ stats.skippedCount++;
118
+ }
107
119
  }
108
120
  }
109
- else {
110
- stats.failureCount++;
121
+ catch (error) {
122
+ // Fallback to individual requests on batch failure
123
+ for (const request of batch) {
124
+ const result = await this.translate(request);
125
+ if (result.success) {
126
+ if (result.translatedText === result.originalText) {
127
+ stats.skippedCount++;
128
+ }
129
+ else {
130
+ stats.successCount++;
131
+ stats.translatedKeys.push({
132
+ key: request.text,
133
+ from: result.originalText,
134
+ to: result.translatedText,
135
+ });
136
+ }
137
+ }
138
+ else {
139
+ stats.failureCount++;
140
+ }
141
+ }
111
142
  }
112
143
  }
113
144
  return stats;
@@ -129,6 +160,8 @@ class GoogleTranslateService {
129
160
  return;
130
161
  }
131
162
  const keys = Object.keys(sourceObject);
163
+ // Collect all texts to translate first
164
+ const textsToTranslate = [];
132
165
  for (const key of keys) {
133
166
  const enValue = sourceObject[key];
134
167
  const targetValue = targetObject[key];
@@ -143,30 +176,42 @@ class GoogleTranslateService {
143
176
  else if (typeof enValue === "string") {
144
177
  stats.totalCount++;
145
178
  if ((0, textValidator_util_1.needsTranslation)(targetValue, enValue)) {
146
- const request = {
147
- text: enValue,
148
- targetLanguage,
149
- };
150
- const result = await this.translate(request);
151
- if (result.success && result.translatedText !== enValue) {
152
- targetObject[key] = result.translatedText;
179
+ textsToTranslate.push({ key, enValue, currentPath });
180
+ }
181
+ else {
182
+ stats.skippedCount++;
183
+ }
184
+ }
185
+ }
186
+ // Batch translate all texts at once
187
+ if (textsToTranslate.length > 0) {
188
+ const batchSize = 50; // Google Translate API can handle ~50 texts at once
189
+ for (let i = 0; i < textsToTranslate.length; i += batchSize) {
190
+ const batch = textsToTranslate.slice(i, i + batchSize);
191
+ const results = await this.translateBatch(batch.map(item => ({
192
+ text: item.enValue,
193
+ targetLanguage,
194
+ })));
195
+ // Apply translations
196
+ for (let j = 0; j < batch.length; j++) {
197
+ const { key, enValue, currentPath } = batch[j];
198
+ const translatedKey = results.translatedKeys[j];
199
+ if (translatedKey && translatedKey.from !== enValue) {
200
+ targetObject[key] = translatedKey.to;
153
201
  stats.successCount++;
154
202
  stats.translatedKeys.push({
155
203
  key: currentPath,
156
204
  from: enValue,
157
- to: result.translatedText,
205
+ to: translatedKey.to,
158
206
  });
159
207
  }
160
- else if (!result.success) {
208
+ else if (!translatedKey) {
161
209
  stats.failureCount++;
162
210
  }
163
211
  else {
164
212
  stats.skippedCount++;
165
213
  }
166
214
  }
167
- else {
168
- stats.skippedCount++;
169
- }
170
215
  }
171
216
  }
172
217
  }
@@ -199,5 +244,41 @@ class GoogleTranslateService {
199
244
  clearTimeout(timeoutId);
200
245
  }
201
246
  }
247
+ async callTranslateAPIBatch(requests, targetLanguage, sourceLanguage = "en") {
248
+ const timeout = this.config?.timeout || constants_1.DEFAULT_TIMEOUT;
249
+ // Build batch request URL
250
+ const queryParts = requests.map(req => encodeURIComponent(req.text)).join('&q=');
251
+ const url = `${constants_1.GOOGLE_TRANSLATE_API_URL}?client=gtx&sl=${sourceLanguage}&tl=${targetLanguage}&dt=t&q=${queryParts}`;
252
+ const controller = new AbortController();
253
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
254
+ try {
255
+ const response = await fetch(url, {
256
+ signal: controller.signal,
257
+ });
258
+ if (!response.ok) {
259
+ throw new Error(`Batch API request failed: ${response.status}`);
260
+ }
261
+ const data = await response.json();
262
+ // Extract translations from batch response
263
+ const translations = [];
264
+ if (Array.isArray(data) && data.length > 0) {
265
+ for (let i = 0; i < requests.length; i++) {
266
+ if (Array.isArray(data[i]) &&
267
+ data[i].length > 0 &&
268
+ Array.isArray(data[i][0]) &&
269
+ typeof data[i][0][0] === "string") {
270
+ translations.push(data[i][0][0]);
271
+ }
272
+ else {
273
+ translations.push(requests[i].text); // Fallback to original
274
+ }
275
+ }
276
+ }
277
+ return translations;
278
+ }
279
+ finally {
280
+ clearTimeout(timeoutId);
281
+ }
282
+ }
202
283
  }
203
284
  exports.googleTranslateService = new GoogleTranslateService();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-google-translate",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
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",
@@ -117,6 +117,8 @@ class GoogleTranslateService implements ITranslationService {
117
117
  };
118
118
  }
119
119
 
120
+ // Use batch API call for better performance
121
+ const batchSize = 50;
120
122
  const stats: TranslationStats = {
121
123
  totalCount: requests.length,
122
124
  successCount: 0,
@@ -125,22 +127,52 @@ class GoogleTranslateService implements ITranslationService {
125
127
  translatedKeys: [],
126
128
  };
127
129
 
128
- for (const request of requests) {
129
- const result = await this.translate(request);
130
+ for (let i = 0; i < requests.length; i += batchSize) {
131
+ const batch = requests.slice(i, i + batchSize);
130
132
 
131
- if (result.success) {
132
- if (result.translatedText === result.originalText) {
133
- stats.skippedCount++;
134
- } else {
135
- stats.successCount++;
136
- stats.translatedKeys.push({
137
- key: request.text,
138
- from: result.originalText,
139
- to: result.translatedText,
140
- });
133
+ // Wait for rate limiter once per batch instead of once per request
134
+ await this.rateLimiter!.waitForSlot();
135
+
136
+ try {
137
+ const translations = await this.callTranslateAPIBatch(batch, requests[0].targetLanguage);
138
+
139
+ for (let j = 0; j < batch.length; j++) {
140
+ const request = batch[j];
141
+ const translatedText = translations[j];
142
+
143
+ if (translatedText && translatedText !== request.text) {
144
+ stats.successCount++;
145
+ stats.translatedKeys.push({
146
+ key: request.text,
147
+ from: request.text,
148
+ to: translatedText,
149
+ });
150
+ } else if (!translatedText) {
151
+ stats.failureCount++;
152
+ } else {
153
+ stats.skippedCount++;
154
+ }
155
+ }
156
+ } catch (error) {
157
+ // Fallback to individual requests on batch failure
158
+ for (const request of batch) {
159
+ const result = await this.translate(request);
160
+
161
+ if (result.success) {
162
+ if (result.translatedText === result.originalText) {
163
+ stats.skippedCount++;
164
+ } else {
165
+ stats.successCount++;
166
+ stats.translatedKeys.push({
167
+ key: request.text,
168
+ from: result.originalText,
169
+ to: result.translatedText,
170
+ });
171
+ }
172
+ } else {
173
+ stats.failureCount++;
174
+ }
141
175
  }
142
- } else {
143
- stats.failureCount++;
144
176
  }
145
177
  }
146
178
 
@@ -174,6 +206,9 @@ class GoogleTranslateService implements ITranslationService {
174
206
 
175
207
  const keys = Object.keys(sourceObject);
176
208
 
209
+ // Collect all texts to translate first
210
+ const textsToTranslate: Array<{key: string; enValue: string; currentPath: string}> = [];
211
+
177
212
  for (const key of keys) {
178
213
  const enValue = sourceObject[key];
179
214
  const targetValue = targetObject[key];
@@ -197,28 +232,43 @@ class GoogleTranslateService implements ITranslationService {
197
232
  stats.totalCount++;
198
233
 
199
234
  if (needsTranslation(targetValue, enValue)) {
200
- const request: TranslationRequest = {
201
- text: enValue,
235
+ textsToTranslate.push({key, enValue, currentPath});
236
+ } else {
237
+ stats.skippedCount++;
238
+ }
239
+ }
240
+ }
241
+
242
+ // Batch translate all texts at once
243
+ if (textsToTranslate.length > 0) {
244
+ const batchSize = 50; // Google Translate API can handle ~50 texts at once
245
+ for (let i = 0; i < textsToTranslate.length; i += batchSize) {
246
+ const batch = textsToTranslate.slice(i, i + batchSize);
247
+ const results = await this.translateBatch(
248
+ batch.map(item => ({
249
+ text: item.enValue,
202
250
  targetLanguage,
203
- };
251
+ }))
252
+ );
204
253
 
205
- const result = await this.translate(request);
254
+ // Apply translations
255
+ for (let j = 0; j < batch.length; j++) {
256
+ const {key, enValue, currentPath} = batch[j];
257
+ const translatedKey = results.translatedKeys[j];
206
258
 
207
- if (result.success && result.translatedText !== enValue) {
208
- targetObject[key] = result.translatedText;
259
+ if (translatedKey && translatedKey.from !== enValue) {
260
+ targetObject[key] = translatedKey.to;
209
261
  stats.successCount++;
210
262
  stats.translatedKeys.push({
211
263
  key: currentPath,
212
264
  from: enValue,
213
- to: result.translatedText,
265
+ to: translatedKey.to,
214
266
  });
215
- } else if (!result.success) {
267
+ } else if (!translatedKey) {
216
268
  stats.failureCount++;
217
269
  } else {
218
270
  stats.skippedCount++;
219
271
  }
220
- } else {
221
- stats.skippedCount++;
222
272
  }
223
273
  }
224
274
  }
@@ -264,6 +314,55 @@ class GoogleTranslateService implements ITranslationService {
264
314
  clearTimeout(timeoutId);
265
315
  }
266
316
  }
317
+
318
+ private async callTranslateAPIBatch(
319
+ requests: TranslationRequest[],
320
+ targetLanguage: string,
321
+ sourceLanguage: string = "en"
322
+ ): Promise<string[]> {
323
+ const timeout = this.config?.timeout || DEFAULT_TIMEOUT;
324
+
325
+ // Build batch request URL
326
+ const queryParts = requests.map(req => encodeURIComponent(req.text)).join('&q=');
327
+ const url = `${GOOGLE_TRANSLATE_API_URL}?client=gtx&sl=${sourceLanguage}&tl=${targetLanguage}&dt=t&q=${queryParts}`;
328
+
329
+ const controller = new AbortController();
330
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
331
+
332
+ try {
333
+ const response = await fetch(url, {
334
+ signal: controller.signal,
335
+ });
336
+
337
+ if (!response.ok) {
338
+ throw new Error(`Batch API request failed: ${response.status}`);
339
+ }
340
+
341
+ const data = await response.json();
342
+
343
+ // Extract translations from batch response
344
+ const translations: string[] = [];
345
+
346
+ if (Array.isArray(data) && data.length > 0) {
347
+ for (let i = 0; i < requests.length; i++) {
348
+ if (
349
+ Array.isArray(data[i]) &&
350
+ data[i].length > 0 &&
351
+ Array.isArray(data[i][0]) &&
352
+ typeof data[i][0][0] === "string"
353
+ ) {
354
+ translations.push(data[i][0][0]);
355
+ } else {
356
+ translations.push(requests[i].text); // Fallback to original
357
+ }
358
+ }
359
+ }
360
+
361
+ return translations;
362
+ } finally {
363
+ clearTimeout(timeoutId);
364
+ }
365
+ }
267
366
  }
268
367
 
269
368
  export const googleTranslateService = new GoogleTranslateService();