LibreTranslate open-source applicatie
LibreTranslate is een gratis en open source machine vertaling API, die volledig zelfgehost kan worden. In tegenstelling tot andere API’s, is het niet afhankelijk van propriëtaire providers zoals Google of Azure om vertalingen uit te voeren. In plaats daarvan wordt de vertaalmachine aangedreven door de open source Argos Translate bibliotheek.
In dit bericht leggen we uit hoe je LibreTranslate zelf kunt hosten met behulp van een Docker container. Tevens leggen we uit hoe je de te vertalen tekst bij de API van LibreTranslate (https://translate.adagia.eu) aanlevert om de tekst te laten vertalen en hoe je de tekst zichtbaar maakt. Hiervoor gebruiken we JavaScript.
Selfhosted API van LibreTranslate met Docker
Met een Docker hub image van LibreTranslate is een Docker container eenvoudig te installeren. Wil je Portainer via Docker installeren zonder terminal? Ben je de ingewikkelde handleidingen beu? Wil je iets snel en gemakkelijk? Lees dan deze installatiehandleiding van mariushosting om Portainer als chassis voor de Docker containers toe te passen.
Maak in Portainer een stack aan waarmee de image voor LibreTranslate wordt gedownload, de container wordt gebouwd en gestart. Om de taalbestanden te bewaren bij het stoppen en herstarten van de container, laat je door de stack een volume (map) aanmaken. Stel vervolgens een Reverse Proxy in onder de naam (voorbeeld) libretranslate.jouwdomein.nl. Stel een poortnummer in waarmee de container via de host (dat is de Synology NAS) verbinding maakt (hieronder: 5001, maar dit kan ook een ander vrij beschikbaar poortnummer zijn). Hiermee is de Docker container van LibreTranslate ook bereikbaar vanaf het www. Kies in de Reverse Proxy instellingen voor het https protocol.
Stack LibreTranslate
Met deze stack wordt LibreTranslate als Docker container geïnstalleerd. Het vertaalprogramma is vervolgens beschikbaar onder http://NAS-Synology-IP-adres:5001 of via de reverse proxy https://libretranslate.jouwdomein.nl.
version: "3.9" services: libretranslate: container_name: libretranslate hostname: libretranslate image: libretranslate/libretranslate build: context: . dockerfile: docker/Dockerfile restart: unless-stopped mem_limit: 2g cpu_shares: 2048 ports: - 5001:5000 tty: true healthcheck: test: ['CMD-SHELL', './venv/bin/python scripts/healthcheck.py'] environment: - LT_UPDATE_MODELS = true - LT_LOAD_ONLY = en,fr,nl,de,es,it,pt,se,dk,ru,jp,cn # naar wens - LT_FRONTEND_LANGUAGE_SOURCE = nl - LT_FRONTEND_LANGUAGE_TARGET = en - LT_SSL = true
volumes: - libretranslate_models:/home/libretranslate/.local:rw volumes: libretranslate_models:
Het installeren van de stack kan enkele minuten duren. Dit hangt af van de internetsnelheid en de prestaties van het type NAS model (rekenkracht). Na installatie ga je naar het (reverse proxy) host adres dat je hebt ingesteld bij de Reverse Proxy (libretranslate.jouwdomein.nl) en kom je uit op de landingspagina van LibreTranslate (zie voorbeeld hieronder).
Definieer het POST-verzoek
We kunnen de reverse proxy ook als API gebruiken wanneer we een vraag aan de API stellen om een tekst te vertalen. Dit doen we door middel van een POST verzoek. In het bericht over het maken van een spellingcontrole met LanguageTool hadden we al kennisgemaakt met GET en POST verzoeken. In dit bericht gaan we verder kennismaken met POST verzoeken. Zoals in het vorige bericht beschreven, vormt een POST request een manier om gegevens met behulp van internet naar een bestemming, in dit geval de API van translate.adagia.eu te verzenden. We stellen een POST verzoek in JavaScript op waarmee we de tekst laten controleren via de API van LibreTranslate. Wanneer we de API laten weten dat we informatie gaan verzenden, dan moeten we dus een POST-verzoek naar de API sturen. Nadat het verzoek is verwerkt, ontvangt de API de te vertalen gegevens zoals bedoeld.
De vraag is op welke manier komen de gegevens bij de API zodat deze het verzoek kan lezen en verwerken? Hiervoor maken we gebruik van onderstaande code in JavaScript en html code in WordPress. We willen gebruik maken van een tekstbox net zoals op de landingspagina van LibreTranslate. Er is een knop die bij het aanklikken de opdracht geeft om de tekst te vertalen en de vertaalde tekst zichtbaar te maken in een tweede tekstbox.
Html code
De eerste tekstbox maken we aan met de html tag <textarea>; de vertaalknop met de tag <button>. Door middel van het attribuut ‘id’ kan het javascript de tekst ophalen en deze naar de API brengen. De tweede tekstbox bevat de vertaalde tekst en een ander id zodat de vertaalde tekst hier kan worden geplakt. De Html code voegen we in op het tabblad ‘Tekst’ van de WordPress pagina (of het bericht); dus niet op het tabblad ‘Visueel’.
<textarea id="te_vertalen" spellcheck="false" cols="50" name="te_vertalen" rows="4" wrap="hard" placeholder="plak hier de te vertalen tekst" data-lt-tmp-id="lt-10567" data-gramm="false"></textarea>
<button id="vertaal" type="button">Vertaal de tekst</button>
<textarea id="vertaalde_tekst" cols="50" name="vertaalde_tekst" rows="4" wrap="hard"></textarea>
JavaScript code
De code is per regel toegelicht na de schuine strepen (forward slash) of tussen de karakters /* en */.
const knop_vertaal = document.getElementById("vertaal");
knop_vertaal.addEventListener("click", vertaal, {passive: true});
function vertaal(){
const tekst = document.getElementById("te_vertalen").value; // betreft tekst uit eerste tekstbox en definieert deze als variabele 'tekst'.
const vertaalde_tekst = document.getElementById("vertaalde_tekst"); // betreft vertaalde tekst uit tweede tekstbox en definieert deze als variabele 'vertaalde_tekst'.
let obj = { // definieert variabele 'obj' in het format van een dictionary dat de API nodig heeft om te weten hoe de vertaling moet plaatsvinden
'q': tekst,
'source': "auto",
'target': "en",
'format': 'text',
'api_key': ""
}
let xhr = new XMLHttpRequest(); // creëert een object 'xhr' met de methode XMLHttpRequest
/*
* Commentaar bij XMLHttpRequest
* Deze methode specificeert de belangrijkste parameters van het verzoek:
* HTTP-methode. Meestal "GET" of "POST."
* URL-adres: de URL van de site, server, API, etc.
* async: standaardwaarde is True. Wanneer deze op False is ingesteld, dan is het verzoek om chronologisch het verzoek af te handelen.
* Gebruiker, wachtwoord en wachtwoord voor basis HTTP auth (indien vereist).
* Houd er rekening mee dat de instructie 'open' nog niet de verbinding zelf opent. Het configureert alleen het verzoek, maar de netwerkactiviteit begint pas met de oproep van 'send'.
*/
xhr.open('POST', 'https://translate.adagia.eu/translate', true);
xhr.setRequestHeader('Content-Type', 'application/json');
/*
XMLHttpRequest maakt het zowel mogelijk om aangepaste headers te sturen of als headers te lezen vanuit het antwoord.
*/
/*
* Luister naar xhr gebeurtenissen voor het antwoord ('response'). De volgende drie 'events' zijn de meest gebruikte:
* load: wanneer het verzoek is voltooid (zelfs bij HTTP-status 400 of 500), en het antwoord volledig is gedownload.
* error: bij het totstandbrengen van het verzoek, bijvoorbeeld het netwerk ligt eruit of de URL is ongeldig.
* progress: dan controleert XMLHttpRequest periodiek tijdens het downloaden van de response hoeveel is gedownload.
* Een XMLHttpRequest object doorloopt de volgorde 0 → 1 → 2 → 3 → ... → 3 → 4 (ready statussen).
*/
/* Wat zijn de ready statussen?
* UNSENT = 0; // begintoestand
* OPENED = 1; // open aangeroepen
* Headers_RECEIVED = 2; // response headers ontvangen
* LOADING = 3; // respons is laden (een datapakket wordt ontvangen)
* DONE = 4; // verzoek voltooid
*
* Status 3 herhaalt zich telkens wanneer een datapakket via het netwerk wordt ontvangen.
* We kunnen de statussen volgen met behulp van readystatechange event:
*/
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
let jsonResponse = JSON.parse(xhr.responseText);
console.log(jsonResponse);
let vertaling = jsonResponse["translatedText"];
console.log(vertaling);
vertaalde_tekst.value = vertaling; // plaats het antwoord in de tweede tekstbox vertaalde_tekst.
} else {
console.error('Error:', xhr.statusText);
}
}
};
/*
* Zodra de server heeft gereageerd, kunnen we het resultaat ontvangen in de volgende xhr eigenschappen (status):
* HTTP-statuscode (een getal): 200, 404, 403, enzovoort, dit kan ook 0 zijn in geval van een niet-HTTP-fout.
* HTTP status bericht (een string): meestal OK voor 200, Niet Gevonden voor 404, Verboden voor 403 enzovoort.
*/
let requestBody = JSON.stringify(obj);
xhr.send(requestBody);
/*
* Verstuur de opdracht met xhr.send([body]). Deze methode opent de verbinding en stuurt het verzoek naar de server.
* De optionele instantieparameters bevatten de instructies zoals geformuleerd in variabele 'obj'.
* Sommige verzoekmethoden zoals GET hebben geen parameters.
* En sommige verzoekmethoden zoals POST gebruiken parameters om de gegevens naar de server te sturen.
*/
}
Aanpassingen aan functions.php
Nu is het zaak om de JavaScript code toe te voegen aan WordPress. We maken hiervoor gebruik van een gestandaardiseerde methode in WordPress die “enqueueing” heet om de benodigde bestanden klaar te zetten. We voegen deze niet toe aan de header, maar plaatsen deze zelf in een wachtrij. Allereerst registreren we het bestand zodat WordPress weet dat het bestand er staat. Vervolgens plaatsen we het bestand daadwerkelijk in de wachtrij waardoor het in de header of net voor de laatste body tag geplaatst wordt.
Eerst slaan we de bovenstaande JavaScript code op in een bestand met de extensie *.js. Vervolgens slaan we dit op in de map /web/wordpress/wp-includes/js. We kunnen ook een andere map kiezen in de wordpress map. Belangrijk is om te verwijzen naar de map bij het ‘enqueuen’ (in de wachtrij plaatsen) van het javascript bestand. Als derde stap openen we het bestand functions.php. In een het bericht over het werken met een child theme zijn we ingegaan op het gebruik van functions.php om code (snippets) toe te voegen waarmee we de website op maat kunnen maken naar onze eigen behoefte. We voegen de volgende code snippet toe aan functions.php.
/**
* Script voor libretranslate in de enqueue wachtrij zetten
*/
function libretranslate() {
if (is_single ('5816'))
{
wp_enqueue_script('libretranslate', site_url().'/wp-includes/js/eigencode/libretranslate.js', array(), '', true);
}
}
add_action('wp_enqueue_scripts', 'libretranslate');
De ‘if conditie’ instrueert WordPress om de code snippet alleen toe te voegen aan deze pagina over LibreTranslate. Het getal ‘5816’ is te vinden in de url-link van de pagina tijdens het bewerken van de pagina in WordPress.
Het resultaat
Voer in de tekstbox de tekst die je wilt vertalen naar het Engels. Invoertaal wordt automatisch gedetecteerd.
Tot slot
Voor het gebruik van andere invoertalen, ga naar translate.adagia.eu.
Het script voor het indienen van vertaalverzoeken naar de API van translate.adagia.eu vind je hier.
Wil je meer weten over het opstellen van POST verzoeken op een API, dan kun je daarover meer lezen in het bericht over Spellingcontrole met LanguageTool.