@umituz/web-localization 1.0.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.
Files changed (42) hide show
  1. package/README.md +71 -0
  2. package/package.json +54 -0
  3. package/src/domain/entities/translation.entity.d.ts +30 -0
  4. package/src/domain/entities/translation.entity.d.ts.map +1 -0
  5. package/src/domain/entities/translation.entity.js +5 -0
  6. package/src/domain/entities/translation.entity.ts +33 -0
  7. package/src/domain/interfaces/translation-service.interface.d.ts +21 -0
  8. package/src/domain/interfaces/translation-service.interface.d.ts.map +1 -0
  9. package/src/domain/interfaces/translation-service.interface.js +1 -0
  10. package/src/domain/interfaces/translation-service.interface.ts +33 -0
  11. package/src/index.d.ts +11 -0
  12. package/src/index.d.ts.map +1 -0
  13. package/src/index.js +10 -0
  14. package/src/index.ts +11 -0
  15. package/src/infrastructure/constants/index.d.ts +11 -0
  16. package/src/infrastructure/constants/index.d.ts.map +1 -0
  17. package/src/infrastructure/constants/index.js +10 -0
  18. package/src/infrastructure/constants/index.ts +13 -0
  19. package/src/infrastructure/services/cli.service.d.ts +11 -0
  20. package/src/infrastructure/services/cli.service.d.ts.map +1 -0
  21. package/src/infrastructure/services/cli.service.js +95 -0
  22. package/src/infrastructure/services/cli.service.ts +129 -0
  23. package/src/infrastructure/services/google-translate.service.d.ts +20 -0
  24. package/src/infrastructure/services/google-translate.service.d.ts.map +1 -0
  25. package/src/infrastructure/services/google-translate.service.js +202 -0
  26. package/src/infrastructure/services/google-translate.service.ts +279 -0
  27. package/src/infrastructure/utils/file.util.d.ts +10 -0
  28. package/src/infrastructure/utils/file.util.d.ts.map +1 -0
  29. package/src/infrastructure/utils/file.util.js +41 -0
  30. package/src/infrastructure/utils/file.util.ts +46 -0
  31. package/src/infrastructure/utils/rate-limit.util.d.ts +11 -0
  32. package/src/infrastructure/utils/rate-limit.util.d.ts.map +1 -0
  33. package/src/infrastructure/utils/rate-limit.util.js +20 -0
  34. package/src/infrastructure/utils/rate-limit.util.ts +25 -0
  35. package/src/infrastructure/utils/text-validator.util.d.ts +16 -0
  36. package/src/infrastructure/utils/text-validator.util.d.ts.map +1 -0
  37. package/src/infrastructure/utils/text-validator.util.js +34 -0
  38. package/src/infrastructure/utils/text-validator.util.ts +31 -0
  39. package/src/scripts/cli.d.ts +6 -0
  40. package/src/scripts/cli.d.ts.map +1 -0
  41. package/src/scripts/cli.js +41 -0
  42. package/src/scripts/cli.ts +46 -0
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Google Translate Service
3
+ * @description Main translation service using Google Translate API
4
+ */
5
+ import { RateLimiter } from "../utils/rate-limit.util";
6
+ import { shouldSkipWord, needsTranslation, isValidText, } from "../utils/text-validator.util";
7
+ import { GOOGLE_TRANSLATE_API_URL, DEFAULT_MIN_DELAY, DEFAULT_TIMEOUT, } from "../constants";
8
+ class GoogleTranslateService {
9
+ config = null;
10
+ rateLimiter = null;
11
+ initialize(config) {
12
+ this.config = {
13
+ minDelay: DEFAULT_MIN_DELAY,
14
+ timeout: DEFAULT_TIMEOUT,
15
+ ...config,
16
+ };
17
+ this.rateLimiter = new RateLimiter(this.config.minDelay);
18
+ }
19
+ isInitialized() {
20
+ return this.config !== null && this.rateLimiter !== null;
21
+ }
22
+ ensureInitialized() {
23
+ if (!this.isInitialized()) {
24
+ throw new Error("GoogleTranslateService is not initialized. Call initialize() first.");
25
+ }
26
+ }
27
+ async translate(request) {
28
+ this.ensureInitialized();
29
+ const { text, targetLanguage, sourceLanguage = "en" } = request;
30
+ if (!isValidText(text) || shouldSkipWord(text)) {
31
+ return {
32
+ originalText: text,
33
+ translatedText: text,
34
+ sourceLanguage,
35
+ targetLanguage,
36
+ success: true,
37
+ };
38
+ }
39
+ if (!targetLanguage || targetLanguage.trim().length === 0) {
40
+ return {
41
+ originalText: text,
42
+ translatedText: text,
43
+ sourceLanguage,
44
+ targetLanguage,
45
+ success: false,
46
+ error: "Invalid target language",
47
+ };
48
+ }
49
+ await this.rateLimiter.waitForSlot();
50
+ try {
51
+ const translatedText = await this.callTranslateAPI(text, targetLanguage, sourceLanguage);
52
+ return {
53
+ originalText: text,
54
+ translatedText,
55
+ sourceLanguage,
56
+ targetLanguage,
57
+ success: true,
58
+ };
59
+ }
60
+ catch (error) {
61
+ return {
62
+ originalText: text,
63
+ translatedText: text,
64
+ sourceLanguage,
65
+ targetLanguage,
66
+ success: false,
67
+ error: error instanceof Error ? error.message : "Unknown error",
68
+ };
69
+ }
70
+ }
71
+ async translateBatch(requests) {
72
+ this.ensureInitialized();
73
+ const stats = {
74
+ totalCount: requests.length,
75
+ successCount: 0,
76
+ failureCount: 0,
77
+ skippedCount: 0,
78
+ translatedKeys: [],
79
+ };
80
+ if (!Array.isArray(requests) || requests.length === 0) {
81
+ return stats;
82
+ }
83
+ // Process requests concurrently with controlled parallelism
84
+ const concurrencyLimit = 10;
85
+ const chunks = [];
86
+ for (let i = 0; i < requests.length; i += concurrencyLimit) {
87
+ chunks.push(requests.slice(i, i + concurrencyLimit));
88
+ }
89
+ for (const chunk of chunks) {
90
+ const results = await Promise.all(chunk.map(async (request) => {
91
+ await this.rateLimiter.waitForSlot();
92
+ return this.callTranslateAPI(request.text, request.targetLanguage, request.sourceLanguage || "en");
93
+ }));
94
+ for (let i = 0; i < chunk.length; i++) {
95
+ const request = chunk[i];
96
+ const translatedText = results[i];
97
+ if (translatedText && translatedText !== request.text) {
98
+ stats.successCount++;
99
+ stats.translatedKeys.push({
100
+ key: request.text,
101
+ from: request.text,
102
+ to: translatedText,
103
+ });
104
+ }
105
+ else if (!translatedText) {
106
+ stats.failureCount++;
107
+ }
108
+ else {
109
+ stats.skippedCount++;
110
+ }
111
+ }
112
+ }
113
+ return stats;
114
+ }
115
+ async translateObject(sourceObject, targetObject, targetLanguage, path = "", stats = {
116
+ totalCount: 0,
117
+ successCount: 0,
118
+ failureCount: 0,
119
+ skippedCount: 0,
120
+ translatedKeys: [],
121
+ }, onTranslate) {
122
+ if (!sourceObject || typeof sourceObject !== "object")
123
+ return;
124
+ if (!targetObject || typeof targetObject !== "object")
125
+ return;
126
+ if (!targetLanguage || targetLanguage.trim().length === 0)
127
+ return;
128
+ const keys = Object.keys(sourceObject);
129
+ const textsToTranslate = [];
130
+ for (const key of keys) {
131
+ const enValue = sourceObject[key];
132
+ const targetValue = targetObject[key];
133
+ const currentPath = path ? `${path}.${key}` : key;
134
+ if (typeof enValue === "object" && enValue !== null) {
135
+ if (!targetObject[key] || typeof targetObject[key] !== "object") {
136
+ targetObject[key] = {};
137
+ }
138
+ await this.translateObject(enValue, targetObject[key], targetLanguage, currentPath, stats, onTranslate);
139
+ }
140
+ else if (typeof enValue === "string") {
141
+ stats.totalCount++;
142
+ if (needsTranslation(targetValue, enValue)) {
143
+ textsToTranslate.push({ key, enValue, currentPath });
144
+ }
145
+ else {
146
+ stats.skippedCount++;
147
+ }
148
+ }
149
+ }
150
+ if (textsToTranslate.length > 0) {
151
+ const batchSize = 50;
152
+ for (let i = 0; i < textsToTranslate.length; i += batchSize) {
153
+ const batch = textsToTranslate.slice(i, i + batchSize);
154
+ const results = await this.translateBatch(batch.map(item => ({
155
+ text: item.enValue,
156
+ targetLanguage,
157
+ })));
158
+ let resultIndex = 0;
159
+ for (let j = 0; j < batch.length; j++) {
160
+ const { key, enValue, currentPath } = batch[j];
161
+ const translatedItem = results.translatedKeys[resultIndex];
162
+ if (translatedItem && translatedItem.from === enValue && translatedItem.to !== enValue) {
163
+ targetObject[key] = translatedItem.to;
164
+ if (onTranslate)
165
+ onTranslate(currentPath, enValue, translatedItem.to);
166
+ resultIndex++;
167
+ }
168
+ }
169
+ }
170
+ }
171
+ }
172
+ async callTranslateAPI(text, targetLanguage, sourceLanguage) {
173
+ const timeout = this.config?.timeout || DEFAULT_TIMEOUT;
174
+ const encodedText = encodeURIComponent(text);
175
+ const url = `${GOOGLE_TRANSLATE_API_URL}?client=gtx&sl=${sourceLanguage}&tl=${targetLanguage}&dt=t&q=${encodedText}`;
176
+ const controller = new AbortController();
177
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
178
+ try {
179
+ const response = await fetch(url, {
180
+ signal: controller.signal,
181
+ });
182
+ if (!response.ok) {
183
+ throw new Error(`API request failed: ${response.status}`);
184
+ }
185
+ const data = await response.json();
186
+ if (Array.isArray(data) &&
187
+ data.length > 0 &&
188
+ Array.isArray(data[0]) &&
189
+ data[0].length > 0 &&
190
+ Array.isArray(data[0][0]) &&
191
+ typeof data[0][0][0] === "string") {
192
+ return data[0][0][0];
193
+ }
194
+ return text;
195
+ }
196
+ finally {
197
+ clearTimeout(timeoutId);
198
+ }
199
+ }
200
+ }
201
+ export const googleTranslateService = new GoogleTranslateService();
202
+ export { GoogleTranslateService };
@@ -0,0 +1,279 @@
1
+ /**
2
+ * Google Translate Service
3
+ * @description Main translation service using Google Translate API
4
+ */
5
+
6
+ import type {
7
+ TranslationRequest,
8
+ TranslationResponse,
9
+ TranslationStats,
10
+ } from "../../domain/entities/translation.entity";
11
+ import type {
12
+ ITranslationService,
13
+ TranslationServiceConfig,
14
+ } from "../../domain/interfaces/translation-service.interface";
15
+ import { RateLimiter } from "../utils/rate-limit.util";
16
+ import {
17
+ shouldSkipWord,
18
+ needsTranslation,
19
+ isValidText,
20
+ } from "../utils/text-validator.util";
21
+ import {
22
+ GOOGLE_TRANSLATE_API_URL,
23
+ DEFAULT_MIN_DELAY,
24
+ DEFAULT_TIMEOUT,
25
+ } from "../constants";
26
+
27
+ class GoogleTranslateService implements ITranslationService {
28
+ private config: TranslationServiceConfig | null = null;
29
+ private rateLimiter: RateLimiter | null = null;
30
+
31
+ initialize(config: TranslationServiceConfig): void {
32
+ this.config = {
33
+ minDelay: DEFAULT_MIN_DELAY,
34
+ timeout: DEFAULT_TIMEOUT,
35
+ ...config,
36
+ };
37
+ this.rateLimiter = new RateLimiter(this.config.minDelay);
38
+ }
39
+
40
+ isInitialized(): boolean {
41
+ return this.config !== null && this.rateLimiter !== null;
42
+ }
43
+
44
+ private ensureInitialized(): void {
45
+ if (!this.isInitialized()) {
46
+ throw new Error(
47
+ "GoogleTranslateService is not initialized. Call initialize() first."
48
+ );
49
+ }
50
+ }
51
+
52
+ async translate(request: TranslationRequest): Promise<TranslationResponse> {
53
+ this.ensureInitialized();
54
+
55
+ const { text, targetLanguage, sourceLanguage = "en" } = request;
56
+
57
+ if (!isValidText(text) || shouldSkipWord(text)) {
58
+ return {
59
+ originalText: text,
60
+ translatedText: text,
61
+ sourceLanguage,
62
+ targetLanguage,
63
+ success: true,
64
+ };
65
+ }
66
+
67
+ if (!targetLanguage || targetLanguage.trim().length === 0) {
68
+ return {
69
+ originalText: text,
70
+ translatedText: text,
71
+ sourceLanguage,
72
+ targetLanguage,
73
+ success: false,
74
+ error: "Invalid target language",
75
+ };
76
+ }
77
+
78
+ await this.rateLimiter!.waitForSlot();
79
+
80
+ try {
81
+ const translatedText = await this.callTranslateAPI(
82
+ text,
83
+ targetLanguage,
84
+ sourceLanguage
85
+ );
86
+
87
+ return {
88
+ originalText: text,
89
+ translatedText,
90
+ sourceLanguage,
91
+ targetLanguage,
92
+ success: true,
93
+ };
94
+ } catch (error) {
95
+ return {
96
+ originalText: text,
97
+ translatedText: text,
98
+ sourceLanguage,
99
+ targetLanguage,
100
+ success: false,
101
+ error: error instanceof Error ? error.message : "Unknown error",
102
+ };
103
+ }
104
+ }
105
+
106
+ async translateBatch(requests: TranslationRequest[]): Promise<TranslationStats> {
107
+ this.ensureInitialized();
108
+
109
+ const stats: TranslationStats = {
110
+ totalCount: requests.length,
111
+ successCount: 0,
112
+ failureCount: 0,
113
+ skippedCount: 0,
114
+ translatedKeys: [],
115
+ };
116
+
117
+ if (!Array.isArray(requests) || requests.length === 0) {
118
+ return stats;
119
+ }
120
+
121
+ // Process requests concurrently with controlled parallelism
122
+ const concurrencyLimit = 10;
123
+ const chunks: TranslationRequest[][] = [];
124
+
125
+ for (let i = 0; i < requests.length; i += concurrencyLimit) {
126
+ chunks.push(requests.slice(i, i + concurrencyLimit));
127
+ }
128
+
129
+ for (const chunk of chunks) {
130
+ const results = await Promise.all(
131
+ chunk.map(async (request) => {
132
+ await this.rateLimiter!.waitForSlot();
133
+ return this.callTranslateAPI(
134
+ request.text,
135
+ request.targetLanguage,
136
+ request.sourceLanguage || "en"
137
+ );
138
+ })
139
+ );
140
+
141
+ for (let i = 0; i < chunk.length; i++) {
142
+ const request = chunk[i];
143
+ const translatedText = results[i];
144
+
145
+ if (translatedText && translatedText !== request.text) {
146
+ stats.successCount++;
147
+ stats.translatedKeys.push({
148
+ key: request.text,
149
+ from: request.text,
150
+ to: translatedText,
151
+ });
152
+ } else if (!translatedText) {
153
+ stats.failureCount++;
154
+ } else {
155
+ stats.skippedCount++;
156
+ }
157
+ }
158
+ }
159
+
160
+ return stats;
161
+ }
162
+
163
+ async translateObject(
164
+ sourceObject: Record<string, unknown>,
165
+ targetObject: Record<string, unknown>,
166
+ targetLanguage: string,
167
+ path = "",
168
+ stats: TranslationStats = {
169
+ totalCount: 0,
170
+ successCount: 0,
171
+ failureCount: 0,
172
+ skippedCount: 0,
173
+ translatedKeys: [],
174
+ },
175
+ onTranslate?: (key: string, from: string, to: string) => void
176
+ ): Promise<void> {
177
+ if (!sourceObject || typeof sourceObject !== "object") return;
178
+ if (!targetObject || typeof targetObject !== "object") return;
179
+ if (!targetLanguage || targetLanguage.trim().length === 0) return;
180
+
181
+ const keys = Object.keys(sourceObject);
182
+ const textsToTranslate: Array<{key: string; enValue: string; currentPath: string}> = [];
183
+
184
+ for (const key of keys) {
185
+ const enValue = sourceObject[key];
186
+ const targetValue = targetObject[key];
187
+ const currentPath = path ? `${path}.${key}` : key;
188
+
189
+ if (typeof enValue === "object" && enValue !== null) {
190
+ if (!targetObject[key] || typeof targetObject[key] !== "object") {
191
+ targetObject[key] = {};
192
+ }
193
+ await this.translateObject(
194
+ enValue as Record<string, unknown>,
195
+ targetObject[key] as Record<string, unknown>,
196
+ targetLanguage,
197
+ currentPath,
198
+ stats,
199
+ onTranslate
200
+ );
201
+ } else if (typeof enValue === "string") {
202
+ stats.totalCount++;
203
+ if (needsTranslation(targetValue, enValue)) {
204
+ textsToTranslate.push({key, enValue, currentPath});
205
+ } else {
206
+ stats.skippedCount++;
207
+ }
208
+ }
209
+ }
210
+
211
+ if (textsToTranslate.length > 0) {
212
+ const batchSize = 50;
213
+ for (let i = 0; i < textsToTranslate.length; i += batchSize) {
214
+ const batch = textsToTranslate.slice(i, i + batchSize);
215
+ const results = await this.translateBatch(
216
+ batch.map(item => ({
217
+ text: item.enValue,
218
+ targetLanguage,
219
+ }))
220
+ );
221
+
222
+ let resultIndex = 0;
223
+ for (let j = 0; j < batch.length; j++) {
224
+ const {key, enValue, currentPath} = batch[j];
225
+ const translatedItem = results.translatedKeys[resultIndex];
226
+
227
+ if (translatedItem && translatedItem.from === enValue && translatedItem.to !== enValue) {
228
+ targetObject[key] = translatedItem.to;
229
+ if (onTranslate) onTranslate(currentPath, enValue, translatedItem.to);
230
+ resultIndex++;
231
+ }
232
+ }
233
+ }
234
+ }
235
+ }
236
+
237
+ private async callTranslateAPI(
238
+ text: string,
239
+ targetLanguage: string,
240
+ sourceLanguage: string
241
+ ): Promise<string> {
242
+ const timeout = this.config?.timeout || DEFAULT_TIMEOUT;
243
+ const encodedText = encodeURIComponent(text);
244
+ const url = `${GOOGLE_TRANSLATE_API_URL}?client=gtx&sl=${sourceLanguage}&tl=${targetLanguage}&dt=t&q=${encodedText}`;
245
+
246
+ const controller = new AbortController();
247
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
248
+
249
+ try {
250
+ const response = await fetch(url, {
251
+ signal: controller.signal,
252
+ });
253
+
254
+ if (!response.ok) {
255
+ throw new Error(`API request failed: ${response.status}`);
256
+ }
257
+
258
+ const data = await response.json();
259
+
260
+ if (
261
+ Array.isArray(data) &&
262
+ data.length > 0 &&
263
+ Array.isArray(data[0]) &&
264
+ data[0].length > 0 &&
265
+ Array.isArray(data[0][0]) &&
266
+ typeof data[0][0][0] === "string"
267
+ ) {
268
+ return data[0][0][0];
269
+ }
270
+
271
+ return text;
272
+ } finally {
273
+ clearTimeout(timeoutId);
274
+ }
275
+ }
276
+ }
277
+
278
+ export const googleTranslateService = new GoogleTranslateService();
279
+ export { GoogleTranslateService };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Parses a TypeScript file containing an object export
3
+ * @description Simplistic parser for 'export default { ... }' or 'export const data = { ... }'
4
+ */
5
+ export declare function parseTypeScriptFile(filePath: string): Record<string, unknown>;
6
+ /**
7
+ * Generates a TypeScript file content from an object
8
+ */
9
+ export declare function generateTypeScriptContent(obj: Record<string, unknown>, langCode?: string): string;
10
+ //# sourceMappingURL=file.util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.util.d.ts","sourceRoot":"","sources":["file.util.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoB7E;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAajG"}
@@ -0,0 +1,41 @@
1
+ import fs from "fs";
2
+ /**
3
+ * Parses a TypeScript file containing an object export
4
+ * @description Simplistic parser for 'export default { ... }' or 'export const data = { ... }'
5
+ */
6
+ export function parseTypeScriptFile(filePath) {
7
+ if (!fs.existsSync(filePath))
8
+ return {};
9
+ const content = fs.readFileSync(filePath, "utf-8");
10
+ // Extract the object part
11
+ // This is a naive implementation, but matches the pattern used in the project
12
+ const match = content.match(/export (default|const [^=]+ =) (\{[\s\S]*\});?\s*$/);
13
+ if (!match)
14
+ return {};
15
+ try {
16
+ // Evaluate the object string to a real JS object
17
+ // Using Function instead of eval for slightly better safety
18
+ const objStr = match[2];
19
+ const obj = new Function(`return ${objStr}`)();
20
+ return obj;
21
+ }
22
+ catch (err) {
23
+ console.error(`Error parsing ${filePath}:`, err);
24
+ return {};
25
+ }
26
+ }
27
+ /**
28
+ * Generates a TypeScript file content from an object
29
+ */
30
+ export function generateTypeScriptContent(obj, langCode) {
31
+ const jsonStr = JSON.stringify(obj, null, 2);
32
+ // Clean up keys (remove quotes if possible, though JSON.stringify adds them)
33
+ // For simplicity, we'll keep them as valid JS objects
34
+ return `/**
35
+ * Localization: ${langCode || "unknown"}
36
+ * Generated by @umituz/web-localization
37
+ */
38
+
39
+ export default ${jsonStr};
40
+ `;
41
+ }
@@ -0,0 +1,46 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+
4
+ /**
5
+ * Parses a TypeScript file containing an object export
6
+ * @description Simplistic parser for 'export default { ... }' or 'export const data = { ... }'
7
+ */
8
+ export function parseTypeScriptFile(filePath: string): Record<string, unknown> {
9
+ if (!fs.existsSync(filePath)) return {};
10
+
11
+ const content = fs.readFileSync(filePath, "utf-8");
12
+
13
+ // Extract the object part
14
+ // This is a naive implementation, but matches the pattern used in the project
15
+ const match = content.match(/export (default|const [^=]+ =) (\{[\s\S]*\});?\s*$/);
16
+ if (!match) return {};
17
+
18
+ try {
19
+ // Evaluate the object string to a real JS object
20
+ // Using Function instead of eval for slightly better safety
21
+ const objStr = match[2];
22
+ const obj = new Function(`return ${objStr}`)();
23
+ return obj;
24
+ } catch (err) {
25
+ console.error(`Error parsing ${filePath}:`, err);
26
+ return {};
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Generates a TypeScript file content from an object
32
+ */
33
+ export function generateTypeScriptContent(obj: Record<string, unknown>, langCode?: string): string {
34
+ const jsonStr = JSON.stringify(obj, null, 2);
35
+
36
+ // Clean up keys (remove quotes if possible, though JSON.stringify adds them)
37
+ // For simplicity, we'll keep them as valid JS objects
38
+
39
+ return `/**
40
+ * Localization: ${langCode || "unknown"}
41
+ * Generated by @umituz/web-localization
42
+ */
43
+
44
+ export default ${jsonStr};
45
+ `;
46
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Simple Rate Limiter
3
+ * @description Controls the frequency of API requests
4
+ */
5
+ export declare class RateLimiter {
6
+ private lastRequestTime;
7
+ private minDelay;
8
+ constructor(minDelay?: number);
9
+ waitForSlot(): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=rate-limit.util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.util.d.ts","sourceRoot":"","sources":["rate-limit.util.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,qBAAa,WAAW;IACtB,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,SAAM;IAIpB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;CAWnC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Simple Rate Limiter
3
+ * @description Controls the frequency of API requests
4
+ */
5
+ export class RateLimiter {
6
+ lastRequestTime = 0;
7
+ minDelay;
8
+ constructor(minDelay = 100) {
9
+ this.minDelay = minDelay;
10
+ }
11
+ async waitForSlot() {
12
+ const now = Date.now();
13
+ const elapsedTime = now - this.lastRequestTime;
14
+ if (elapsedTime < this.minDelay) {
15
+ const waitTime = this.minDelay - elapsedTime;
16
+ await new Promise(resolve => setTimeout(resolve, waitTime));
17
+ }
18
+ this.lastRequestTime = Date.now();
19
+ }
20
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Simple Rate Limiter
3
+ * @description Controls the frequency of API requests
4
+ */
5
+
6
+ export class RateLimiter {
7
+ private lastRequestTime = 0;
8
+ private minDelay: number;
9
+
10
+ constructor(minDelay = 100) {
11
+ this.minDelay = minDelay;
12
+ }
13
+
14
+ async waitForSlot(): Promise<void> {
15
+ const now = Date.now();
16
+ const elapsedTime = now - this.lastRequestTime;
17
+
18
+ if (elapsedTime < this.minDelay) {
19
+ const waitTime = this.minDelay - elapsedTime;
20
+ await new Promise(resolve => setTimeout(resolve, waitTime));
21
+ }
22
+
23
+ this.lastRequestTime = Date.now();
24
+ }
25
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Text Validation Utilities
3
+ */
4
+ /**
5
+ * Validates if the text is suitable for translation
6
+ */
7
+ export declare function isValidText(text: unknown): text is string;
8
+ /**
9
+ * Checks if a word should be skipped (e.g., proper nouns, symbols)
10
+ */
11
+ export declare function shouldSkipWord(text: string): boolean;
12
+ /**
13
+ * Determines if a key needs translation
14
+ */
15
+ export declare function needsTranslation(targetValue: unknown, sourceValue: string): boolean;
16
+ //# sourceMappingURL=text-validator.util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-validator.util.d.ts","sourceRoot":"","sources":["text-validator.util.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,MAAM,CAKzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGpD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAKnF"}