Source: translation_api.js

/**
 * Standard JS interface to get translations
 * 
 * @author  andreask7 <andreasks7@users.noreply.github.com>
 * @license Unlicense <http://unlicense.org/>
 * @since   1.6.16-fork
 */

function deleteTranslation (){
	let frame = window.parent.frames['ro'];
	if (frame === undefined) 
		frame = window.opener;
	if ($('[name="WoTranslation"]', frame.document).val().trim().length) {
		$('[name="WoTranslation"]', frame.document).val('');
		frame.makeDirty();
	}
}

function addTranslation (s) {
	let frame = window.parent.frames['ro'];
	if (frame === undefined) 
		frame = window.opener;
	if (frame === undefined) {
		alert('Translation can not be copied!');
		return;
	}
	let word_trans = frame.document.forms[0].WoTranslation;
	if (typeof word_trans != 'object') {
		alert('Translation can not be copied!');
		return;
	}
	let oldValue = word_trans.value;
	if (oldValue.trim() == '') {
		word_trans.value = s;
		frame.makeDirty();
	} else {
		if (oldValue.indexOf(s) == -1) {
			word_trans.value = oldValue + ' / ' + s;
			frame.makeDirty();
		} else {
			if (confirm(
				'"' + s + '" seems already to exist as a translation.\n' + 
				'Insert anyway?'
				)) 
			{
				word_trans.value = oldValue + ' / ' + s;
				frame.makeDirty();
			}
		}
	}
}

function getGlosbeTranslation(text, lang, dest) {
	// Note from 2.9.0: make asynchronous if possible
	// Note: the Glosbe API is closed and may not be open again
	$.ajax({
		url: 'http://glosbe.com/gapi/translate?' + $.param({
			from: lang,
			dest: dest,
			format: "json",
			phrase: text,
			callback: "?"
		}),
		type:"GET",
		dataType: 'jsonp',
		jsonp: 'getTranslationFromGlosbeApi',
		jsonpCallback: 'getTranslationFromGlosbeApi',
		async:'true'
	});
}

function getTranslationFromGlosbeApi(data) {
	try {
		$.each(data.tuc,function(i,rows){
			if(rows.phrase){
				$('#translations')
				.append(
					'<span class="click" onclick="addTranslation(\'' + 
					rows.phrase.text + '\');">' + 
						'<img src="icn/tick-button.png" title="Copy" alt="Copy" />' + 
						' &nbsp; ' + rows.phrase.text + 
					'</span><br />'
				);
			} else if(rows.meanings){
				$('#translations')
				.append(
					'<span class="click" onclick="addTranslation(' + "'(" + 
					rows.meanings[0].text + ")'" + ');">' + 
						'<img src="icn/tick-button.png" title="Copy" alt="Copy" />' +
						' &nbsp; ' + "(" + rows.meanings[0].text + ")" + 
					'</span><br />'
				);
			}
		});
		if(!data.tuc.length){
			$('#translations')
			.before(
				'<p>No translations found (' + data.from + '-' + data.dest + ').</p>'
			);
			if(data.dest!='en' && data.from!='en'){
				$('#translations').attr('id','no_trans')
				.after(
					'<hr /><p>&nbsp;</p><h3><a href="http://glosbe.com/' + 
					data.from + '/en/' + data.phrase + '">Glosbe Dictionary (' + 
					data.from + '-en):  &nbsp; <span class="red2">' + 
					data.phrase + '</span></a></h3>&nbsp;<p id="translations"></p>'
				);
				getGlosbeTranslation(data.phrase,data.from,'en');
			} else $('#translations').after('<hr />');
		} else 
			$('#translations')
			.after('<p>&nbsp;<br/>' + data.tuc.length + ' translation' + 
			(data.tuc.length==1 ? '' : 's') + 
			' retrieved via <a href="http://glosbe.com/a-api" target="_blank">' + 
			'Glosbe API</a>.</p><hr />'
			);
	}
	catch(err) {
		$('#translations')
		.text(
			'Retrieval error. Possible reason: There is a limit of Glosbe API ' + 
			'calls that may be done from one IP address in a fixed period of time,' + 
			' to prevent from abuse.'
		)
		.after('<hr />');
	}
}

/**
 * Base function to get a translation from LibreTranslate.
 * 
 * @param {string}           text Text to translate
 * @param {string}           lang Source language (language of the text, two letters or "auto")
 * @param {string}           dest Destination language (two language)
 * @param {string|undefined} key  Optional API key
 * @param {string}           url  API URL
 * @returns {string} Translation
 */
async function getLibreTranslateTranslationBase(
	text, lang, dest, key="", url="http://localhost:5000/translate"
	) {
	const res = await fetch(
		url, 
		{
			method: "POST",
			body: JSON.stringify({
				q: text,
				source: lang,
				target: dest,
				format: "text",
				api_key: key
			}),
			headers: { "Content-Type": "application/json" }
		}
	);

	const data = await res.json();
	return data.translatedText;
}

/**
 * Main wrapper for LibreTranslate translation.
 * 
 * @param {URL}    libre_url URL of LibreTranslate.
 * @param {string} text      Text to translate
 * @param {string} lang      Source language (language of the text, two letters or "auto")
 * @param {string} dest      Destination language (two language)
 * @returns {string} Translation
 */
async function getLibreTranslateTranslation(libre_url, text, lang, dest) {
	const search_params = libre_url.searchParams;
	if (search_params.get("lwt_translator") != "libretranslate") {
		throw 'Translation API not supported: ' + 
		search_params.get("lwt_translator") + "!";
	}
	let translator_ajax;
	if (search_params.get("lwt_translator_ajax")) {
		translator_ajax = decodeURIComponent(search_params.get("lwt_translator_ajax"));
	} else {
		translator_ajax = libre_url.toString().replace(libre_url.search, '') + "translate";
	}
	return getLibreTranslateTranslationBase(
		text, lang, dest, key=search_params.get("lwt_key"), translator_ajax
	);
}