@@ -2,185 +2,8 @@ import dedent from "dedent";
22import { ILocalizer , LocalizerData } from "./_types" ;
33import chalk from "chalk" ;
44import { colors } from "../constants" ;
5+ import { LingoDotDevEngine } from "@lingo.dev/_sdk" ;
56import { getSettings } from "../utils/settings" ;
6- import { createId } from "@paralleldrive/cuid2" ;
7-
8- /**
9- * Creates a custom engine for Lingo.dev vNext that sends requests to:
10- * https://api.lingo.dev/process/<processId>/localize
11- */
12- function createVNextEngine ( config : {
13- apiKey : string ;
14- apiUrl : string ;
15- processId : string ;
16- sessionId : string ;
17- triggerType : "cli" | "ci" ;
18- } ) {
19- const endpoint = `${ config . apiUrl } /process/${ config . processId } /localize` ;
20-
21- return {
22- async localizeChunk (
23- sourceLocale : string | null ,
24- targetLocale : string ,
25- payload : {
26- data : Record < string , any > ;
27- reference ?: Record < string , Record < string , any > > ;
28- hints ?: Record < string , string [ ] > ;
29- } ,
30- fast : boolean ,
31- filePath ?: string ,
32- signal ?: AbortSignal ,
33- ) : Promise < Record < string , string > > {
34- const res = await fetch ( endpoint , {
35- method : "POST" ,
36- headers : {
37- "Content-Type" : "application/json; charset=utf-8" ,
38- "X-API-Key" : config . apiKey ,
39- } ,
40- body : JSON . stringify (
41- {
42- params : { fast } ,
43- sourceLocale,
44- targetLocale,
45- data : payload . data ,
46- reference : payload . reference ,
47- hints : payload . hints ,
48- sessionId : config . sessionId ,
49- triggerType : config . triggerType ,
50- metadata : filePath ? { filePath } : undefined ,
51- } ,
52- null ,
53- 2 ,
54- ) ,
55- signal,
56- } ) ;
57-
58- if ( ! res . ok ) {
59- if ( res . status >= 500 && res . status < 600 ) {
60- const errorText = await res . text ( ) ;
61- throw new Error (
62- `Server error (${ res . status } ): ${ res . statusText } . ${ errorText } . This may be due to temporary service issues.` ,
63- ) ;
64- } else if ( res . status === 400 ) {
65- throw new Error ( `Invalid request: ${ res . statusText } ` ) ;
66- } else {
67- const errorText = await res . text ( ) ;
68- throw new Error ( errorText ) ;
69- }
70- }
71-
72- const jsonResponse = await res . json ( ) ;
73-
74- if ( ! jsonResponse . data && jsonResponse . error ) {
75- throw new Error ( jsonResponse . error ) ;
76- }
77-
78- return jsonResponse . data || { } ;
79- } ,
80-
81- async whoami (
82- signal ?: AbortSignal ,
83- ) : Promise < { email : string ; id : string } | null > {
84- // vNext uses a simple response for whoami
85- return { email : "vnext-user" , id : config . processId } ;
86- } ,
87-
88- async localizeObject (
89- obj : Record < string , any > ,
90- params : {
91- sourceLocale : string | null ;
92- targetLocale : string ;
93- fast ?: boolean ;
94- reference ?: Record < string , Record < string , any > > ;
95- hints ?: Record < string , string [ ] > ;
96- filePath ?: string ;
97- } ,
98- progressCallback ?: (
99- progress : number ,
100- sourceChunk : Record < string , string > ,
101- processedChunk : Record < string , string > ,
102- ) => void ,
103- signal ?: AbortSignal ,
104- ) : Promise < Record < string , string > > {
105- const chunkedPayload = extractPayloadChunks ( obj ) ;
106- const processedPayloadChunks : Record < string , string > [ ] = [ ] ;
107-
108- for ( let i = 0 ; i < chunkedPayload . length ; i ++ ) {
109- const chunk = chunkedPayload [ i ] ;
110- const percentageCompleted = Math . round (
111- ( ( i + 1 ) / chunkedPayload . length ) * 100 ,
112- ) ;
113-
114- const processedPayloadChunk = await this . localizeChunk (
115- params . sourceLocale ,
116- params . targetLocale ,
117- { data : chunk , reference : params . reference , hints : params . hints } ,
118- params . fast || false ,
119- params . filePath ,
120- signal ,
121- ) ;
122-
123- if ( progressCallback ) {
124- progressCallback ( percentageCompleted , chunk , processedPayloadChunk ) ;
125- }
126-
127- processedPayloadChunks . push ( processedPayloadChunk ) ;
128- }
129-
130- return Object . assign ( { } , ...processedPayloadChunks ) ;
131- } ,
132- } ;
133- }
134-
135- /**
136- * Helper functions for chunking payloads
137- */
138- function extractPayloadChunks (
139- payload : Record < string , string > ,
140- batchSize : number = 25 ,
141- idealBatchItemSize : number = 250 ,
142- ) : Record < string , string > [ ] {
143- const result : Record < string , string > [ ] = [ ] ;
144- let currentChunk : Record < string , string > = { } ;
145- let currentChunkItemCount = 0 ;
146-
147- const payloadEntries = Object . entries ( payload ) ;
148- for ( let i = 0 ; i < payloadEntries . length ; i ++ ) {
149- const [ key , value ] = payloadEntries [ i ] ;
150- currentChunk [ key ] = value ;
151- currentChunkItemCount ++ ;
152-
153- const currentChunkSize = countWordsInRecord ( currentChunk ) ;
154- if (
155- currentChunkSize > idealBatchItemSize ||
156- currentChunkItemCount >= batchSize ||
157- i === payloadEntries . length - 1
158- ) {
159- result . push ( currentChunk ) ;
160- currentChunk = { } ;
161- currentChunkItemCount = 0 ;
162- }
163- }
164-
165- return result ;
166- }
167-
168- function countWordsInRecord (
169- payload : any | Record < string , any > | Array < any > ,
170- ) : number {
171- if ( Array . isArray ( payload ) ) {
172- return payload . reduce ( ( acc , item ) => acc + countWordsInRecord ( item ) , 0 ) ;
173- } else if ( typeof payload === "object" && payload !== null ) {
174- return Object . values ( payload ) . reduce (
175- ( acc : number , item ) => acc + countWordsInRecord ( item ) ,
176- 0 ,
177- ) ;
178- } else if ( typeof payload === "string" ) {
179- return payload . trim ( ) . split ( / \s + / ) . filter ( Boolean ) . length ;
180- } else {
181- return 0 ;
182- }
183- }
1847
1858export default function createLingoDotDevVNextLocalizer (
1869 processId : string ,
@@ -207,15 +30,12 @@ export default function createLingoDotDevVNextLocalizer(
20730 // Use LINGO_API_URL from environment or default to api.lingo.dev
20831 const apiUrl = process . env . LINGO_API_URL || "https://api.lingo.dev" ;
20932
210- const sessionId = createId ( ) ;
21133 const triggerType = process . env . CI ? "ci" : "cli" ;
21234
213- const engine = createVNextEngine ( {
35+ const engine = new LingoDotDevEngine ( {
21436 apiKey,
21537 apiUrl,
216- processId,
217- sessionId,
218- triggerType,
38+ engineId : processId ,
21939 } ) ;
22040
22141 return {
@@ -250,6 +70,7 @@ export default function createLingoDotDevVNextLocalizer(
25070 } ,
25171 hints : input . hints ,
25272 filePath : input . filePath ,
73+ triggerType,
25374 } ,
25475 onProgress ,
25576 ) ;
0 commit comments