Dein Support-Widget sollte die Sprache der Seite lesen, nicht die des Browsers

Product

Bis zu dieser Woche wusste das Chat-Widget von Kookee nicht, in welcher Sprache es lief. Eine Website konnte eine locale übergeben, und das Widget reichte sie an die API weiter, aber die Buttons und das „How can we help?“ auf der Startseite blieben englisch, solange die Website nicht jeden Text selbst übersetzte. Manche Texte, etwa die Fehlermeldungen, ließen sich gar nicht übersetzen.

Eine Ebene tiefer war es schlimmer. Die API verglich Sprach-Tags als einfache Zeichenketten. Eine brasilianische Website, die pt-BR an ein Projekt übergab, dessen Hilfecenter auf pt geschrieben war, fand also keine Übereinstimmung und bekam die Standardsprache zurück.

Mehrsprachig wirkte das Widget nur, wenn die Website die halbe Arbeit erledigte und das Tag exakt richtig schrieb. Ich habe neu gebaut, wie es eine Sprache wählt und was es damit macht. Das ist heute live gegangen, und das sind die Regeln, auf die ich mich festgelegt habe.

Die Startseite des Widgets auf Russisch: Sie begrüßt den Besucher mit Namen, darunter eine Ankündigung, die es nur auf Englisch gibt, und drei Links

1. Zuerst entscheidet die Seite, dann der Browser

Die meisten Widgets lesen navigator.language, die Sprache des Browsers. Das ist das naheliegende Signal und meistens das falsche, denn es beschreibt den Computer des Besuchers, nicht die Seite, die er liest. Eine deutsche Entwicklerin auf einer englischen Doku-Seite bekäme ein deutsches Widget auf einer englischen Seite, das ihr Artikel anbietet, die es dann ohnehin auf Englisch lädt.

Die Seite gibt ihre Sprache bereits an: <html lang>. Die meisten Frameworks und CMS setzen das Attribut, und es ist eine Entscheidung des Website-Betreibers, keine Vermutung. Deshalb liest das Widget zuerst das. Der Browser hat nur dann etwas zu sagen, wenn die Seite nichts angibt, und nur für eine Sprache, die das Widget tatsächlich mitbringt. Fehlt beides, nimmt es die Standardsprache des Projekts.

Eine Website kann all das weiterhin mit data-locale überstimmen, in React mit locale. Und wenn ihr Sprachumschalter <html lang> ohne Neuladen ändert, bemerkt das Widget das und zieht mit.

2. Ein Sprach-Tag ist eine Familie, keine Zeichenkette

pt-BR, pt, PT-br und pt_BR bedeuten alle Portugiesisch, und ein Widget, das auf fremden Websites läuft, muss jede dieser Formen akzeptieren. Die Form mit Unterstrich kommt von Servern, die Locales nach POSIX-Art schreiben. Manche Tags enthalten mehr als eine Region, etwa ca-ES-valencia.

Das passiert an zwei Stellen. Das Widget bereinigt das Tag, bevor es etwas sendet: Es bringt es in die kanonische Form, behält Sprache und Region und verwirft alles, was gar kein Sprach-Tag ist, denn eine Anfrage, die die API ablehnt, ließe den Besucher mit einem kaputten Widget zurück. Der Server gleicht das Tag dann mit den Sprachen des Projekts ab: zuerst eine exakte Übereinstimmung, dann die Basissprache, dann ein paar Legacy-Codes wie nb und nn für Norwegisch und iw für Hebräisch.

Ein Tag, das zu nichts passt, bleibt, was es ist. Es wird nicht stillschweigend zu einer anderen Sprache. Es fällt genauso zurück wie eine fehlende Übersetzung.

3. Deine Texte fallen auf deine Sprache zurück, die des Widgets auf Englisch

Ein Widget zeigt zwei Arten von Text, und sie brauchen unterschiedliche Fallbacks.

Deine Inhalte (Hilfeartikel, Sammlungen, Neuigkeiten auf der Startseite) fallen auf die Standardsprache deines Projekts zurück. Ein englischer Artikel auf einer französischen Seite ist nicht ideal, aber besser als ein leerer Tab Hilfe, und genau so hat die API eine fehlende Übersetzung schon vorher behandelt.

Die eigenen Texte des Widgets fallen auf Englisch zurück. Das Widget bringt fünf Sprachen mit, und bei einer sechsten sind die Buttons englisch, bis du dem Widget mit labels eigene Texte gibst.

Eine italienische Seite in einem Projekt mit italienischen Artikeln zeigt also italienische Artikel mit englischen Buttons. Ich habe lange hin und her überlegt und es so gelassen. Ein gemischter Bildschirm zeigt ehrlich, was es gibt. Einen Artikel zu verstecken, weil das Widget kein italienisches Wort für „Back“ hat, wäre schlimmer.

Die Startseite im Bild oben zeigt beide Regeln auf einmal. Die Texte des Widgets und die Begrüßung, die die Seite in ihrem Code übergeben hat, sind russisch, und die Ankündigung, die es nur auf Englisch gibt, erscheint auf Englisch.

Bei der Arbeit daran sind zwei ältere Bugs an derselben Stelle aufgetaucht. Eine Liste konnte denselben Artikel zweimal zeigen, einmal in jeder Sprache, und bei einer Sprache ohne übersetzte Kategorien verlor der Tab Hilfe seine Sammlungen komplett. Beide sind behoben: Eine Liste enthält jeden Artikel jetzt nur noch in einer Version, und Kategorien fallen zurück wie alles andere.

4. In der Sprache antworten, in der der Besucher schreibt

Alles bis hierher ist eine Vermutung über den Besucher. Seine Nachricht ist keine. Wer auf einer Seite, die Englisch als Sprache angibt, auf Spanisch schreibt, will die Antwort auf Spanisch.

Deshalb antwortet der Assistent jetzt in der Sprache der letzten Nachricht des Besuchers und nimmt nur dann die Sprache des Widgets, wenn die Nachricht das nicht klärt, etwa bei „hi“ oder einem Produktnamen. Deine Artikel durchsucht er weiterhin in der Sprache, in der sie vorliegen, und zitiert sie so, wie sie sind.

Der Chat des Widgets auf Spanisch: eine Frage zu Rechnungen, die Suchen des Assistenten und seine Antwort auf Spanisch mit einem englischen Hilfeartikel als Quelle

5. Ein Sprachwechsel sollte die Unterhaltung nicht kosten

In einer Single-Page-App kann der Besucher die Sprache ohne Neuladen wechseln. Dann laden Startseite und Hilfe in der neuen Sprache neu, und die Unterhaltung bleibt, wo sie war.

Ein Artikel, der in diesem Moment offen ist, schließt sich, und der Besucher landet wieder in dessen Tab. Der Artikel wurde in der alten Sprache geladen, und seine Adresse kann sich von Sprache zu Sprache unterscheiden, deshalb lässt er sich nicht zuverlässig an Ort und Stelle neu laden. Ein Schritt zurück ist ein kleiner Preis, und die Unterhaltung bleibt unberührt.

Websites, deren Sprachumschalter <html lang> nicht anfasst, rufen stattdessen KookeeChat.setLocale('fr') auf.

6. Die Texte mit dem Widget ausliefern

Ich hätte die Übersetzungen über die API ausliefern können, eine Sprache pro Anfrage. Das Skript wäre kleiner geblieben, aber jeder Seitenaufruf hätte mit kurz aufblitzendem Englisch begonnen, während die Texte laden, und eine ältere Kopie des Widgets wäre an dem Tag kaputtgegangen, an dem ich einen Schlüssel umbenenne.

Deshalb stecken die fünf Sprachen in der Datei. Das kostet etwa 7 KB gzipped: Das Skript wuchs von 149,0 auf 156,2 KB. Eine sechste Sprache ist eine Datei und ein Release, und labels deckt alles dazwischen ab.

Was ich weggelassen habe

Eine Sprachauswahl im Widget. Deine Website hat schon einen Sprachumschalter, und ein zweiter in der Ecke der Seite wird ihm früher oder später widersprechen. Das Widget folgt deinem.

Übersetzte Texte im Dashboard. Titel, Begrüßung, Vorschläge und Links im Tab Anpassen werden in einer Sprache gespeichert. Eine mehrsprachige Website kann sie leer lassen, dann greifen die übersetzten Standardtexte des Widgets, oder sie pro Seite im Code setzen, wo sie Vorrang vor den gespeicherten Werten haben:

HTML
<script async src="https://kookee.dev/chat/latest.js"
  data-api-key="YOUR_API_KEY"
  data-locale="es"
  data-greeting="¿En qué podemos ayudarte?"></script>

Mehr als fünf Sprachen. Jeder neue Text im Widget braucht eine Übersetzung in jeder mitgelieferten Sprache, und ich habe lieber fünf, die ich prüfen kann, als dreißig, die ich nicht prüfen kann.

So bekommst du es

Das Script-Tag übernimmt das ohne Änderung an deiner Website. In React aktualisierst du auf @kookee/react 1.12.0 und @kookee/sdk 1.12.0. Wenn deine Seite <html lang> setzt, folgt das Widget dem bereits.

Eine Änderung im Verhalten: Eine Website, die keine Sprache setzt, bekommt jetzt die, die ihre Seite angibt. Soll das Widget englisch bleiben, egal was die Seite sagt, setz data-locale="en". Im Tab Installation auf der Seite Website-Widget gibt es dafür ein Auswahlfeld „Sprache“, das das Attribut für dich schreibt.

Das geöffnete Auswahlfeld Sprache im Tab Installation: Auto (Seite oder Browser), English, Русский, Español, Français und Português

Das Widget in der Sprache deiner Besucher anzeigen beschreibt alle Optionen, und Das Chat-Widget per JavaScript steuern erklärt setLocale(). Das gehostete Portal hat seine eigenen Sprachen später bekommen, siehe Ein mehrsprachiges Hilfecenter ohne leere Seiten.