@@ -12,7 +12,7 @@ import { colors } from "../constants";
1212import { jsonrepair } from "jsonrepair" ;
1313import { createOllama } from "ollama-ai-provider-v2" ;
1414import _ from "lodash" ;
15-
15+ import { extractPayloadChunks } from "../utils/chunk" ;
1616export default function createExplicitLocalizer (
1717 provider : NonNullable < I18nConfig [ "provider" ] > ,
1818 batchSize ?: number ,
@@ -28,10 +28,10 @@ export default function createExplicitLocalizer(
2828 To fix this issue:
2929 1. Switch to one of the supported providers, or
3030 2. Remove the ${ chalk . italic (
31- "provider" ,
32- ) } node from your i18n.json configuration to switch to ${ chalk . hex (
33- colors . green ,
34- ) ( "Lingo.dev" ) }
31+ "provider" ,
32+ ) } node from your i18n.json configuration to switch to ${ chalk . hex (
33+ colors . green ,
34+ ) ( "Lingo.dev" ) }
3535
3636 ${ chalk . hex ( colors . blue ) ( "Docs: https://lingo.dev/go/docs" ) }
3737 ` ,
@@ -136,19 +136,21 @@ function createAiSdkLocalizer(params: {
136136 if ( ! skipAuth && ( ! apiKey || ! params . apiKeyName ) ) {
137137 throw new Error (
138138 dedent `
139- You're trying to use raw ${ chalk . dim ( params . id ) } API for translation. ${ params . apiKeyName
140- ? `However, ${ chalk . dim (
141- params . apiKeyName ,
142- ) } environment variable is not set.`
143- : "However, that provider is unavailable."
139+ You're trying to use raw ${ chalk . dim ( params . id ) } API for translation. ${
140+ params . apiKeyName
141+ ? `However, ${ chalk . dim (
142+ params . apiKeyName ,
143+ ) } environment variable is not set.`
144+ : "However, that provider is unavailable."
144145 }
145146
146147 To fix this issue:
147- 1. ${ params . apiKeyName
148- ? `Set ${ chalk . dim (
149- params . apiKeyName ,
150- ) } in your environment variables`
151- : "Set the environment variable for your provider (if required)"
148+ 1. ${
149+ params . apiKeyName
150+ ? `Set ${ chalk . dim (
151+ params . apiKeyName ,
152+ ) } in your environment variables`
153+ : "Set the environment variable for your provider (if required)"
152154 } , or
153155 2. Remove the ${ chalk . italic (
154156 "provider" ,
@@ -295,30 +297,17 @@ function createAiSdkLocalizer(params: {
295297 // Handle both object and string responses
296298 if ( typeof result ?. data === "object" && result . data !== null ) {
297299 finalResult = result . data ;
298- } else if ( result ?. data ) {
299- // Handle string responses - extract and repair JSON
300- const index = result . data . indexOf ( "{" ) ;
301- const lastIndex = result . data . lastIndexOf ( "}" ) ;
302- if ( index !== - 1 && lastIndex !== - 1 ) {
303- try {
304- const trimmed = result . data . slice ( index , lastIndex + 1 ) ;
305- const repaired = jsonrepair ( trimmed ) ;
306- const parsed = JSON . parse ( repaired ) ;
307- finalResult = parsed . data || parsed || { } ;
308- } catch ( e ) {
309- console . error (
310- `Failed to parse nested JSON response. Snippet: ${ result . data . slice ( 0 , 100 ) } ...` ,
311- ) ;
312- throw new Error (
313- `Failed to parse nested JSON response: ${ e } (Snippet: ${ result . data . slice ( 0 , 100 ) } ...)` ,
314- ) ;
315- }
316- } else {
300+ } else if ( typeof result ?. data === "string" ) {
301+ // Handle string responses where the model double-stringified the JSON
302+ try {
303+ const parsed = parseModelResponse ( result . data ) ;
304+ finalResult = parsed . data || parsed || { } ;
305+ } catch ( e ) {
317306 console . error (
318- `Unexpected response format - no JSON object found . Snippet: ${ String ( result . data ) . slice ( 0 , 100 ) } ...` ,
307+ `Failed to parse nested JSON response . Snippet: ${ result . data . slice ( 0 , 100 ) } ...` ,
319308 ) ;
320309 throw new Error (
321- `Unexpected response format from ${ params . id } - no JSON object found in response ` ,
310+ `Failed to parse nested JSON response: ${ e } (Snippet: ${ result . data . slice ( 0 , 100 ) } ...) ` ,
322311 ) ;
323312 }
324313 }
@@ -334,63 +323,3 @@ function createAiSdkLocalizer(params: {
334323 } ,
335324 } ;
336325}
337-
338- /**
339- * Extract payload chunks based on the ideal chunk size
340- * @param payload - The payload to be chunked
341- * @param batchSize - Max number of keys per chunk (default: 25)
342- * @returns An array of payload chunks
343- */
344- function extractPayloadChunks (
345- payload : Record < string , any > ,
346- batchSize ?: number ,
347- ) : Record < string , any > [ ] {
348- const idealBatchItemSize = 250 ;
349- const result : Record < string , any > [ ] = [ ] ;
350- let currentChunk : Record < string , any > = { } ;
351- let currentChunkItemCount = 0 ;
352-
353- const payloadEntries = Object . entries ( payload ) ;
354- for ( let i = 0 ; i < payloadEntries . length ; i ++ ) {
355- const [ key , value ] = payloadEntries [ i ] ;
356- currentChunk [ key ] = value ;
357- currentChunkItemCount ++ ;
358-
359- const currentChunkSize = countWordsInRecord ( currentChunk ) ;
360- const effectiveBatchSize =
361- batchSize && batchSize > 0 ? batchSize : payloadEntries . length || 1 ;
362- if (
363- currentChunkSize > idealBatchItemSize ||
364- currentChunkItemCount >= effectiveBatchSize ||
365- i === payloadEntries . length - 1
366- ) {
367- result . push ( currentChunk ) ;
368- currentChunk = { } ;
369- currentChunkItemCount = 0 ;
370- }
371- }
372-
373- return result ;
374- }
375-
376- /**
377- * Count words in a record or array
378- * @param payload - The payload to count words in
379- * @returns The total number of words
380- */
381- function countWordsInRecord (
382- payload : any | Record < string , any > | Array < any > ,
383- ) : number {
384- if ( Array . isArray ( payload ) ) {
385- return payload . reduce ( ( acc , item ) => acc + countWordsInRecord ( item ) , 0 ) ;
386- } else if ( typeof payload === "object" && payload !== null ) {
387- return Object . values ( payload ) . reduce (
388- ( acc : number , item ) => acc + countWordsInRecord ( item ) ,
389- 0 ,
390- ) ;
391- } else if ( typeof payload === "string" ) {
392- return payload . trim ( ) . split ( / \s + / ) . filter ( Boolean ) . length ;
393- } else {
394- return 0 ;
395- }
396- }
0 commit comments