gptrans 1.1.8 → 1.2.2

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.
@@ -1,9 +0,0 @@
1
- {
2
- "topup_uzdh5y": "شحن",
3
- "transf_176pc1a": "تحويل",
4
- "deposi_wg2ec5": "إيداع",
5
- "balanc_1rv8if7": "رصيد",
6
- "transa_1wtqm5d": "معاملة",
7
- "accoun_x1y0v8": "حساب",
8
- "card_yis1ox": "بطاقة"
9
- }
@@ -0,0 +1,10 @@
1
+ {
2
+ "hello_name_1987p1n": "Ciao, {name}!",
3
+ "topup_uzdh5y": "Ricarica",
4
+ "transf_176pc1a": "Trasferimento",
5
+ "deposi_wg2ec5": "Deposito",
6
+ "balanc_1rv8if7": "Saldo",
7
+ "transa_1wtqm5d": "Transazione",
8
+ "accoun_x1y0v8": "Conto",
9
+ "card_yis1ox": "Carta"
10
+ }
package/demo/case_2.js CHANGED
@@ -2,18 +2,20 @@ import GPTrans from '../index.js';
2
2
 
3
3
  try {
4
4
  const gptrans = new GPTrans({
5
- target: 'ar',
6
- model: 'claude-3-7-sonnet-20250219',
5
+ target: 'it',
6
+ model: 'gpt-4o-mini',
7
7
  });
8
8
 
9
+ await gptrans.preload();
10
+ console.log('ready');
11
+
9
12
  console.log(gptrans.t('Top-up'));
10
13
  console.log(gptrans.t('Transfer'));
11
14
  console.log(gptrans.t('Deposit'));
12
15
  console.log(gptrans.t('Balance'));
13
16
  console.log(gptrans.t('Transaction'));
14
17
  console.log(gptrans.t('Account'));
15
- console.log(gptrans.t('Card'));
18
+ console.log(gptrans.t('Card'));
16
19
  } catch (e) {
17
20
  console.error(e);
18
- }
19
-
21
+ }
package/index.js CHANGED
@@ -1,13 +1,12 @@
1
1
  import DeepBase from 'deepbase';
2
2
  import stringHash from 'string-hash';
3
3
  import { ModelMix, MixOpenAI, MixAnthropic } from 'modelmix';
4
+ import { isoAssoc, isLanguageAvailable } from './isoAssoc.js';
4
5
  import dotenv from 'dotenv';
5
- import path from 'path';
6
6
 
7
- import { isoAssoc } from './isoAssoc.js';
8
7
  dotenv.config();
9
8
 
10
- class Gptrans {
9
+ class GPTrans {
11
10
  static #mmixInstance = null;
12
11
 
13
12
  static get mmix() {
@@ -22,10 +21,14 @@ class Gptrans {
22
21
  return this.#mmixInstance;
23
22
  }
24
23
 
24
+ static isLanguageAvailable(langCode) {
25
+ return isLanguageAvailable(langCode);
26
+ }
27
+
25
28
  constructor({ from = 'en-US', target = 'es-AR', model = 'claude-3-7-sonnet-20250219', batchThreshold = 1000, debounceTimeout = 500, promptFile = null, context = '' }) {
26
29
  this.dbTarget = new DeepBase({ name: 'gptrans_' + target });
27
30
  this.dbFrom = new DeepBase({ name: 'gptrans_from_' + from });
28
-
31
+
29
32
  try {
30
33
  this.replace_target = isoAssoc(target, 'TARGET_');
31
34
  this.replace_from = isoAssoc(from, 'FROM_');
@@ -39,18 +42,19 @@ class Gptrans {
39
42
  this.pendingCharCount = 0; // Add character count tracker
40
43
  this.debounceTimer = null;
41
44
  this.modelKey = model;
42
- this.promptFile ??= path.resolve('./prompt/translate.md'); // Convert to absolute path
45
+ this.promptFile = promptFile ?? new URL('./prompt/translate.md', import.meta.url).pathname;
43
46
  this.context = context;
44
47
  this.modelConfig = {
45
48
  config: {
46
49
  max_history: 1,
47
50
  debug: false,
48
51
  bottleneck: {
49
- maxConcurrent: 5,
52
+ maxConcurrent: 2,
50
53
  }
51
54
  },
52
55
  options: { max_tokens: batchThreshold }
53
56
  };
57
+ this.processing = false;
54
58
  }
55
59
 
56
60
  setContext(context = '') {
@@ -104,6 +108,8 @@ class Gptrans {
104
108
  }
105
109
 
106
110
  async _processBatch() {
111
+ this.processing = true;
112
+
107
113
  const batch = Array.from(this.pendingTranslations.entries());
108
114
 
109
115
  // Clear pending translations and character count before awaiting translation
@@ -119,10 +125,12 @@ class Gptrans {
119
125
  batch.forEach(([key], index) => {
120
126
  this.dbTarget.set(key, translatedTexts[index].trim());
121
127
  });
128
+
129
+ this.processing = false;
122
130
  }
123
131
 
124
132
  async _translate(text) {
125
- const model = Gptrans.mmix.create(this.modelKey, this.modelConfig);
133
+ const model = GPTrans.mmix.create(this.modelKey, this.modelConfig);
126
134
 
127
135
  model.setSystem("You are an expert translator specialized in literary translation between FROM_LANG and TARGET_DENONYM TARGET_LANG.");
128
136
 
@@ -154,6 +162,37 @@ class Gptrans {
154
162
  key += stringHash(text + this.context).toString(36);
155
163
  return key;
156
164
  }
165
+
166
+ async preload({ target = this.replace_target.TARGET_ISO, model = this.modelKey, from = this.replace_from.FROM_ISO, batchThreshold = this.batchThreshold, debounceTimeout = this.debounceTimeout } = {}) {
167
+
168
+ // Create new GPTrans instance for the target language
169
+ const translator = new GPTrans({
170
+ from,
171
+ target,
172
+ model,
173
+ batchThreshold,
174
+ debounceTimeout,
175
+ });
176
+
177
+ // Process all entries in batches
178
+ for (const [key, text] of this.dbFrom.entries()) {
179
+ translator.get(key, text);
180
+ }
181
+
182
+ // Wait for any pending translations to complete
183
+ if (translator.pendingTranslations.size > 0) {
184
+ await new Promise(resolve => {
185
+ const checkInterval = setInterval(() => {
186
+ if (translator.processing === false && translator.pendingTranslations.size === 0) {
187
+ clearInterval(checkInterval);
188
+ resolve();
189
+ }
190
+ }, 1000);
191
+ });
192
+ }
193
+
194
+ return translator;
195
+ }
157
196
  }
158
197
 
159
- export default Gptrans;
198
+ export default GPTrans;
package/isoAssoc.js CHANGED
@@ -152,38 +152,44 @@ const langName = {
152
152
  'ms': 'Malay'
153
153
  };
154
154
 
155
+ export function isLanguageAvailable(isoCode) {
156
+ if (!isoCode) return false;
157
+
158
+ const parts = isoCode.toLowerCase().split('-');
159
+ const lang = parts[0];
160
+ const country = parts.length > 1 ? parts[1] : null;
161
+
162
+ // Verificar si el idioma existe
163
+ if (!langName[lang]) return false;
164
+
165
+ // Si hay código de país, verificar si existe
166
+ if (country && !countryName[country]) return false;
167
+
168
+ return true;
169
+ }
170
+
155
171
  export function isoAssoc(iso, prefix = '') {
156
172
  if (!iso) {
157
173
  throw new Error('ISO code is required');
158
174
  }
175
+
176
+ // Usar la nueva función para validar el ISO
177
+ if (!isLanguageAvailable(iso)) {
178
+ throw new Error(`Invalid ISO code: ${iso}`);
179
+ }
159
180
 
160
181
  const parts = iso.toLowerCase().split('-');
161
182
  const lang = parts[0];
162
183
  const country = parts.length > 1 ? parts[1] : null;
163
184
 
164
- if (!langName[lang]) {
165
- throw new Error(`Invalid language code: ${lang}`);
166
- }
167
-
168
- if (country && !countryName[country]) {
169
- throw new Error(`Invalid country code: ${country}`);
170
- }
171
-
172
- // Special handling for languages with variants
173
185
  let denonym = country ? countryDenonym[country] : 'Neutral';
174
-
175
- // Handle Chinese without specified dialect (use "Simplified" instead of "Neutral")
186
+
176
187
  if (lang === 'zh' && !country) {
177
188
  denonym = 'Simplified';
178
189
  }
179
- // Handle Arabic without specified dialect (use "Standard" instead of "Neutral")
180
190
  else if (lang === 'ar' && !country) {
181
191
  denonym = 'Standard';
182
192
  }
183
- // Handle Portuguese without specified dialect (use "European" instead of "Neutral")
184
- else if (lang === 'pt' && !country) {
185
- denonym = 'European';
186
- }
187
193
 
188
194
  return {
189
195
  [prefix + 'ISO']: iso,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gptrans",
3
3
  "type": "module",
4
- "version": "1.1.8",
4
+ "version": "1.2.2",
5
5
  "description": "🚆 GPTrans - The smarter AI-powered way to translate.",
6
6
  "keywords": [
7
7
  "translate",
@@ -14,6 +14,7 @@
14
14
  "language",
15
15
  "translation",
16
16
  "translator",
17
+ "magic",
17
18
  "clasen"
18
19
  ],
19
20
  "repository": {