diff --git a/apps/readest-app/src/app/reader/components/annotator/DeepLPopup.tsx b/apps/readest-app/src/app/reader/components/annotator/DeepLPopup.tsx index 65635bb0..0939d069 100644 --- a/apps/readest-app/src/app/reader/components/annotator/DeepLPopup.tsx +++ b/apps/readest-app/src/app/reader/components/annotator/DeepLPopup.tsx @@ -76,7 +76,8 @@ const DeepLPopup: React.FC = ({ setTranslation(null); try { - const result = await translate([text]); + const input = text.replaceAll('\n', ' ').trim(); + const result = await translate([input]); const translatedText = result[0]; const detectedSource = null; diff --git a/apps/readest-app/src/pages/api/deepl/translate.ts b/apps/readest-app/src/pages/api/deepl/translate.ts index eebb8ed6..a69a8de1 100644 --- a/apps/readest-app/src/pages/api/deepl/translate.ts +++ b/apps/readest-app/src/pages/api/deepl/translate.ts @@ -130,8 +130,11 @@ async function callDeepLAPI( ) { const isV2Api = apiUrl.endsWith('/v2/translate'); + // TODO: this should be processed in the client, but for now, we need to do it here + // please remove this when most clients are updated + const input = text.replaceAll('\n', ' ').trim(); const requestBody = { - text: isV2Api ? [text] : text, + text: isV2Api ? [input] : input, source_lang: isV2Api ? sourceLang : (LANG_V2_V1_MAP[sourceLang] ?? sourceLang), target_lang: isV2Api ? targetLang : (LANG_V2_V1_MAP[targetLang] ?? targetLang), }; diff --git a/apps/readest-app/src/services/translators/providers/deepl.ts b/apps/readest-app/src/services/translators/providers/deepl.ts index fb0339fd..593e0daf 100644 --- a/apps/readest-app/src/services/translators/providers/deepl.ts +++ b/apps/readest-app/src/services/translators/providers/deepl.ts @@ -12,46 +12,37 @@ export const deeplProvider: TranslationProvider = { token?: string | null, useCache: boolean = false, ): Promise => { - try { - const headers: Record = { - 'Content-Type': 'application/json', - }; + const headers: Record = { + 'Content-Type': 'application/json', + }; - if (token) { - headers['Authorization'] = `Bearer ${token}`; - } - - const response = await fetch(DEEPL_API_ENDPOINT, { - method: 'POST', - headers, - body: JSON.stringify({ - text: text, - source_lang: sourceLang, - target_lang: targetLang, - use_cache: useCache, - }), - }); - - if (!response.ok) { - throw new Error(`Translation failed with status ${response.status}`); - } - - const data = await response.json(); - - const result = [...text]; - let translationIndex = 0; - - for (let i = 0; i < text.length; i++) { - if (text[i]!.trim().length > 0) { - result[i] = data.translations?.[translationIndex]?.text || text[i]; - translationIndex++; - } - } - - return result; - } catch (error) { - console.error('Translation error:', error); - return text; + if (token) { + headers['Authorization'] = `Bearer ${token}`; } + + const body = JSON.stringify({ + text: text, + source_lang: sourceLang, + target_lang: targetLang, + use_cache: useCache, + }); + + const response = await fetch(DEEPL_API_ENDPOINT, { method: 'POST', headers, body }); + + if (!response.ok) { + throw new Error(`Translation failed with status ${response.status}`); + } + + const data = await response.json(); + if (!data || !data.translations) { + throw new Error('Invalid response from translation service'); + } + + return text.map((line, i) => { + if (!line?.trim().length) { + return line; + } + return data.translations?.[i]?.text || line; + }); }, };