UNPKG

@deeplx/core

Version:

An unofficial but powerful and easy-to-use yet free DeepL API client for Node.js using [DeepL](https://www.deepl.com) by porting [OwO-Network/DeepLX](https://github.com/OwO-Network/DeepLX).

150 lines 5.57 kB
import { createProxy } from 'node-fetch-native/proxy'; import { detectLang } from 'whatlang-node'; import { xfetch } from 'x-fetch'; import { API_URL, COMMON_HEADERS, HTTP_STATUS_NOT_FOUND, HTTP_STATUS_OK, HTTP_STATUS_SERVICE_UNAVAILABLE, } from "./constants.js"; import { abbreviateLanguage, formatPostString, getICount, getRandomNumber, getTimeStamp, } from "./utils.js"; const makeRequest = async (postData, proxyUrl, dlSession) => { return xfetch(API_URL, { method: 'POST', body: formatPostString(postData), headers: dlSession ? { ...COMMON_HEADERS, Cookie: `dl_session=${dlSession}` } : COMMON_HEADERS, ...createProxy({ url: proxyUrl }), }); }; const splitAndProcess = (text) => text.split('\n').map(line => (line.trim() === '' ? '\n' : line)); export const translateByDeepLX = async (sourceLang, targetLang, text, formal, tagHandling = 'plaintext', proxyUrl, dlSession) => { if (!text) { return { code: HTTP_STATUS_NOT_FOUND, message: 'No text to translate' }; } const textParts = splitAndProcess(text); const translatedParts = []; const allAlternatives = []; for (const part of textParts) { if (!part.trim()) { translatedParts.push(''); allAlternatives.push(['']); continue; } if (!sourceLang || sourceLang === 'auto') { sourceLang = detectLang(part, true); } const sourceLangCode = abbreviateLanguage(sourceLang) ?? sourceLang.toUpperCase(); const jobs = [ { kind: 'default', preferred_num_beams: 4, raw_en_context_before: [], raw_en_context_after: [], sentences: [{ prefix: '', text: part, id: 0 }], }, ]; let hasRegionalVariant = false; let targetLangCode = abbreviateLanguage(targetLang) ?? targetLang.toUpperCase(); const targetLangParts = targetLang.split('-'); if (targetLangParts.length > 1) { targetLangCode = targetLangParts[0]; hasRegionalVariant = true; } const id = getRandomNumber(); const postData = { jsonrpc: '2.0', method: 'LMT_handle_jobs', id, params: { commonJobParams: { mode: 'translate', formality: formal == null ? 'undefined' : formal ? 'formal' : 'informal', transcribe_as: 'romanize', advancedMode: false, textType: tagHandling, wasSpoken: false, ...(hasRegionalVariant && { regionalVariant: targetLang }), }, lang: { source_lang_user_selected: 'auto', target_lang: targetLangCode, source_lang_computed: sourceLangCode, }, jobs, timestamp: getTimeStamp(getICount(part)), }, }; let translations; try { const { result } = await makeRequest(postData, proxyUrl, dlSession); translations = result.translations; } catch (error) { return { code: HTTP_STATUS_SERVICE_UNAVAILABLE, message: String(error), }; } let partTranslation = ''; const partAlternatives = []; if (translations.length > 0) { for (const translation of translations) { partTranslation += translation.beams[0].sentences[0].text + ' '; } partTranslation = partTranslation.trim(); const numBeams = translations[0].beams.length; for (let i = 1; i < numBeams; i++) { let altText = ''; for (const translation of translations) { const beams = translation.beams; if (i < beams.length) { altText += beams[i].sentences[0].text + ' '; } } if (altText) { partAlternatives.push(altText.trim()); } } } if (!partTranslation) { return { code: HTTP_STATUS_SERVICE_UNAVAILABLE, message: 'Translation failed', }; } translatedParts.push(partTranslation); allAlternatives.push(partAlternatives); } const translatedText = translatedParts.join('\n'); const combinedAlternatives = []; let maxAlts = 0; for (const alts of allAlternatives) { if (alts.length > maxAlts) { maxAlts = alts.length; } } for (let i = 0; i < maxAlts; i++) { const altParts = []; for (const [j, alts] of allAlternatives.entries()) { if (i < alts.length) { altParts.push(alts[i]); } else if (translatedParts[j].length === 0) { altParts.push(''); } else { altParts.push(translatedParts[j]); } } combinedAlternatives.push(altParts.join('\n')); } return { code: HTTP_STATUS_OK, id: getRandomNumber(), data: translatedText, alternatives: combinedAlternatives, sourceLang: sourceLang, targetLang, method: dlSession ? 'Pro' : 'Free', }; }; //# sourceMappingURL=translate.js.map