UNPKG

deepl-node

Version:

deepl-node is the official DeepL Node.js client library

283 lines (282 loc) 11.1 kB
"use strict"; // Copyright 2022 DeepL SE (https://www.deepl.com) // Use of this source code is governed by an MIT // license that can be found in the LICENSE file. var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.extractGlossaryId = exports.appendCsvDictionaryEntries = exports.appendDictionaryEntries = exports.validateAndAppendTextOptions = exports.appendTextsAndReturnIsSingular = exports.buildURLSearchParams = exports.nonRegionalLanguageCode = exports.standardizeLanguageCode = exports.isFreeAccountAuthKey = exports.toBoolString = exports.isString = exports.timeout = exports.streamToString = exports.streamToBuffer = exports.logInfo = exports.logDebug = void 0; const loglevel_1 = __importDefault(require("loglevel")); const errors_1 = require("./errors"); const logger = loglevel_1.default.getLogger('deepl'); function concatLoggingArgs(args) { let detail = ''; if (args) { for (const [key, value] of Object.entries(args)) { detail += `, ${key} = ${value}`; } } return detail; } function logDebug(message, args) { logger.debug(message + concatLoggingArgs(args)); } exports.logDebug = logDebug; function logInfo(message, args) { logger.info(message + concatLoggingArgs(args)); } exports.logInfo = logInfo; /** * Converts contents of given stream to a Buffer. * @private */ async function streamToBuffer(stream) { const chunks = []; return new Promise((resolve, reject) => { stream.on('data', (chunk) => chunks.push(chunk)); stream.on('error', (err) => reject(err)); stream.on('end', () => resolve(Buffer.concat(chunks))); }); } exports.streamToBuffer = streamToBuffer; /** * Converts contents of given stream to a string using UTF-8 encoding. * @private */ async function streamToString(stream) { return (await streamToBuffer(stream)).toString('utf8'); } exports.streamToString = streamToString; // Wrap setTimeout() with Promise const timeout = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); exports.timeout = timeout; /** * Returns true if the given argument is a string. * @param arg Argument to check. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function isString(arg) { return typeof arg === 'string'; } exports.isString = isString; /** * Returns '1' if the given arg is truthy, '0' otherwise. * @param arg Argument to check. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function toBoolString(arg) { return arg ? '1' : '0'; } exports.toBoolString = toBoolString; /** * Returns true if the specified DeepL Authentication Key is associated with a free account, * otherwise false. * @param authKey The authentication key to check. * @return True if the key is associated with a free account, otherwise false. */ function isFreeAccountAuthKey(authKey) { return authKey.endsWith(':fx'); } exports.isFreeAccountAuthKey = isFreeAccountAuthKey; /** * Changes the upper- and lower-casing of the given language code to match ISO 639-1 with an * optional regional code from ISO 3166-1. * For example, input 'EN-US' returns 'en-US'. * @param langCode String containing language code to standardize. * @return Standardized language code. */ function standardizeLanguageCode(langCode) { if (!isString(langCode) || langCode.length === 0) { throw new errors_1.DeepLError('langCode must be a non-empty string'); } const [lang, region] = langCode.split('-', 2); return (region === undefined ? lang.toLowerCase() : `${lang.toLowerCase()}-${region.toUpperCase()}`); } exports.standardizeLanguageCode = standardizeLanguageCode; /** * Removes the regional variant from a language, for example inputs 'en' and 'en-US' both return * 'en'. * @param langCode String containing language code to convert. * @return Language code with regional variant removed. */ function nonRegionalLanguageCode(langCode) { if (!isString(langCode) || langCode.length === 0) { throw new errors_1.DeepLError('langCode must be a non-empty string'); } return langCode.split('-', 2)[0].toLowerCase(); } exports.nonRegionalLanguageCode = nonRegionalLanguageCode; /** * Joins given TagList with commas to form a single comma-delimited string. * @private */ function joinTagList(tagList) { if (isString(tagList)) { return tagList; } else { return tagList.join(','); } } /** * Validates and prepares URLSearchParams for arguments common to text and document translation. * @private */ function buildURLSearchParams(sourceLang, targetLang, formality, glossary, extraRequestParameters) { targetLang = standardizeLanguageCode(targetLang); if (sourceLang !== null) { sourceLang = standardizeLanguageCode(sourceLang); } if (glossary !== undefined && sourceLang === null) { throw new errors_1.DeepLError('sourceLang is required if using a glossary'); } if (targetLang === 'en') { throw new errors_1.DeepLError("targetLang='en' is deprecated, please use 'en-GB' or 'en-US' instead."); } else if (targetLang === 'pt') { throw new errors_1.DeepLError("targetLang='pt' is deprecated, please use 'pt-PT' or 'pt-BR' instead."); } const searchParams = new URLSearchParams({ target_lang: targetLang, }); if (sourceLang !== null) { searchParams.append('source_lang', sourceLang); } if (formality !== undefined) { const formalityStr = String(formality).toLowerCase(); searchParams.append('formality', formalityStr); } if (glossary !== undefined) { if (!isString(glossary)) { if (glossary.glossaryId === undefined) { throw new errors_1.DeepLError('glossary option should be a string containing the Glossary ID or a GlossaryInfo object.'); } glossary = glossary.glossaryId; } searchParams.append('glossary_id', glossary); } if (extraRequestParameters !== undefined) { for (const paramName in extraRequestParameters) { searchParams.append(paramName, extraRequestParameters[paramName]); } } return searchParams; } exports.buildURLSearchParams = buildURLSearchParams; /** * Validates and appends texts to HTTP request parameters, and returns whether a single text * argument was provided. * @param data Parameters for HTTP request. * @param texts User-supplied texts to be checked. * @return True if only a single text was provided. * @private */ function appendTextsAndReturnIsSingular(data, texts) { const singular = !Array.isArray(texts); if (singular) { if (!isString(texts) || texts.length === 0) { throw new errors_1.DeepLError('texts parameter must be a non-empty string or array of non-empty strings'); } data.append('text', texts); } else { for (const text of texts) { if (!isString(text) || text.length === 0) { throw new errors_1.DeepLError('texts parameter must be a non-empty string or array of non-empty strings'); } data.append('text', text); } } return singular; } exports.appendTextsAndReturnIsSingular = appendTextsAndReturnIsSingular; /** * Validates and appends text options to HTTP request parameters. * @param data Parameters for HTTP request. * @param options Options for translate text request. * Note the formality and glossaryId options are handled separately, because these options * overlap with the translateDocument function. * @private */ function validateAndAppendTextOptions(data, options) { if (!options) { return; } if (options.splitSentences !== undefined) { options.splitSentences = options.splitSentences.toLowerCase(); if (options.splitSentences === 'on' || options.splitSentences === 'default') { data.append('split_sentences', '1'); } else if (options.splitSentences === 'off') { data.append('split_sentences', '0'); } else { data.append('split_sentences', options.splitSentences); } } if (options.preserveFormatting !== undefined) { data.append('preserve_formatting', toBoolString(options.preserveFormatting)); } if (options.tagHandling !== undefined) { data.append('tag_handling', options.tagHandling); } if (options.outlineDetection !== undefined) { data.append('outline_detection', toBoolString(options.outlineDetection)); } if (options.context !== undefined) { data.append('context', options.context); } if (options.modelType !== undefined) { data.append('model_type', options.modelType); } if (options.nonSplittingTags !== undefined) { data.append('non_splitting_tags', joinTagList(options.nonSplittingTags)); } if (options.splittingTags !== undefined) { data.append('splitting_tags', joinTagList(options.splittingTags)); } if (options.ignoreTags !== undefined) { data.append('ignore_tags', joinTagList(options.ignoreTags)); } } exports.validateAndAppendTextOptions = validateAndAppendTextOptions; /** * Appends glossary dictionaries to HTTP request parameters. * @param data URL-encoded parameters for a HTTP request. * @param dictionaries Glossary dictionaries to append. * @private */ function appendDictionaryEntries(data, dictionaries) { dictionaries.forEach((dict, index) => { data.append(`dictionaries[${index}].source_lang`, dict.sourceLangCode); data.append(`dictionaries[${index}].target_lang`, dict.targetLangCode); data.append(`dictionaries[${index}].entries`, dict.entries.toTsv()); data.append(`dictionaries[${index}].entries_format`, 'tsv'); }); } exports.appendDictionaryEntries = appendDictionaryEntries; /** * Appends a glossary dictionary with CSV entries to HTTP request parameters. * @param data URL-encoded parameters for a HTTP request. * @param sourceLanguageCode Source language code of the dictionary. * @param targetLanguageCode Target language code of the dictionary. * @param csvContent CSV-formatted string containing the dictionary entries. * @private */ function appendCsvDictionaryEntries(data, sourceLanguageCode, targetLanguageCode, csvContent) { data.append('dictionaries[0].source_lang', sourceLanguageCode); data.append('dictionaries[0].target_lang', targetLanguageCode); data.append('dictionaries[0].entries', csvContent); data.append('dictionaries[0].entries_format', 'csv'); } exports.appendCsvDictionaryEntries = appendCsvDictionaryEntries; /** * Extract the glossary ID from the argument. * @param glossary The glossary as a string, GlossaryInfo, or MultilingualGlossaryInfo. * @private */ function extractGlossaryId(glossary) { return typeof glossary === 'string' ? glossary : glossary.glossaryId; } exports.extractGlossaryId = extractGlossaryId;