@happyvertical/translator 0.80.0 → 0.80.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/dist/index.js CHANGED
@@ -1,252 +1,333 @@
1
1
  import { loadEnvConfig } from "@happyvertical/utils";
2
- class TranslationError extends Error {
3
- constructor(message, code, provider) {
4
- super(message);
5
- this.code = code;
6
- this.provider = provider;
7
- this.name = "TranslationError";
8
- }
9
- }
10
- class UnsupportedLanguageError extends TranslationError {
11
- constructor(language, provider) {
12
- super(
13
- `Unsupported language: ${language}`,
14
- "UNSUPPORTED_LANGUAGE",
15
- provider
16
- );
17
- this.name = "UnsupportedLanguageError";
18
- }
19
- }
20
- class QuotaExceededError extends TranslationError {
21
- constructor(provider) {
22
- super("Translation quota exceeded", "QUOTA_EXCEEDED", provider);
23
- this.name = "QuotaExceededError";
24
- }
25
- }
26
- class AuthenticationError extends TranslationError {
27
- constructor(provider) {
28
- super("Authentication failed", "AUTH_ERROR", provider);
29
- this.name = "AuthenticationError";
30
- }
31
- }
32
- class InvalidTextError extends TranslationError {
33
- constructor(reason, provider) {
34
- super(`Invalid text: ${reason}`, "INVALID_TEXT", provider);
35
- this.name = "InvalidTextError";
36
- }
37
- }
38
- const LANGUAGE_NAMES = {
39
- en: "English",
40
- es: "Spanish",
41
- fr: "French",
42
- de: "German",
43
- it: "Italian",
44
- pt: "Portuguese",
45
- ru: "Russian",
46
- ja: "Japanese",
47
- ko: "Korean",
48
- zh: "Chinese",
49
- ar: "Arabic",
50
- hi: "Hindi",
51
- nl: "Dutch",
52
- pl: "Polish",
53
- tr: "Turkish",
54
- sv: "Swedish",
55
- da: "Danish",
56
- no: "Norwegian",
57
- fi: "Finnish",
58
- cs: "Czech",
59
- el: "Greek",
60
- he: "Hebrew",
61
- th: "Thai",
62
- vi: "Vietnamese",
63
- id: "Indonesian",
64
- ro: "Romanian",
65
- uk: "Ukrainian",
66
- bg: "Bulgarian",
67
- hr: "Croatian",
68
- sk: "Slovak",
69
- sl: "Slovenian",
70
- lt: "Lithuanian",
71
- lv: "Latvian",
72
- et: "Estonian",
73
- hu: "Hungarian",
74
- ca: "Catalan",
75
- gl: "Galician",
76
- eu: "Basque",
77
- fa: "Persian",
78
- ur: "Urdu",
79
- bn: "Bengali",
80
- ta: "Tamil",
81
- te: "Telugu",
82
- mr: "Marathi",
83
- ml: "Malayalam",
84
- kn: "Kannada",
85
- gu: "Gujarati",
86
- pa: "Punjabi",
87
- sw: "Swahili",
88
- ms: "Malay",
89
- tl: "Tagalog",
90
- af: "Afrikaans",
91
- sq: "Albanian",
92
- am: "Amharic",
93
- hy: "Armenian",
94
- az: "Azerbaijani",
95
- be: "Belarusian",
96
- bs: "Bosnian",
97
- my: "Burmese",
98
- ceb: "Cebuano",
99
- ny: "Chichewa",
100
- co: "Corsican",
101
- eo: "Esperanto",
102
- fy: "Frisian",
103
- ka: "Georgian",
104
- haw: "Hawaiian",
105
- hmn: "Hmong",
106
- is: "Icelandic",
107
- ig: "Igbo",
108
- ga: "Irish",
109
- jw: "Javanese",
110
- kk: "Kazakh",
111
- km: "Khmer",
112
- ku: "Kurdish",
113
- ky: "Kyrgyz",
114
- lo: "Lao",
115
- la: "Latin",
116
- lb: "Luxembourgish",
117
- mk: "Macedonian",
118
- mg: "Malagasy",
119
- mt: "Maltese",
120
- mi: "Maori",
121
- mn: "Mongolian",
122
- ne: "Nepali",
123
- ps: "Pashto",
124
- sm: "Samoan",
125
- gd: "Scots Gaelic",
126
- sr: "Serbian",
127
- st: "Sesotho",
128
- sn: "Shona",
129
- sd: "Sindhi",
130
- si: "Sinhala",
131
- so: "Somali",
132
- su: "Sundanese",
133
- tg: "Tajik",
134
- tt: "Tatar",
135
- tk: "Turkmen",
136
- ug: "Uyghur",
137
- uz: "Uzbek",
138
- cy: "Welsh",
139
- xh: "Xhosa",
140
- yi: "Yiddish",
141
- yo: "Yoruba",
142
- zu: "Zulu"
2
+ //#region src/shared/types.ts
3
+ /**
4
+ * Base error class for translation operations
5
+ *
6
+ * @param message - Human-readable error description
7
+ * @param code - Machine-readable error code (e.g., 'QUOTA_EXCEEDED', 'AUTH_ERROR', 'TIMEOUT')
8
+ * @param provider - The provider that produced the error (e.g., 'google', 'deepl', 'libretranslate')
9
+ */
10
+ var TranslationError = class extends Error {
11
+ code;
12
+ provider;
13
+ constructor(message, code, provider) {
14
+ super(message);
15
+ this.code = code;
16
+ this.provider = provider;
17
+ this.name = "TranslationError";
18
+ }
19
+ };
20
+ /**
21
+ * Thrown when a requested language code is not supported by the provider
22
+ *
23
+ * @param language - The unsupported ISO 639-1 language code
24
+ * @param provider - The provider that rejected the language
25
+ */
26
+ var UnsupportedLanguageError = class extends TranslationError {
27
+ constructor(language, provider) {
28
+ super(`Unsupported language: ${language}`, "UNSUPPORTED_LANGUAGE", provider);
29
+ this.name = "UnsupportedLanguageError";
30
+ }
31
+ };
32
+ /**
33
+ * Thrown when the provider's translation quota or rate limit has been exceeded
34
+ *
35
+ * @param provider - The provider that reported the quota limit
36
+ */
37
+ var QuotaExceededError = class extends TranslationError {
38
+ constructor(provider) {
39
+ super("Translation quota exceeded", "QUOTA_EXCEEDED", provider);
40
+ this.name = "QuotaExceededError";
41
+ }
143
42
  };
43
+ /**
44
+ * Thrown when the provider rejects the API key or credentials
45
+ *
46
+ * @param provider - The provider that rejected authentication
47
+ */
48
+ var AuthenticationError = class extends TranslationError {
49
+ constructor(provider) {
50
+ super("Authentication failed", "AUTH_ERROR", provider);
51
+ this.name = "AuthenticationError";
52
+ }
53
+ };
54
+ /**
55
+ * Thrown when the input text is empty or otherwise invalid for translation
56
+ *
57
+ * @param reason - Description of why the text is invalid
58
+ * @param provider - The provider that rejected the text
59
+ */
60
+ var InvalidTextError = class extends TranslationError {
61
+ constructor(reason, provider) {
62
+ super(`Invalid text: ${reason}`, "INVALID_TEXT", provider);
63
+ this.name = "InvalidTextError";
64
+ }
65
+ };
66
+ //#endregion
67
+ //#region src/shared/utils.ts
68
+ /**
69
+ * Utility functions for translation operations
70
+ */
71
+ /**
72
+ * Common ISO 639-1 language codes and their names
73
+ */
74
+ var LANGUAGE_NAMES = {
75
+ en: "English",
76
+ es: "Spanish",
77
+ fr: "French",
78
+ de: "German",
79
+ it: "Italian",
80
+ pt: "Portuguese",
81
+ ru: "Russian",
82
+ ja: "Japanese",
83
+ ko: "Korean",
84
+ zh: "Chinese",
85
+ ar: "Arabic",
86
+ hi: "Hindi",
87
+ nl: "Dutch",
88
+ pl: "Polish",
89
+ tr: "Turkish",
90
+ sv: "Swedish",
91
+ da: "Danish",
92
+ no: "Norwegian",
93
+ fi: "Finnish",
94
+ cs: "Czech",
95
+ el: "Greek",
96
+ he: "Hebrew",
97
+ th: "Thai",
98
+ vi: "Vietnamese",
99
+ id: "Indonesian",
100
+ ro: "Romanian",
101
+ uk: "Ukrainian",
102
+ bg: "Bulgarian",
103
+ hr: "Croatian",
104
+ sk: "Slovak",
105
+ sl: "Slovenian",
106
+ lt: "Lithuanian",
107
+ lv: "Latvian",
108
+ et: "Estonian",
109
+ hu: "Hungarian",
110
+ ca: "Catalan",
111
+ gl: "Galician",
112
+ eu: "Basque",
113
+ fa: "Persian",
114
+ ur: "Urdu",
115
+ bn: "Bengali",
116
+ ta: "Tamil",
117
+ te: "Telugu",
118
+ mr: "Marathi",
119
+ ml: "Malayalam",
120
+ kn: "Kannada",
121
+ gu: "Gujarati",
122
+ pa: "Punjabi",
123
+ sw: "Swahili",
124
+ ms: "Malay",
125
+ tl: "Tagalog",
126
+ af: "Afrikaans",
127
+ sq: "Albanian",
128
+ am: "Amharic",
129
+ hy: "Armenian",
130
+ az: "Azerbaijani",
131
+ be: "Belarusian",
132
+ bs: "Bosnian",
133
+ my: "Burmese",
134
+ ceb: "Cebuano",
135
+ ny: "Chichewa",
136
+ co: "Corsican",
137
+ eo: "Esperanto",
138
+ fy: "Frisian",
139
+ ka: "Georgian",
140
+ haw: "Hawaiian",
141
+ hmn: "Hmong",
142
+ is: "Icelandic",
143
+ ig: "Igbo",
144
+ ga: "Irish",
145
+ jw: "Javanese",
146
+ kk: "Kazakh",
147
+ km: "Khmer",
148
+ ku: "Kurdish",
149
+ ky: "Kyrgyz",
150
+ lo: "Lao",
151
+ la: "Latin",
152
+ lb: "Luxembourgish",
153
+ mk: "Macedonian",
154
+ mg: "Malagasy",
155
+ mt: "Maltese",
156
+ mi: "Maori",
157
+ mn: "Mongolian",
158
+ ne: "Nepali",
159
+ ps: "Pashto",
160
+ sm: "Samoan",
161
+ gd: "Scots Gaelic",
162
+ sr: "Serbian",
163
+ st: "Sesotho",
164
+ sn: "Shona",
165
+ sd: "Sindhi",
166
+ si: "Sinhala",
167
+ so: "Somali",
168
+ su: "Sundanese",
169
+ tg: "Tajik",
170
+ tt: "Tatar",
171
+ tk: "Turkmen",
172
+ ug: "Uyghur",
173
+ uz: "Uzbek",
174
+ cy: "Welsh",
175
+ xh: "Xhosa",
176
+ yi: "Yiddish",
177
+ yo: "Yoruba",
178
+ zu: "Zulu"
179
+ };
180
+ /**
181
+ * Validates an ISO 639-1 language code
182
+ * @param code Language code to validate
183
+ * @returns True if valid
184
+ */
144
185
  function isValidLanguageCode(code) {
145
- return code.length === 2 && /^[a-z]{2}$/.test(code);
186
+ return code.length === 2 && /^[a-z]{2}$/.test(code);
146
187
  }
188
+ /**
189
+ * Gets the language name from a language code
190
+ * @param code ISO 639-1 language code
191
+ * @returns Language name or the code if not found
192
+ */
147
193
  function getLanguageName(code) {
148
- return LANGUAGE_NAMES[code] || code;
194
+ return LANGUAGE_NAMES[code] || code;
149
195
  }
196
+ /**
197
+ * Normalizes a confidence score to 0-1 range
198
+ * @param score Confidence score (may be 0-1 or 0-100)
199
+ * @returns Normalized score between 0 and 1
200
+ */
150
201
  function normalizeConfidence(score) {
151
- if (score > 1 && score <= 100) {
152
- return score / 100;
153
- }
154
- return Math.max(0, Math.min(1, score));
202
+ if (score > 1 && score <= 100) return score / 100;
203
+ return Math.max(0, Math.min(1, score));
155
204
  }
205
+ /**
206
+ * Validates that text is not empty
207
+ * @param text Text to validate
208
+ * @returns True if text is valid
209
+ */
156
210
  function isValidText(text) {
157
- return typeof text === "string" && text.trim().length > 0;
211
+ return typeof text === "string" && text.trim().length > 0;
158
212
  }
213
+ /**
214
+ * Truncates text to a maximum length
215
+ * @param text Text to truncate
216
+ * @param maxLength Maximum length
217
+ * @returns Truncated text
218
+ */
159
219
  function truncateText(text, maxLength) {
160
- if (text.length <= maxLength) {
161
- return text;
162
- }
163
- return `${text.substring(0, maxLength - 3)}...`;
164
- }
165
- class TranslatorWrapper {
166
- constructor(provider) {
167
- this.provider = provider;
168
- }
169
- async translate(text, targetLanguage, sourceLanguage) {
170
- return this.provider.translate(text, targetLanguage, sourceLanguage);
171
- }
172
- async detectLanguage(text) {
173
- return this.provider.detectLanguage(text);
174
- }
175
- async getSupportedLanguages() {
176
- return this.provider.getSupportedLanguages();
177
- }
178
- async translateBatch(texts, targetLanguage, sourceLanguage) {
179
- return this.provider.translateBatch(texts, targetLanguage, sourceLanguage);
180
- }
181
- /**
182
- * Creates a pre-configured translation function
183
- * This is the key ergonomic feature that makes repeated translations simple
184
- */
185
- templateFunction(sourceLanguage, targetLanguage = "en") {
186
- return async (text) => {
187
- const result = await this.provider.translate(
188
- text,
189
- targetLanguage,
190
- sourceLanguage
191
- );
192
- return result.translatedText;
193
- };
194
- }
220
+ if (text.length <= maxLength) return text;
221
+ return `${text.substring(0, maxLength - 3)}...`;
195
222
  }
223
+ //#endregion
224
+ //#region src/index.ts
225
+ /**
226
+ * Translator package entry point
227
+ * Provides standardized translation interface
228
+ */
229
+ /**
230
+ * Translator wrapper class that adds templateFunction to providers
231
+ */
232
+ var TranslatorWrapper = class {
233
+ provider;
234
+ constructor(provider) {
235
+ this.provider = provider;
236
+ }
237
+ async translate(text, targetLanguage, sourceLanguage) {
238
+ return this.provider.translate(text, targetLanguage, sourceLanguage);
239
+ }
240
+ async detectLanguage(text) {
241
+ return this.provider.detectLanguage(text);
242
+ }
243
+ async getSupportedLanguages() {
244
+ return this.provider.getSupportedLanguages();
245
+ }
246
+ async translateBatch(texts, targetLanguage, sourceLanguage) {
247
+ return this.provider.translateBatch(texts, targetLanguage, sourceLanguage);
248
+ }
249
+ /**
250
+ * Creates a pre-configured translation function
251
+ * This is the key ergonomic feature that makes repeated translations simple
252
+ */
253
+ templateFunction(sourceLanguage, targetLanguage = "en") {
254
+ return async (text) => {
255
+ return (await this.provider.translate(text, targetLanguage, sourceLanguage)).translatedText;
256
+ };
257
+ }
258
+ };
259
+ /**
260
+ * Factory function to create a translator instance
261
+ *
262
+ * Supports environment variable configuration using HAVE_TRANSLATOR_* pattern:
263
+ * - HAVE_TRANSLATOR_PROVIDER: Translation provider ('google'|'deepl'|'libretranslate')
264
+ *
265
+ * Provider-specific API keys are loaded from their respective environment variables:
266
+ * - GOOGLE_TRANSLATE_API_KEY: Google Translate API key
267
+ * - DEEPL_API_KEY: DeepL API key
268
+ *
269
+ * @param options - Configuration options for the translation provider (optional if using env vars)
270
+ * @returns Promise resolving to a translator that implements Translator
271
+ *
272
+ * @example
273
+ * ```typescript
274
+ * // Using explicit options
275
+ * const translator = await getTranslator({
276
+ * provider: 'google',
277
+ * apiKey: process.env.GOOGLE_TRANSLATE_API_KEY!
278
+ * });
279
+ *
280
+ * // Using environment variables
281
+ * // Set: HAVE_TRANSLATOR_PROVIDER=deepl
282
+ * // DEEPL_API_KEY=your_key_here
283
+ * const translator = await getTranslator();
284
+ *
285
+ * // Mix of env vars and explicit options (explicit takes precedence)
286
+ * // Set: HAVE_TRANSLATOR_PROVIDER=google
287
+ * const translator = await getTranslator({
288
+ * apiKey: 'explicit_key' // Overrides env var
289
+ * });
290
+ *
291
+ * // Use the translator
292
+ * const result = await translator.translate('Hello, world!', 'es');
293
+ *
294
+ * // Use template function for repeated translations
295
+ * const t = translator.templateFunction('en', 'es');
296
+ * const greeting = await t('Hello');
297
+ * const farewell = await t('Goodbye');
298
+ * ```
299
+ */
196
300
  async function getTranslator(options = {}) {
197
- const config = loadEnvConfig(
198
- options,
199
- {
200
- packageName: "translator",
201
- schema: {
202
- provider: "string",
203
- timeout: "number",
204
- maxRetries: "number"
205
- },
206
- allowUnknown: true
207
- }
208
- );
209
- if (!config.apiKey) {
210
- if (config.provider === "google" && process.env.GOOGLE_TRANSLATE_API_KEY) {
211
- config.apiKey = process.env.GOOGLE_TRANSLATE_API_KEY;
212
- } else if (config.provider === "deepl" && process.env.DEEPL_API_KEY) {
213
- config.apiKey = process.env.DEEPL_API_KEY;
214
- }
215
- }
216
- if (!config.provider) {
217
- throw new Error(
218
- "Translation provider not specified. Set HAVE_TRANSLATOR_PROVIDER environment variable or pass provider in options."
219
- );
220
- }
221
- let provider;
222
- if (config.provider === "google") {
223
- const { GoogleTranslateProvider } = await import("./chunks/google-KGGP9X0w.js");
224
- provider = new GoogleTranslateProvider(config);
225
- } else if (config.provider === "deepl") {
226
- const { DeepLProvider } = await import("./chunks/deepl-CWEP0MSh.js");
227
- provider = new DeepLProvider(config);
228
- } else if (config.provider === "libretranslate") {
229
- const { LibreTranslateProvider } = await import("./chunks/libretranslate-BeC38-0r.js");
230
- provider = new LibreTranslateProvider(config);
231
- } else {
232
- throw new Error(`Unsupported provider: ${config.provider}`);
233
- }
234
- return new TranslatorWrapper(provider);
301
+ const config = loadEnvConfig(options, {
302
+ packageName: "translator",
303
+ schema: {
304
+ provider: "string",
305
+ timeout: "number",
306
+ maxRetries: "number"
307
+ },
308
+ allowUnknown: true
309
+ });
310
+ if (!config.apiKey) {
311
+ if (config.provider === "google" && process.env.GOOGLE_TRANSLATE_API_KEY) config.apiKey = process.env.GOOGLE_TRANSLATE_API_KEY;
312
+ else if (config.provider === "deepl" && process.env.DEEPL_API_KEY) config.apiKey = process.env.DEEPL_API_KEY;
313
+ }
314
+ if (!config.provider) throw new Error("Translation provider not specified. Set HAVE_TRANSLATOR_PROVIDER environment variable or pass provider in options.");
315
+ let provider;
316
+ if (config.provider === "google") {
317
+ const { GoogleTranslateProvider } = await import("./chunks/google-jZMDn2Ru.js");
318
+ provider = new GoogleTranslateProvider(config);
319
+ } else if (config.provider === "deepl") {
320
+ const { DeepLProvider } = await import("./chunks/deepl-C9iR9zJ1.js");
321
+ provider = new DeepLProvider(config);
322
+ } else if (config.provider === "libretranslate") {
323
+ const { LibreTranslateProvider } = await import("./chunks/libretranslate-oJr-l5MM.js");
324
+ provider = new LibreTranslateProvider(config);
325
+ } else throw new Error(`Unsupported provider: ${config.provider}`);
326
+ return new TranslatorWrapper(provider);
235
327
  }
236
- const PACKAGE_VERSION_INITIALIZED = true;
237
- export {
238
- AuthenticationError,
239
- InvalidTextError,
240
- LANGUAGE_NAMES,
241
- PACKAGE_VERSION_INITIALIZED,
242
- QuotaExceededError,
243
- TranslationError,
244
- UnsupportedLanguageError,
245
- getLanguageName,
246
- getTranslator,
247
- isValidLanguageCode,
248
- isValidText,
249
- normalizeConfidence,
250
- truncateText
251
- };
252
- //# sourceMappingURL=index.js.map
328
+ /** @internal */
329
+ var PACKAGE_VERSION_INITIALIZED = true;
330
+ //#endregion
331
+ export { AuthenticationError, InvalidTextError, LANGUAGE_NAMES, PACKAGE_VERSION_INITIALIZED, QuotaExceededError, TranslationError, UnsupportedLanguageError, getLanguageName, getTranslator, isValidLanguageCode, isValidText, normalizeConfidence, truncateText };
332
+
333
+ //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/shared/types.ts","../src/shared/utils.ts","../src/index.ts"],"sourcesContent":["/**\n * Core types and interfaces for the Translator library\n */\n\n/**\n * Standardized translation result\n */\nexport interface TranslationResult {\n /**\n * The translated text\n */\n translatedText: string;\n\n /**\n * The original source text\n */\n sourceText: string;\n\n /**\n * The detected or specified source language (ISO 639-1 code)\n */\n sourceLanguage: string;\n\n /**\n * The target language (ISO 639-1 code)\n */\n targetLanguage: string;\n\n /**\n * Confidence score for the translation (0-1), if available\n */\n confidence?: number;\n\n /**\n * Alternative translations, if available\n */\n alternatives?: string[];\n\n /**\n * Whether the source language was automatically detected\n */\n detectedSourceLanguage: boolean;\n\n /**\n * The original, raw response from the provider\n */\n raw: any;\n}\n\n/**\n * Language detection result\n */\nexport interface LanguageDetectionResult {\n /**\n * The detected language (ISO 639-1 code)\n */\n language: string;\n\n /**\n * Confidence score for the detection (0-1)\n */\n confidence: number;\n\n /**\n * Alternative detected languages with confidence scores, if available\n */\n alternatives?: Array<{\n language: string;\n confidence: number;\n }>;\n\n /**\n * The original, raw response from the provider\n */\n raw: any;\n}\n\n/**\n * Supported language information\n */\nexport interface SupportedLanguage {\n /**\n * ISO 639-1 language code (e.g., 'en', 'es', 'fr')\n */\n code: string;\n\n /**\n * Human-readable language name in English\n */\n name: string;\n\n /**\n * Native name of the language (optional)\n */\n nativeName?: string;\n}\n\n/**\n * Translation provider interface - all providers must implement this\n */\nexport interface TranslationProvider {\n /**\n * Translates text from source language to target language\n * @param text The text to translate\n * @param targetLanguage The target language code (ISO 639-1)\n * @param sourceLanguage Optional source language code. If not provided, auto-detect\n * @returns A promise that resolves to a TranslationResult object\n */\n translate(\n text: string,\n targetLanguage: string,\n sourceLanguage?: string,\n ): Promise<TranslationResult>;\n\n /**\n * Detects the language of the provided text\n * @param text The text to analyze\n * @returns A promise that resolves to a LanguageDetectionResult object\n */\n detectLanguage(text: string): Promise<LanguageDetectionResult>;\n\n /**\n * Gets the list of languages supported by this provider\n * @returns A promise that resolves to an array of SupportedLanguage objects\n */\n getSupportedLanguages(): Promise<SupportedLanguage[]>;\n\n /**\n * Translates multiple texts in a single batch operation\n * @param texts Array of texts to translate\n * @param targetLanguage The target language code (ISO 639-1)\n * @param sourceLanguage Optional source language code. If not provided, auto-detect\n * @returns A promise that resolves to an array of TranslationResult objects\n */\n translateBatch(\n texts: string[],\n targetLanguage: string,\n sourceLanguage?: string,\n ): Promise<TranslationResult[]>;\n}\n\n/**\n * Translator interface - extends provider interface with convenience methods\n */\nexport interface Translator extends TranslationProvider {\n /**\n * Creates a pre-configured translation function for repeated translations\n * @param sourceLanguage Optional source language code (ISO 639-1). If undefined, auto-detects\n * @param targetLanguage Optional target language code (ISO 639-1). Defaults to 'en'\n * @returns A function that translates text with the pre-configured languages\n */\n templateFunction(\n sourceLanguage?: string,\n targetLanguage?: string,\n ): (text: string) => Promise<string>;\n}\n\n/**\n * Base configuration options for all providers\n */\nexport interface BaseTranslatorOptions {\n /**\n * Request timeout in milliseconds\n */\n timeout?: number;\n\n /**\n * Maximum number of retries for failed requests\n */\n maxRetries?: number;\n}\n\n/**\n * Google Translate provider options\n */\nexport interface GoogleTranslateOptions extends BaseTranslatorOptions {\n provider: 'google';\n /**\n * Google Cloud API key or credentials\n */\n apiKey: string;\n /**\n * Optional Google Cloud project ID\n */\n projectId?: string;\n}\n\n/**\n * DeepL provider options\n */\nexport interface DeepLOptions extends BaseTranslatorOptions {\n provider: 'deepl';\n /**\n * DeepL API key\n */\n apiKey: string;\n /**\n * Whether to use free or pro API endpoint (default: false = pro)\n */\n freeApi?: boolean;\n}\n\n/**\n * LibreTranslate provider options\n */\nexport interface LibreTranslateOptions extends BaseTranslatorOptions {\n provider: 'libretranslate';\n /**\n * Custom instance URL (default: https://libretranslate.com)\n */\n apiUrl?: string;\n /**\n * Optional API key for some instances\n */\n apiKey?: string;\n}\n\n/**\n * Union type for all provider options\n */\nexport type TranslatorOptions =\n | GoogleTranslateOptions\n | DeepLOptions\n | LibreTranslateOptions;\n\n/**\n * Base error class for translation operations\n *\n * @param message - Human-readable error description\n * @param code - Machine-readable error code (e.g., 'QUOTA_EXCEEDED', 'AUTH_ERROR', 'TIMEOUT')\n * @param provider - The provider that produced the error (e.g., 'google', 'deepl', 'libretranslate')\n */\nexport class TranslationError extends Error {\n constructor(\n message: string,\n public code: string,\n public provider?: string,\n ) {\n super(message);\n this.name = 'TranslationError';\n }\n}\n\n/**\n * Thrown when a requested language code is not supported by the provider\n *\n * @param language - The unsupported ISO 639-1 language code\n * @param provider - The provider that rejected the language\n */\nexport class UnsupportedLanguageError extends TranslationError {\n constructor(language: string, provider?: string) {\n super(\n `Unsupported language: ${language}`,\n 'UNSUPPORTED_LANGUAGE',\n provider,\n );\n this.name = 'UnsupportedLanguageError';\n }\n}\n\n/**\n * Thrown when the provider's translation quota or rate limit has been exceeded\n *\n * @param provider - The provider that reported the quota limit\n */\nexport class QuotaExceededError extends TranslationError {\n constructor(provider?: string) {\n super('Translation quota exceeded', 'QUOTA_EXCEEDED', provider);\n this.name = 'QuotaExceededError';\n }\n}\n\n/**\n * Thrown when the provider rejects the API key or credentials\n *\n * @param provider - The provider that rejected authentication\n */\nexport class AuthenticationError extends TranslationError {\n constructor(provider?: string) {\n super('Authentication failed', 'AUTH_ERROR', provider);\n this.name = 'AuthenticationError';\n }\n}\n\n/**\n * Thrown when the input text is empty or otherwise invalid for translation\n *\n * @param reason - Description of why the text is invalid\n * @param provider - The provider that rejected the text\n */\nexport class InvalidTextError extends TranslationError {\n constructor(reason: string, provider?: string) {\n super(`Invalid text: ${reason}`, 'INVALID_TEXT', provider);\n this.name = 'InvalidTextError';\n }\n}\n","/**\n * Utility functions for translation operations\n */\n\n/**\n * Common ISO 639-1 language codes and their names\n */\nexport const LANGUAGE_NAMES: Record<string, string> = {\n en: 'English',\n es: 'Spanish',\n fr: 'French',\n de: 'German',\n it: 'Italian',\n pt: 'Portuguese',\n ru: 'Russian',\n ja: 'Japanese',\n ko: 'Korean',\n zh: 'Chinese',\n ar: 'Arabic',\n hi: 'Hindi',\n nl: 'Dutch',\n pl: 'Polish',\n tr: 'Turkish',\n sv: 'Swedish',\n da: 'Danish',\n no: 'Norwegian',\n fi: 'Finnish',\n cs: 'Czech',\n el: 'Greek',\n he: 'Hebrew',\n th: 'Thai',\n vi: 'Vietnamese',\n id: 'Indonesian',\n ro: 'Romanian',\n uk: 'Ukrainian',\n bg: 'Bulgarian',\n hr: 'Croatian',\n sk: 'Slovak',\n sl: 'Slovenian',\n lt: 'Lithuanian',\n lv: 'Latvian',\n et: 'Estonian',\n hu: 'Hungarian',\n ca: 'Catalan',\n gl: 'Galician',\n eu: 'Basque',\n fa: 'Persian',\n ur: 'Urdu',\n bn: 'Bengali',\n ta: 'Tamil',\n te: 'Telugu',\n mr: 'Marathi',\n ml: 'Malayalam',\n kn: 'Kannada',\n gu: 'Gujarati',\n pa: 'Punjabi',\n sw: 'Swahili',\n ms: 'Malay',\n tl: 'Tagalog',\n af: 'Afrikaans',\n sq: 'Albanian',\n am: 'Amharic',\n hy: 'Armenian',\n az: 'Azerbaijani',\n be: 'Belarusian',\n bs: 'Bosnian',\n my: 'Burmese',\n ceb: 'Cebuano',\n ny: 'Chichewa',\n co: 'Corsican',\n eo: 'Esperanto',\n fy: 'Frisian',\n ka: 'Georgian',\n haw: 'Hawaiian',\n hmn: 'Hmong',\n is: 'Icelandic',\n ig: 'Igbo',\n ga: 'Irish',\n jw: 'Javanese',\n kk: 'Kazakh',\n km: 'Khmer',\n ku: 'Kurdish',\n ky: 'Kyrgyz',\n lo: 'Lao',\n la: 'Latin',\n lb: 'Luxembourgish',\n mk: 'Macedonian',\n mg: 'Malagasy',\n mt: 'Maltese',\n mi: 'Maori',\n mn: 'Mongolian',\n ne: 'Nepali',\n ps: 'Pashto',\n sm: 'Samoan',\n gd: 'Scots Gaelic',\n sr: 'Serbian',\n st: 'Sesotho',\n sn: 'Shona',\n sd: 'Sindhi',\n si: 'Sinhala',\n so: 'Somali',\n su: 'Sundanese',\n tg: 'Tajik',\n tt: 'Tatar',\n tk: 'Turkmen',\n ug: 'Uyghur',\n uz: 'Uzbek',\n cy: 'Welsh',\n xh: 'Xhosa',\n yi: 'Yiddish',\n yo: 'Yoruba',\n zu: 'Zulu',\n};\n\n/**\n * Validates an ISO 639-1 language code\n * @param code Language code to validate\n * @returns True if valid\n */\nexport function isValidLanguageCode(code: string): boolean {\n return code.length === 2 && /^[a-z]{2}$/.test(code);\n}\n\n/**\n * Gets the language name from a language code\n * @param code ISO 639-1 language code\n * @returns Language name or the code if not found\n */\nexport function getLanguageName(code: string): string {\n return LANGUAGE_NAMES[code] || code;\n}\n\n/**\n * Normalizes a confidence score to 0-1 range\n * @param score Confidence score (may be 0-1 or 0-100)\n * @returns Normalized score between 0 and 1\n */\nexport function normalizeConfidence(score: number): number {\n if (score > 1 && score <= 100) {\n return score / 100;\n }\n return Math.max(0, Math.min(1, score));\n}\n\n/**\n * Validates that text is not empty\n * @param text Text to validate\n * @returns True if text is valid\n */\nexport function isValidText(text: string): boolean {\n return typeof text === 'string' && text.trim().length > 0;\n}\n\n/**\n * Truncates text to a maximum length\n * @param text Text to truncate\n * @param maxLength Maximum length\n * @returns Truncated text\n */\nexport function truncateText(text: string, maxLength: number): string {\n if (text.length <= maxLength) {\n return text;\n }\n return `${text.substring(0, maxLength - 3)}...`;\n}\n","/**\n * Translator package entry point\n * Provides standardized translation interface\n */\n\nimport { loadEnvConfig } from '@happyvertical/utils';\nimport type {\n DeepLOptions,\n GoogleTranslateOptions,\n LanguageDetectionResult,\n LibreTranslateOptions,\n SupportedLanguage,\n TranslationProvider,\n TranslationResult,\n Translator,\n TranslatorOptions,\n} from './shared/types';\n\n// Export all types\nexport * from './shared/types';\nexport * from './shared/utils';\n\n/**\n * Type guard for Google Translate options\n */\nfunction _isGoogleTranslateOptions(\n options: TranslatorOptions,\n): options is GoogleTranslateOptions {\n return options.provider === 'google';\n}\n\n/**\n * Type guard for DeepL options\n */\nfunction _isDeepLOptions(options: TranslatorOptions): options is DeepLOptions {\n return options.provider === 'deepl';\n}\n\n/**\n * Type guard for LibreTranslate options\n */\nfunction _isLibreTranslateOptions(\n options: TranslatorOptions,\n): options is LibreTranslateOptions {\n return options.provider === 'libretranslate';\n}\n\n/**\n * Translator wrapper class that adds templateFunction to providers\n */\nclass TranslatorWrapper implements Translator {\n constructor(private provider: TranslationProvider) {}\n\n async translate(\n text: string,\n targetLanguage: string,\n sourceLanguage?: string,\n ): Promise<TranslationResult> {\n return this.provider.translate(text, targetLanguage, sourceLanguage);\n }\n\n async detectLanguage(text: string): Promise<LanguageDetectionResult> {\n return this.provider.detectLanguage(text);\n }\n\n async getSupportedLanguages(): Promise<SupportedLanguage[]> {\n return this.provider.getSupportedLanguages();\n }\n\n async translateBatch(\n texts: string[],\n targetLanguage: string,\n sourceLanguage?: string,\n ): Promise<TranslationResult[]> {\n return this.provider.translateBatch(texts, targetLanguage, sourceLanguage);\n }\n\n /**\n * Creates a pre-configured translation function\n * This is the key ergonomic feature that makes repeated translations simple\n */\n templateFunction(\n sourceLanguage?: string,\n targetLanguage: string = 'en',\n ): (text: string) => Promise<string> {\n return async (text: string): Promise<string> => {\n const result = await this.provider.translate(\n text,\n targetLanguage,\n sourceLanguage,\n );\n return result.translatedText;\n };\n }\n}\n\n/**\n * Factory function to create a translator instance\n *\n * Supports environment variable configuration using HAVE_TRANSLATOR_* pattern:\n * - HAVE_TRANSLATOR_PROVIDER: Translation provider ('google'|'deepl'|'libretranslate')\n *\n * Provider-specific API keys are loaded from their respective environment variables:\n * - GOOGLE_TRANSLATE_API_KEY: Google Translate API key\n * - DEEPL_API_KEY: DeepL API key\n *\n * @param options - Configuration options for the translation provider (optional if using env vars)\n * @returns Promise resolving to a translator that implements Translator\n *\n * @example\n * ```typescript\n * // Using explicit options\n * const translator = await getTranslator({\n * provider: 'google',\n * apiKey: process.env.GOOGLE_TRANSLATE_API_KEY!\n * });\n *\n * // Using environment variables\n * // Set: HAVE_TRANSLATOR_PROVIDER=deepl\n * // DEEPL_API_KEY=your_key_here\n * const translator = await getTranslator();\n *\n * // Mix of env vars and explicit options (explicit takes precedence)\n * // Set: HAVE_TRANSLATOR_PROVIDER=google\n * const translator = await getTranslator({\n * apiKey: 'explicit_key' // Overrides env var\n * });\n *\n * // Use the translator\n * const result = await translator.translate('Hello, world!', 'es');\n *\n * // Use template function for repeated translations\n * const t = translator.templateFunction('en', 'es');\n * const greeting = await t('Hello');\n * const farewell = await t('Goodbye');\n * ```\n */\nexport async function getTranslator(\n options: Partial<TranslatorOptions> = {},\n): Promise<Translator> {\n // Load configuration from environment variables with user options taking precedence\n const config: Record<string, any> = loadEnvConfig(\n options as Record<string, any>,\n {\n packageName: 'translator',\n schema: {\n provider: 'string',\n timeout: 'number',\n maxRetries: 'number',\n },\n allowUnknown: true,\n },\n );\n\n // Load provider-specific API keys from their respective env vars\n // This maintains backward compatibility with existing env var patterns\n if (!config.apiKey) {\n if (config.provider === 'google' && process.env.GOOGLE_TRANSLATE_API_KEY) {\n config.apiKey = process.env.GOOGLE_TRANSLATE_API_KEY;\n } else if (config.provider === 'deepl' && process.env.DEEPL_API_KEY) {\n config.apiKey = process.env.DEEPL_API_KEY;\n }\n }\n\n // Validate provider is set\n if (!config.provider) {\n throw new Error(\n 'Translation provider not specified. Set HAVE_TRANSLATOR_PROVIDER environment variable or pass provider in options.',\n );\n }\n\n let provider: TranslationProvider;\n\n if (config.provider === 'google') {\n const { GoogleTranslateProvider } = await import('./providers/google.js');\n provider = new GoogleTranslateProvider(config as GoogleTranslateOptions);\n } else if (config.provider === 'deepl') {\n const { DeepLProvider } = await import('./providers/deepl.js');\n provider = new DeepLProvider(config as DeepLOptions);\n } else if (config.provider === 'libretranslate') {\n const { LibreTranslateProvider } = await import(\n './providers/libretranslate.js'\n );\n provider = new LibreTranslateProvider(config as LibreTranslateOptions);\n } else {\n throw new Error(`Unsupported provider: ${config.provider}`);\n }\n\n return new TranslatorWrapper(provider);\n}\n\n/** @internal */\nexport const PACKAGE_VERSION_INITIALIZED = true;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/shared/types.ts","../src/shared/utils.ts","../src/index.ts"],"sourcesContent":["/**\n * Core types and interfaces for the Translator library\n */\n\n/**\n * Standardized translation result\n */\nexport interface TranslationResult {\n /**\n * The translated text\n */\n translatedText: string;\n\n /**\n * The original source text\n */\n sourceText: string;\n\n /**\n * The detected or specified source language (ISO 639-1 code)\n */\n sourceLanguage: string;\n\n /**\n * The target language (ISO 639-1 code)\n */\n targetLanguage: string;\n\n /**\n * Confidence score for the translation (0-1), if available\n */\n confidence?: number;\n\n /**\n * Alternative translations, if available\n */\n alternatives?: string[];\n\n /**\n * Whether the source language was automatically detected\n */\n detectedSourceLanguage: boolean;\n\n /**\n * The original, raw response from the provider\n */\n raw: any;\n}\n\n/**\n * Language detection result\n */\nexport interface LanguageDetectionResult {\n /**\n * The detected language (ISO 639-1 code)\n */\n language: string;\n\n /**\n * Confidence score for the detection (0-1)\n */\n confidence: number;\n\n /**\n * Alternative detected languages with confidence scores, if available\n */\n alternatives?: Array<{\n language: string;\n confidence: number;\n }>;\n\n /**\n * The original, raw response from the provider\n */\n raw: any;\n}\n\n/**\n * Supported language information\n */\nexport interface SupportedLanguage {\n /**\n * ISO 639-1 language code (e.g., 'en', 'es', 'fr')\n */\n code: string;\n\n /**\n * Human-readable language name in English\n */\n name: string;\n\n /**\n * Native name of the language (optional)\n */\n nativeName?: string;\n}\n\n/**\n * Translation provider interface - all providers must implement this\n */\nexport interface TranslationProvider {\n /**\n * Translates text from source language to target language\n * @param text The text to translate\n * @param targetLanguage The target language code (ISO 639-1)\n * @param sourceLanguage Optional source language code. If not provided, auto-detect\n * @returns A promise that resolves to a TranslationResult object\n */\n translate(\n text: string,\n targetLanguage: string,\n sourceLanguage?: string,\n ): Promise<TranslationResult>;\n\n /**\n * Detects the language of the provided text\n * @param text The text to analyze\n * @returns A promise that resolves to a LanguageDetectionResult object\n */\n detectLanguage(text: string): Promise<LanguageDetectionResult>;\n\n /**\n * Gets the list of languages supported by this provider\n * @returns A promise that resolves to an array of SupportedLanguage objects\n */\n getSupportedLanguages(): Promise<SupportedLanguage[]>;\n\n /**\n * Translates multiple texts in a single batch operation\n * @param texts Array of texts to translate\n * @param targetLanguage The target language code (ISO 639-1)\n * @param sourceLanguage Optional source language code. If not provided, auto-detect\n * @returns A promise that resolves to an array of TranslationResult objects\n */\n translateBatch(\n texts: string[],\n targetLanguage: string,\n sourceLanguage?: string,\n ): Promise<TranslationResult[]>;\n}\n\n/**\n * Translator interface - extends provider interface with convenience methods\n */\nexport interface Translator extends TranslationProvider {\n /**\n * Creates a pre-configured translation function for repeated translations\n * @param sourceLanguage Optional source language code (ISO 639-1). If undefined, auto-detects\n * @param targetLanguage Optional target language code (ISO 639-1). Defaults to 'en'\n * @returns A function that translates text with the pre-configured languages\n */\n templateFunction(\n sourceLanguage?: string,\n targetLanguage?: string,\n ): (text: string) => Promise<string>;\n}\n\n/**\n * Base configuration options for all providers\n */\nexport interface BaseTranslatorOptions {\n /**\n * Request timeout in milliseconds\n */\n timeout?: number;\n\n /**\n * Maximum number of retries for failed requests\n */\n maxRetries?: number;\n}\n\n/**\n * Google Translate provider options\n */\nexport interface GoogleTranslateOptions extends BaseTranslatorOptions {\n provider: 'google';\n /**\n * Google Cloud API key or credentials\n */\n apiKey: string;\n /**\n * Optional Google Cloud project ID\n */\n projectId?: string;\n}\n\n/**\n * DeepL provider options\n */\nexport interface DeepLOptions extends BaseTranslatorOptions {\n provider: 'deepl';\n /**\n * DeepL API key\n */\n apiKey: string;\n /**\n * Whether to use free or pro API endpoint (default: false = pro)\n */\n freeApi?: boolean;\n}\n\n/**\n * LibreTranslate provider options\n */\nexport interface LibreTranslateOptions extends BaseTranslatorOptions {\n provider: 'libretranslate';\n /**\n * Custom instance URL (default: https://libretranslate.com)\n */\n apiUrl?: string;\n /**\n * Optional API key for some instances\n */\n apiKey?: string;\n}\n\n/**\n * Union type for all provider options\n */\nexport type TranslatorOptions =\n | GoogleTranslateOptions\n | DeepLOptions\n | LibreTranslateOptions;\n\n/**\n * Base error class for translation operations\n *\n * @param message - Human-readable error description\n * @param code - Machine-readable error code (e.g., 'QUOTA_EXCEEDED', 'AUTH_ERROR', 'TIMEOUT')\n * @param provider - The provider that produced the error (e.g., 'google', 'deepl', 'libretranslate')\n */\nexport class TranslationError extends Error {\n constructor(\n message: string,\n public code: string,\n public provider?: string,\n ) {\n super(message);\n this.name = 'TranslationError';\n }\n}\n\n/**\n * Thrown when a requested language code is not supported by the provider\n *\n * @param language - The unsupported ISO 639-1 language code\n * @param provider - The provider that rejected the language\n */\nexport class UnsupportedLanguageError extends TranslationError {\n constructor(language: string, provider?: string) {\n super(\n `Unsupported language: ${language}`,\n 'UNSUPPORTED_LANGUAGE',\n provider,\n );\n this.name = 'UnsupportedLanguageError';\n }\n}\n\n/**\n * Thrown when the provider's translation quota or rate limit has been exceeded\n *\n * @param provider - The provider that reported the quota limit\n */\nexport class QuotaExceededError extends TranslationError {\n constructor(provider?: string) {\n super('Translation quota exceeded', 'QUOTA_EXCEEDED', provider);\n this.name = 'QuotaExceededError';\n }\n}\n\n/**\n * Thrown when the provider rejects the API key or credentials\n *\n * @param provider - The provider that rejected authentication\n */\nexport class AuthenticationError extends TranslationError {\n constructor(provider?: string) {\n super('Authentication failed', 'AUTH_ERROR', provider);\n this.name = 'AuthenticationError';\n }\n}\n\n/**\n * Thrown when the input text is empty or otherwise invalid for translation\n *\n * @param reason - Description of why the text is invalid\n * @param provider - The provider that rejected the text\n */\nexport class InvalidTextError extends TranslationError {\n constructor(reason: string, provider?: string) {\n super(`Invalid text: ${reason}`, 'INVALID_TEXT', provider);\n this.name = 'InvalidTextError';\n }\n}\n","/**\n * Utility functions for translation operations\n */\n\n/**\n * Common ISO 639-1 language codes and their names\n */\nexport const LANGUAGE_NAMES: Record<string, string> = {\n en: 'English',\n es: 'Spanish',\n fr: 'French',\n de: 'German',\n it: 'Italian',\n pt: 'Portuguese',\n ru: 'Russian',\n ja: 'Japanese',\n ko: 'Korean',\n zh: 'Chinese',\n ar: 'Arabic',\n hi: 'Hindi',\n nl: 'Dutch',\n pl: 'Polish',\n tr: 'Turkish',\n sv: 'Swedish',\n da: 'Danish',\n no: 'Norwegian',\n fi: 'Finnish',\n cs: 'Czech',\n el: 'Greek',\n he: 'Hebrew',\n th: 'Thai',\n vi: 'Vietnamese',\n id: 'Indonesian',\n ro: 'Romanian',\n uk: 'Ukrainian',\n bg: 'Bulgarian',\n hr: 'Croatian',\n sk: 'Slovak',\n sl: 'Slovenian',\n lt: 'Lithuanian',\n lv: 'Latvian',\n et: 'Estonian',\n hu: 'Hungarian',\n ca: 'Catalan',\n gl: 'Galician',\n eu: 'Basque',\n fa: 'Persian',\n ur: 'Urdu',\n bn: 'Bengali',\n ta: 'Tamil',\n te: 'Telugu',\n mr: 'Marathi',\n ml: 'Malayalam',\n kn: 'Kannada',\n gu: 'Gujarati',\n pa: 'Punjabi',\n sw: 'Swahili',\n ms: 'Malay',\n tl: 'Tagalog',\n af: 'Afrikaans',\n sq: 'Albanian',\n am: 'Amharic',\n hy: 'Armenian',\n az: 'Azerbaijani',\n be: 'Belarusian',\n bs: 'Bosnian',\n my: 'Burmese',\n ceb: 'Cebuano',\n ny: 'Chichewa',\n co: 'Corsican',\n eo: 'Esperanto',\n fy: 'Frisian',\n ka: 'Georgian',\n haw: 'Hawaiian',\n hmn: 'Hmong',\n is: 'Icelandic',\n ig: 'Igbo',\n ga: 'Irish',\n jw: 'Javanese',\n kk: 'Kazakh',\n km: 'Khmer',\n ku: 'Kurdish',\n ky: 'Kyrgyz',\n lo: 'Lao',\n la: 'Latin',\n lb: 'Luxembourgish',\n mk: 'Macedonian',\n mg: 'Malagasy',\n mt: 'Maltese',\n mi: 'Maori',\n mn: 'Mongolian',\n ne: 'Nepali',\n ps: 'Pashto',\n sm: 'Samoan',\n gd: 'Scots Gaelic',\n sr: 'Serbian',\n st: 'Sesotho',\n sn: 'Shona',\n sd: 'Sindhi',\n si: 'Sinhala',\n so: 'Somali',\n su: 'Sundanese',\n tg: 'Tajik',\n tt: 'Tatar',\n tk: 'Turkmen',\n ug: 'Uyghur',\n uz: 'Uzbek',\n cy: 'Welsh',\n xh: 'Xhosa',\n yi: 'Yiddish',\n yo: 'Yoruba',\n zu: 'Zulu',\n};\n\n/**\n * Validates an ISO 639-1 language code\n * @param code Language code to validate\n * @returns True if valid\n */\nexport function isValidLanguageCode(code: string): boolean {\n return code.length === 2 && /^[a-z]{2}$/.test(code);\n}\n\n/**\n * Gets the language name from a language code\n * @param code ISO 639-1 language code\n * @returns Language name or the code if not found\n */\nexport function getLanguageName(code: string): string {\n return LANGUAGE_NAMES[code] || code;\n}\n\n/**\n * Normalizes a confidence score to 0-1 range\n * @param score Confidence score (may be 0-1 or 0-100)\n * @returns Normalized score between 0 and 1\n */\nexport function normalizeConfidence(score: number): number {\n if (score > 1 && score <= 100) {\n return score / 100;\n }\n return Math.max(0, Math.min(1, score));\n}\n\n/**\n * Validates that text is not empty\n * @param text Text to validate\n * @returns True if text is valid\n */\nexport function isValidText(text: string): boolean {\n return typeof text === 'string' && text.trim().length > 0;\n}\n\n/**\n * Truncates text to a maximum length\n * @param text Text to truncate\n * @param maxLength Maximum length\n * @returns Truncated text\n */\nexport function truncateText(text: string, maxLength: number): string {\n if (text.length <= maxLength) {\n return text;\n }\n return `${text.substring(0, maxLength - 3)}...`;\n}\n","/**\n * Translator package entry point\n * Provides standardized translation interface\n */\n\nimport { loadEnvConfig } from '@happyvertical/utils';\nimport type {\n DeepLOptions,\n GoogleTranslateOptions,\n LanguageDetectionResult,\n LibreTranslateOptions,\n SupportedLanguage,\n TranslationProvider,\n TranslationResult,\n Translator,\n TranslatorOptions,\n} from './shared/types';\n\n// Export all types\nexport * from './shared/types';\nexport * from './shared/utils';\n\n/**\n * Type guard for Google Translate options\n */\nfunction _isGoogleTranslateOptions(\n options: TranslatorOptions,\n): options is GoogleTranslateOptions {\n return options.provider === 'google';\n}\n\n/**\n * Type guard for DeepL options\n */\nfunction _isDeepLOptions(options: TranslatorOptions): options is DeepLOptions {\n return options.provider === 'deepl';\n}\n\n/**\n * Type guard for LibreTranslate options\n */\nfunction _isLibreTranslateOptions(\n options: TranslatorOptions,\n): options is LibreTranslateOptions {\n return options.provider === 'libretranslate';\n}\n\n/**\n * Translator wrapper class that adds templateFunction to providers\n */\nclass TranslatorWrapper implements Translator {\n constructor(private provider: TranslationProvider) {}\n\n async translate(\n text: string,\n targetLanguage: string,\n sourceLanguage?: string,\n ): Promise<TranslationResult> {\n return this.provider.translate(text, targetLanguage, sourceLanguage);\n }\n\n async detectLanguage(text: string): Promise<LanguageDetectionResult> {\n return this.provider.detectLanguage(text);\n }\n\n async getSupportedLanguages(): Promise<SupportedLanguage[]> {\n return this.provider.getSupportedLanguages();\n }\n\n async translateBatch(\n texts: string[],\n targetLanguage: string,\n sourceLanguage?: string,\n ): Promise<TranslationResult[]> {\n return this.provider.translateBatch(texts, targetLanguage, sourceLanguage);\n }\n\n /**\n * Creates a pre-configured translation function\n * This is the key ergonomic feature that makes repeated translations simple\n */\n templateFunction(\n sourceLanguage?: string,\n targetLanguage: string = 'en',\n ): (text: string) => Promise<string> {\n return async (text: string): Promise<string> => {\n const result = await this.provider.translate(\n text,\n targetLanguage,\n sourceLanguage,\n );\n return result.translatedText;\n };\n }\n}\n\n/**\n * Factory function to create a translator instance\n *\n * Supports environment variable configuration using HAVE_TRANSLATOR_* pattern:\n * - HAVE_TRANSLATOR_PROVIDER: Translation provider ('google'|'deepl'|'libretranslate')\n *\n * Provider-specific API keys are loaded from their respective environment variables:\n * - GOOGLE_TRANSLATE_API_KEY: Google Translate API key\n * - DEEPL_API_KEY: DeepL API key\n *\n * @param options - Configuration options for the translation provider (optional if using env vars)\n * @returns Promise resolving to a translator that implements Translator\n *\n * @example\n * ```typescript\n * // Using explicit options\n * const translator = await getTranslator({\n * provider: 'google',\n * apiKey: process.env.GOOGLE_TRANSLATE_API_KEY!\n * });\n *\n * // Using environment variables\n * // Set: HAVE_TRANSLATOR_PROVIDER=deepl\n * // DEEPL_API_KEY=your_key_here\n * const translator = await getTranslator();\n *\n * // Mix of env vars and explicit options (explicit takes precedence)\n * // Set: HAVE_TRANSLATOR_PROVIDER=google\n * const translator = await getTranslator({\n * apiKey: 'explicit_key' // Overrides env var\n * });\n *\n * // Use the translator\n * const result = await translator.translate('Hello, world!', 'es');\n *\n * // Use template function for repeated translations\n * const t = translator.templateFunction('en', 'es');\n * const greeting = await t('Hello');\n * const farewell = await t('Goodbye');\n * ```\n */\nexport async function getTranslator(\n options: Partial<TranslatorOptions> = {},\n): Promise<Translator> {\n // Load configuration from environment variables with user options taking precedence\n const config: Record<string, any> = loadEnvConfig(\n options as Record<string, any>,\n {\n packageName: 'translator',\n schema: {\n provider: 'string',\n timeout: 'number',\n maxRetries: 'number',\n },\n allowUnknown: true,\n },\n );\n\n // Load provider-specific API keys from their respective env vars\n // This maintains backward compatibility with existing env var patterns\n if (!config.apiKey) {\n if (config.provider === 'google' && process.env.GOOGLE_TRANSLATE_API_KEY) {\n config.apiKey = process.env.GOOGLE_TRANSLATE_API_KEY;\n } else if (config.provider === 'deepl' && process.env.DEEPL_API_KEY) {\n config.apiKey = process.env.DEEPL_API_KEY;\n }\n }\n\n // Validate provider is set\n if (!config.provider) {\n throw new Error(\n 'Translation provider not specified. Set HAVE_TRANSLATOR_PROVIDER environment variable or pass provider in options.',\n );\n }\n\n let provider: TranslationProvider;\n\n if (config.provider === 'google') {\n const { GoogleTranslateProvider } = await import('./providers/google.js');\n provider = new GoogleTranslateProvider(config as GoogleTranslateOptions);\n } else if (config.provider === 'deepl') {\n const { DeepLProvider } = await import('./providers/deepl.js');\n provider = new DeepLProvider(config as DeepLOptions);\n } else if (config.provider === 'libretranslate') {\n const { LibreTranslateProvider } = await import(\n './providers/libretranslate.js'\n );\n provider = new LibreTranslateProvider(config as LibreTranslateOptions);\n } else {\n throw new Error(`Unsupported provider: ${config.provider}`);\n }\n\n return new TranslatorWrapper(provider);\n}\n\n/** @internal */\nexport const PACKAGE_VERSION_INITIALIZED = true;\n"],"mappings":"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"}