API-Dokumentation

Nexling übersetzt eine Website mit einem einzigen Script-Tag — ohne Änderungen am HTML. Wer tiefer gehen will, findet hier zusätzlich eine öffentliche REST-API, einen Export für die eigene Build-Pipeline und Webhooks.

Schnellstart

Fügen Sie diese eine Zeile in den <head> Ihrer Seite ein. Ersetzen Sie YOUR-PROJECT-ID durch die Projekt-ID aus den Projekteinstellungen.

<script src="https://nexling.app/nl.js"
        data-project="YOUR-PROJECT-ID"></script>

Mehr ist nicht nötig. Beim Laden der Seite passiert Folgendes:

  1. nl.js ermittelt die Sprache der Besucherin — erzwungene Sprache, zuletzt gewählte Sprache, Browsersprache, dann Standardsprache.
  2. Die Übersetzungen für diese Sprache werden geladen und im Speicher gehalten.
  3. Jeder Textknoten im DOM wird ersetzt, ebenso placeholder, alt, title und aria-label.
  4. Ein MutationObserver übersetzt auch später nachgeladene Inhalte — React, Vue und andere SPAs funktionieren ohne Zusatzkonfiguration.
Die Originaltexte bleiben erhalten. Beim Sprachwechsel wird immer aus dem Original übersetzt, nie aus einer bereits übersetzten Fassung — dadurch gibt es keine Qualitätsverluste durch mehrfaches Übersetzen.

Mit allen gängigen Optionen

<script src="https://nexling.app/nl.js"
        data-project="YOUR-PROJECT-ID"
        data-default-language="de-CH"
        data-switcher="true"
        data-position="bottom-right"></script>

Ausprobieren

Die öffentlichen Endpunkte benötigen keinen Schlüssel. Geben Sie Ihre Projekt-ID ein und sehen Sie die echte Antwort — die Abfrage läuft direkt aus Ihrem Browser.

Script-Attribute

Alles wird direkt am <script>-Tag konfiguriert.

AttributStandardBeschreibung
data-projectErforderlich. Die Projekt-ID aus den Projekteinstellungen.
data-default-languageenSprache, in der die Seite geschrieben ist — die Ausgangssprache.
data-current-languageErzwingt eine Sprache und überschreibt die gespeicherte Auswahl. Nützlich, wenn Sie die Sprache serverseitig bestimmen.
data-modeautoauto übersetzt die ganze Seite. manual übersetzt nur Elemente mit data-nl-Attributen.
data-switchertrueBlendet den Sprachumschalter aus, wenn auf false gesetzt.
data-positionbottom-rightPosition des Umschalters: bottom-right, bottom-left, top-right, top-left.
data-switcher-targetCSS-Selektor. Rendert den Umschalter in Ihr eigenes Element statt schwebend über der Seite.
data-api-urlhttps://nexling.appÜberschreibt die API-Basis-URL — nötig, wenn Sie nl.js über ein eigenes CDN ausliefern.
data-debugfalseSchreibt ausführliche Meldungen in die Browser-Konsole.
Der Umschalter läuft in einem Shadow DOM. Ihre Seiten-CSS kann ihn nicht versehentlich verändern, und er verändert Ihre Seite nicht.

Element-Attribute

Im Automatikmodus brauchen Sie diese nicht. Sie sind dann sinnvoll, wenn Sie eine bestimmte Stelle über einen festen Schlüssel ansteuern oder einen Bereich schützen wollen.

<!-- Text content -->
<h1 data-nl="page_title">Willkommen</h1>

<!-- Attributes -->
<input data-nl-placeholder="search_hint" placeholder="Suchen…">
<img  data-nl-alt="logo_alt" alt="Firmenlogo">
<a    data-nl-title="home_tip" title="Zur Startseite">Home</a>
<button data-nl-label="close_btn" aria-label="Schliessen">×</button>

<!-- Raw HTML (use only with trusted content) -->
<div data-nl-html="rich_intro"><b>Hallo</b> Welt</div>

<!-- Never translate this subtree -->
<pre data-nl-skip>const x = "Speichern";</pre>
AttributWirkung
data-nlTextinhalt des Elements
data-nl-htmlinnerHTML — nur mit vertrauenswürdigem Inhalt verwenden
data-nl-placeholderplaceholder von Eingabefeldern
data-nl-altalt von Bildern
data-nl-titletitle-Attribut
data-nl-labelaria-label
data-nl-skipSchliesst das Element und alle Kindelemente von der Übersetzung aus
Setzen Sie data-nl-skip auf Codebeispiele, Benutzernamen, Bestellnummern und alles, was wörtlich stehen bleiben muss. Ohne diesen Hinweis kann eine KI-Übersetzung solche Werte verändern.

Die älteren data-lf-*-Attribute aus lf.js funktionieren weiterhin. Neue Projekte sollten data-nl-* verwenden.

JavaScript-API

Nach dem Laden steht window.Nexling global zur Verfügung. window.LocaleFlow bleibt als Alias erhalten.

// Switching
await Nexling.setLanguage('fr-CH');
Nexling.getLanguage();        // → 'fr-CH'
Nexling.getLanguages();       // → [{ code, name, isSource }, …]

// Keyed lookup
Nexling.t('save_button');              // → 'Speichern'
Nexling.t('greeting', { name: 'Ana' }); // → 'Hallo, Ana!'

// Re-applying
Nexling.refresh();          // re-apply current language, no refetch
Nexling.init();             // re-initialise (SPA route changes)
Nexling.restoreOriginal();  // put the original text back
Nexling.restoreToSource('de-CH');

// Events
Nexling.on('ready',       () => console.log('translated'));
Nexling.on('langChanged', code => console.log('now', code));
Nexling.on('error',       err => console.warn(err));
Nexling.off('ready', handler);
MethodeBeschreibung
setLanguage(code)Wechselt die Sprache und übersetzt die Seite neu. Die Auswahl wird pro Projekt gespeichert.
getLanguage()Aktuell aktiver Sprachcode.
getLanguages()Alle für das Projekt konfigurierten Sprachen.
t(key, vars?)Übersetzung zu einem Schlüssel. vars ersetzt Platzhalter im Text.
refresh()Wendet die aktuelle Sprache erneut an, ohne neu zu laden.
init()Initialisiert neu — nach Routenwechseln in einer SPA.
restoreOriginal()Stellt sämtliche Originaltexte wieder her.
restoreToSource(code)Zurück zur Ausgangssprache, ohne API-Aufruf.
on(event, fn) / off(event, fn)Event-Listener registrieren beziehungsweise entfernen.

Single-Page-Anwendungen

Der MutationObserver deckt die meisten Fälle bereits ab. Wenn Ihr Router grosse Teile des DOM auf einmal austauscht, rufen Sie nach der Navigation init() auf.

// React Router / Vue Router — re-scan after each navigation
router.afterEach(() => Nexling.init());

Events

EventWird ausgelöst
readyDie erste Übersetzung ist abgeschlossen und die Seite vollständig sichtbar.
langChangedDie Sprache wurde gewechselt. Der Sprachcode wird übergeben.
errorÜbersetzungen konnten nicht geladen oder angewendet werden.

REST-API

Diese Endpunkte liefert nl.js selbst an. Sie sind öffentlich, benötigen keinen Schlüssel und erlauben Cross-Origin-Zugriff — Sie können sie also direkt aus dem Browser aufrufen. Es werden ausschliesslich Übersetzungen ausgeliefert, keine Kontodaten.

GET /MyApi/languages/{projectId}

Alle für das Projekt konfigurierten Sprachen, inklusive Kennzeichnung der Ausgangssprache.

curl https://nexling.app/MyApi/languages/YOUR-PROJECT-ID
[
  { "code": "de-CH", "name": "German (Switzerland)", "isSource": true  },
  { "code": "fr-CH", "name": "French (Switzerland)",  "isSource": false },
  { "code": "it-CH", "name": "Italian (Switzerland)", "isSource": false }
]
GET /MyApi/translates/{projectId}/{lang}

Flache Zuordnung von Schlüssel zu Übersetzung — passend, wenn Sie mit eigenen Schlüsseln arbeiten.

curl https://nexling.app/MyApi/translates/YOUR-PROJECT-ID/fr-CH
{
  "save_button": "Enregistrer",
  "learn_more":  "En savoir plus"
}
GET /MyApi/map/{projectId}/{lang}

Die angereicherte Fassung, die nl.js im Automatikmodus verwendet. byKey funktioniert wie oben; byText ordnet den sichtbaren Originaltext der Übersetzung zu und nennt zusätzlich den Elementtyp, damit gleiche Wörter je nach Kontext unterschiedlich übersetzt werden können.

curl https://nexling.app/MyApi/map/YOUR-PROJECT-ID/fr-CH
{
  "byKey": {
    "learn_more": "En savoir plus"
  },
  "byText": {
    "Mehr erfahren": { "value": "En savoir plus", "context": "a" }
  }
}
byText enthält auch die Fassungen der übrigen Sprachen. Dadurch findet eine französische Ausgangsseite dieselbe Übersetzung wie eine deutsche — Sie müssen kein separates Projekt pro Ausgangssprache anlegen.

Export für CI/CD

Für Build-Pipelines gibt es einen Endpunkt mit Schlüssel, der Übersetzungen als Datei liefert. Erzeugen Sie den Schlüssel in den Projekteinstellungen — er wird nur einmal angezeigt und bei uns ausschliesslich als Hash gespeichert.

GET /api/export/json/{langCode}
curl -H "X-Api-Key: nxl_your_key_here" \
     https://nexling.app/api/export/json/fr-CH
GET /api/export/languages
curl -H "X-Api-Key: nxl_your_key_here" \
     https://nexling.app/api/export/languages

Beispiel für einen Build-Schritt

# Pull the latest translations during a build
for LANG in de-CH fr-CH it-CH; do
  curl -sf -H "X-Api-Key: $NEXLING_API_KEY" \
       "https://nexling.app/api/export/json/$LANG" \
       -o "locales/$LANG.json"
done
Der Schlüssel gehört in die Secrets Ihrer Pipeline, nicht ins Repository. Die öffentliche Projekt-ID wird hier bewusst nicht akzeptiert — dieser Endpunkt verlangt immer einen echten Schlüssel.

Webhooks

Nexling kann Ihren Server benachrichtigen, sobald sich Übersetzungen ändern — etwa um einen Rebuild anzustossen oder einen Cache zu leeren. Endpunkte verwalten Sie in den Projekteinstellungen.

EventWird ausgelöst
translation.completedEine Massenübersetzung per KI ist fertig.
translation.updatedÜbersetzungen wurden bearbeitet oder importiert. Schnelle Einzeländerungen werden zusammengefasst.
terms.importedNeue Texte kamen über Crawler, Autopilot oder Datei-Import hinzu.
project.language.addedDem Projekt wurde eine Sprache hinzugefügt.
export.downloadedEin Export wurde heruntergeladen.

Aufbau der Anfrage

POST /your-endpoint
X-Nexling-Event: translation.completed
X-Nexling-Signature: sha256=9f86d081884c7d65…
User-Agent: Nexling-Webhooks/1.0

{
  "event": "translation.completed",
  "projectId": "YOUR-PROJECT-ID",
  "timestamp": "2026-09-07T14:22:31Z",
  "data": {
    "languageCode": "fr-CH",
    "translatedCount": 128,
    "totalTerms": 130,
    "engine": "claude-haiku",
    "coveragePercent": 98.5
  }
}

Signatur prüfen

Jede Anfrage wird mit HMAC-SHA256 über den rohen Body signiert, mit dem Secret Ihres Endpunkts als Schlüssel. Prüfen Sie die Signatur, bevor Sie den Inhalt verarbeiten — sonst kann jede beliebige Person Ereignisse an Ihren Endpunkt senden.

const crypto = require('crypto');

function isFromNexling(rawBody, header, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(rawBody)          // the raw body, before JSON.parse
    .digest('hex');

  // Constant-time compare — never use ===
  return crypto.timingSafeEqual(
    Buffer.from(expected), Buffer.from(header)
  );
}
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var expected = "sha256=" + Convert.ToHexString(
    hmac.ComputeHash(Encoding.UTF8.GetBytes(rawBody))).ToLowerInvariant();

var ok = CryptographicOperations.FixedTimeEquals(
    Encoding.UTF8.GetBytes(expected),
    Encoding.UTF8.GetBytes(signatureHeader));
Signieren Sie den Body genau so, wie er angekommen ist — vor dem Parsen. Schon ein erneutes Serialisieren verändert Leerzeichen und die Signatur stimmt nicht mehr. Vergleichen Sie zeitkonstant, nicht mit ===.
Zustellung erfolgt ohne Blockieren, mit 5 Sekunden Zeitlimit. Nach 10 fehlgeschlagenen Versuchen in Folge wird ein Endpunkt automatisch deaktiviert; beim Wiedereinschalten wird der Zähler zurückgesetzt. Jeder Versuch ist im Verlauf des Endpunkts einsehbar.

Exportformate

Innerhalb der Anwendung lassen sich Übersetzungen pro Sprache in verschiedenen Formaten herunterladen. Programmatisch steht JSON über den oben beschriebenen CI/CD-Endpunkt zur Verfügung.

FormatTypisch für
JSONWeb-Frontends, i18next, eigene Pipelines
POgettext — WordPress, Laravel, Python
XLIFFÜbersetzungsbüros und CAT-Werkzeuge
RESX.NET-Anwendungen
strings.xmlAndroid
.stringsiOS und macOS
CSVTabellenkalkulation, manuelle Durchsicht

Limits & Fehler

EndpunktLimitGilt pro
/MyApi/*60 Anfragen / MinuteIP-Adresse
/api/export/*30 Anfragen / MinuteAPI-Schlüssel

Wird ein Limit überschritten, antwortet die API so:

HTTP/1.1 429 Too Many Requests
Retry-After: 60

{ "error": "Rate limit exceeded", "retryAfter": 60 }
nl.js behandelt das selbst: Die Seite wird sofort in der Ausgangssprache angezeigt und nach der in Retry-After genannten Zeit einmal erneut versucht. Besucherinnen sehen nie eine leere Seite — im schlechtesten Fall den Originaltext.

Weitere Statuscodes

CodeBedeutung
400Projekt-ID ist keine gültige GUID.
401X-Api-Key fehlt oder ist ungültig (nur CI/CD-Export).
404Projekt oder Sprache nicht gefunden.
429Limit erreicht — siehe Retry-After.

Noch offene Fragen?

Schreiben Sie an info@nexling.ch — am besten mit Ihrer Projekt-ID, dann können wir direkt nachsehen.