Locales
Titel und Beschreibung jeder Regel sowie Zusammenfassung und Hinweis jedes Vorkommens werden über ein schlüsselbasiertes Wörterbuch lokalisiert, nicht pro Sprache fest einprogrammiert.
Aktuelle Abdeckung der Locales
| Locale | Datei | Schlüssel | Unübersetzt |
|---|---|---|---|
en (English) | src/i18n/en.json | 1334 | — (der kanonische Satz bzw. Fallback) |
de (German) | src/i18n/de.json | 1334 | 0 |
es (Spanish) | src/i18n/es.json | 1334 | 0 |
fr (French) | src/i18n/fr.json | 1334 | 0 |
ja (Japanese) | src/i18n/ja.json | 1334 | 0 |
„Unübersetzt“ zählt Werte, die Zeichen für Zeichen dem englischen Text entsprechen, außer Wörtern, die in einer Sprache zu Recht gleich sind: französisch Orientation, Interruptions und Occurrences, deutsch Frame, Frames und Element, spanisch Selector. Diese sind als solche aufgeführt, jeweils mit dem englischen Text, gegen den sie geprüft wurden, und zählen als übersetzt. Ändert sich das Englische, gilt der Eintrag nicht mehr, und der String zählt als unübersetzt, bis ihn jemand erneut prüft. Ein englisches Wort in einem sonst übersetzten Satz sieht die Zählung nicht; das findet man beim Lesen des Textes, und in den Locales oben ist keines mehr übrig. Ebenso wenig misst sie, ob eine Übersetzung korrekt ist oder die in einer Sprache üblichen Begriffe der Barrierefreiheit verwendet; das kann nur jemand beurteilen, der die Sprache liest.
Abdeckung aus dem Paket lesen
Dieselben Zahlen sind zur Laufzeit verfügbar, aus den Wörterbüchern, die das installierte Paket mitbringt. Ein Tool oder eine Dokumentationsseite kann sie also anzeigen, ohne das Repository auszuchecken:
const { getLocaleCoverage } = require('@surea11y/core');getLocaleCoverage();// {// sourceLocale: 'en',// totalKeys: 1334,// locales: [// { locale: 'de', total: 1334, translated: 1334, missing: 0, orphaned: [], percent: 100 },// { locale: 'es', total: 1334, translated: 1334, missing: 0, orphaned: [], percent: 100 },// ...// ]// }
Pro Locale ist total die Zahl der englischen Schlüssel, an der sie gemessen wird, translated, wie viele ihrer Werte sich vom Englischen unterscheiden oder als zu Recht gleich aufgeführt sind, missing, wie viele Schlüssel ihr fehlen (sie erscheinen auf Englisch), und orphaned die Schlüssel, die sie hat, das Englische aber nicht. total - translated ist die Spalte „Unübersetzt“ oben, fehlende Schlüssel eingeschlossen. Schlüssel, die ein Profil bewusst aus einer Locale weglässt, werden nicht gezählt. Der Abdeckungsbericht des Repositorys und diese Funktion teilen sich eine Implementierung und stimmen daher immer überein; der Bericht zählt die Wörterbücher von core und die jedes Profils getrennt, diese Funktion das zusammengeführte Wörterbuch, das ein Scan verwendet. Sie ist ein unterstützter Export (API_STABILITY.md, Erweiterungspunkte).
Locale-Dateien sind einfaches JSON: eine flache Zuordnung von Schlüssel zu übersetztem String, in derselben Schlüsselreihenfolge wie en.json. Sonst steht nichts darin, eine Sprache beizutragen heißt also, Text zu bearbeiten, ohne Code anzufassen.
Jede Locale enthält jeden Schlüssel, den en.json hat. Dafür sorgt npm run i18n:sync: Nach jeder Änderung an en.json ausgeführt, schreibt es jede nicht-englische Locale-Datei passend um. Es ergänzt neue Schlüssel, entfernt Schlüssel, die en.json nicht mehr hat, und lässt vorhandene Übersetzungen unverändert. Ein neu ergänzter Schlüssel wird mit dem englischen Text vorbelegt und gilt als unübersetzt, bis ihn jemand ersetzt.
Eine Locale auswählen
runDomRulesInPage(url, null, { locale: 'fr' }, null);
Ohne Angabe ist der Standard 'en'. Jeder String wird akzeptiert; eine unbekannte Locale ist nie ein Fehler.
Wie eine Locale gewählt wird
Es passieren zwei Dinge, in dieser Reihenfolge. Die meisten Missverständnisse entstehen, wenn man sie verwechselt, darum werden sie getrennt beschrieben.
Schritt 1: ein Wörterbuch wählen (einmal pro Scan)
- Das Wörterbuch verwenden, das zu Ihrem Code passt.
defindetde.json. Groß-/Kleinschreibung spielt keine Rolle:pt-br,pt-BRundPT-BRfinden allept-BR.json. - Andernfalls alles nach dem ersten
-abschneiden und das versuchen.de-DEfindetde.json, ebensode-AT. - Andernfalls Englisch verwenden.
Eine de-DE.json brauchen Sie also nur, wenn sich Deutsch in Österreich und Deutschland tatsächlich unterschiedlich lesen soll. Liefern Sie de.json aus, ist jede deutsche Variante abgedeckt.
Schritt 2: jeden String auflösen (pro String)
Innerhalb des gewählten Wörterbuchs wird jeder String einzeln nachgeschlagen:
- Den Wert des Schlüssels aus dem gewählten Wörterbuch nehmen.
- Fehlt dieser Schlüssel, den englischen nehmen.
- Fehlt er auch im Englischen (was bei einem eingebauten Schlüssel nicht vorkommen sollte, bei einem selbst angelegten aber schon), den wörtlichen Text verwenden, den die Regel selbst mitbringt.
Das Ergebnis ist nie leer, nie undefined und nie ein geworfener Fehler. Eine halb fertige Übersetzung erscheint in Ihrer Sprache, wo es sie gibt, und überall sonst auf Englisch.
Erkennen, welche Locale Sie tatsächlich bekommen haben
Der sanfte Fallback hat einen Nachteil: Fordern Sie eine Sprache an, die der Build nicht enthält, bekommen Sie einwandfreies Englisch zurück, ohne dass die Strings darauf hinweisen. Jedes Ergebnis meldet die Auflösung deshalb einmal, ganz oben:
"engine": {"tag": "a11ycore","schemaVersion": "1.0.0","locale": { "requested": "ko", "resolved": "en", "reason": "unknown-locale" }}
requested ist das, was Sie angefordert haben (nach dem Trimmen; en, wenn Sie nichts oder keinen String übergeben haben), resolved ist das verwendete Wörterbuch, und reason ist einer dieser Werte:
| reason | Bedeutung |
|---|---|
ok | Sie haben genau das bekommen, was Sie angefordert haben, und dieses Wörterbuch enthält jeden Schlüssel. |
primary-subtag | Ihr Code enthielt einen Subtag ohne eigenes Wörterbuch, deshalb wurde die Basissprache verwendet: Sie haben de-DE angefordert und de bekommen. Normal und erwartet; es gibt nichts zu beheben. Ein reiner Unterschied in der Groß-/Kleinschreibung fällt nicht darunter: DE meldet ok. |
dictionary-not-loaded | Das Projekt liefert diese Sprache aus, aber diese Kopie der Engine enthält sie nicht, und es wurde auch keine übergeben. In der Praxis: das Standalone-Browser-Bundle ohne die zugehörige Locale-Datei. |
unknown-locale | Das Projekt hat überhaupt keine solche Übersetzung, deshalb wurde Englisch verwendet. ko und pt-BR landen derzeit beide hier. |
partial-dictionary | Das Wörterbuch wurde verwendet, aber ihm fehlen einige Schlüssel, deshalb sind diese einzelnen Strings auf Englisch zurückgefallen. |
Behandeln Sie die Liste als offen: Ein späteres Release kann einen Wert hinzufügen. Prüfen Sie also auf die Werte, die Sie interessieren, und lassen Sie den Rest in einen Standardfall laufen.
Wenn Sie eine bestimmte Sprache brauchen, ist requested !== resolved die Bedingung, die Sie in der CI prüfen. Beachten Sie, dass sie auch im harmlosen Fall primary-subtag zutrifft; prüfen Sie also auf reason === 'unknown-locale' || reason === 'dictionary-not-loaded', wenn Ihnen ein Treffer auf die Basissprache genügt. Siehe das Ausgabeschema für die Stelle des Felds im Ergebnis und API_STABILITY.md dafür, was dazu garantiert ist.
Wo die Wörterbücher liegen
Welche Sprachen verfügbar sind, hängt davon ab, wie Sie die Engine laden.
| Wie Sie sie laden | Was Sie bekommen |
|---|---|
require('@surea11y/core') | Jede Locale, fest eingebaut. Nichts zu konfigurieren. |
| Ein Binding (Playwright, Cypress, …) | Jede Locale, fest eingebaut. Nichts zu konfigurieren. |
surea11y.browser.js | Englisch. Laden Sie für alles andere danach surea11y.i18n.<locale>.js. |
Das Bundle ist aufgeteilt, weil es über das Netzwerk an jede Seite geht, die es nutzt, und keine Seite alle Sprachen braucht. Englisch inline und den Rest optional zu halten, hält die anderen Sprachen aus dem Download heraus und verhindert, dass er mit jeder neuen Sprache wächst. Jede Zusatzdatei, surea11y.i18n.<locale>.js, ist etwa so groß wie der englische Text, den sie ersetzt (derzeit 200 bis 250 KB), und eine Seite lädt nur die, die sie nutzt. Sonst ändert sich nichts: Das Node-Paket und die Bindings sind nicht betroffen.
<script src="surea11y.browser.js"></script><script src="surea11y.i18n.ja.js"></script><script>const result = a11ycore.runa11yCoreInPage(location.href, null, { locale: 'ja' }, null);</script>
Fordern Sie eine Sprache an, deren Datei Sie nicht geladen haben, bekommen Sie Englisch, mit engine.locale.reason auf dictionary-not-loaded. Das unterscheidet sich von unknown-locale, was bedeutet, dass das Projekt überhaupt keine solche Übersetzung hat.
In Node ist dieselbe Zusatzdatei ein Modul: require('@surea11y/core/i18n/de') gibt { locale, messages } zurück (locale ist 'de', messages die flache Zuordnung von Schlüssel zu Text), ohne dass das Bundle nötig ist.
Die Meldungen eines Packs stehen in dessen eigenen Wörterbüchern, die das Pack pro Locale auflistet; in einer Locale, für die das Pack kein Wörterbuch hat, erscheinen seine Meldungen auf Englisch.
Die Prüf-Wörterbücher
Die Schritte, die einer Person sagen, wie sie einen offenen Befund beantwortet (howToCheck, siehe das Ausgabeschema), stehen in eigenen Wörterbüchern, in denselben fünf Locales. Sie sind von den Wörterbüchern der Engine getrennt, damit die Schritte nie ins Bundle oder in eine Seite gelangen: Sie werden nach dem Scan hinzugefügt, in Node oder durch Code, der sie importiert. Ab core 1.14.0.
| Wer sie liest | Wie |
|---|---|
runDomRulesInPage, addHowToCheck, howToCheckFor, renderHtmlReport | Aus dem installierten Paket, gesucht nach der Locale in Kleinbuchstaben (fr-ca, dann fr), Englisch zuletzt. |
| Code, der im Browser läuft (eine Cypress-Spec) | applyHowToCheck(result, { en, fr }) aus @surea11y/core/how-to-check, mit den Wörterbüchern, die er als @surea11y/core/review/<locale> importiert. |
a11ycore.openReport(result) im Browser-Bundle | Neben dem Bundle abgerufen oder als { reviewDictionaries } übergeben. |
Ein Schritt, der einer Locale fehlt, erscheint auf Englisch, wie eine Meldung. Die eigenen Schritte einer Pack-Regel sind in jeder Locale englisch. getLocaleCoverage() zählt diese Wörterbücher nicht. Die Schritte tragen keine Schlüssel; um sie in einer anderen Locale zu zeigen, fügen Sie sie erneut hinzu:
const { addHowToCheck } = require('@surea11y/core');const inFrench = addHowToCheck(result, { locale: 'fr' });
Ein eigenes Wörterbuch übergeben
engineOptions.messages akzeptiert { [locale]: { key: value } } und hat Vorrang vor allem, was eingebaut ist oder aus einer separaten Datei geladen wird. Nützlich, um eine Handvoll Strings zu überschreiben, oder für eine Sprache, die Sie intern pflegen:
runDomRulesInPage(url, null, {locale: 'de',messages: { de: { img_altPresent_title: 'Eigener Text' } }}, null);
Schlüssel, die Sie nicht übergeben, fallen normal zurück; eine teilweise Überschreibung ist also kein Problem.
Sprachspezifischer Abgleich
Fünf Regeln beurteilen Text anhand bekannter Formulierungen und bringen daher neben Meldungen auch Wortlisten mit: link-name-quality („click here“, „こちら“), heading-quality („Untitled“, „見出し“), form-control-label-quality („Label“, „入力欄“), page-title-patterns („Home“, „トップページ“) und media-alternative-transcript-evidence („transcript“, „文字起こし“). Jede Liste deckt en, de, es, fr und ja ab. Die Regel skip-link erkennt Skip-Link-Formulierungen in denselben fünf Sprachen.
Englisch wird immer geprüft. Die Liste der eigenen Sprache des Elements, aus dem nächsten lang-Attribut (bei einem Seitentitel dem des <html>-Elements), kommt hinzu. link-name-quality prüft die Listen aller Sprachen, wo im Baum über dem Link nirgends ein lang angegeben ist, da der Link in jeder davon sein kann. Alle Listen überall zu prüfen, würde Wörter melden, die in einer Sprache generisch und in einer anderen ein echter Name sind, etwa „Suite“ oder „Plus“ auf einer englischen Seite. Transkript-Wörter sind die Ausnahme: Sie sind in jeder Sprache eindeutig, und eine Seite kann ein Transkript in einer anderen Sprache verlinken, daher werden sie immer alle geprüft. Text wird zuerst nach NFKC normalisiert, sodass auch Formen voller Breite wie „見出し2“ erkannt werden.
page-title-patterns zählt außerdem jedes chinesische, japanische oder koreanische Zeichen doppelt, wenn es entscheidet, ob ein Titel zu kurz ist, da „お問い合わせ“ mit sechs Zeichen ein vollständiger Titel ist.
Wo Schlüssel verwendet werden
Mehrere Schlüssel-Namensräume, alle auf dieselbe Weise aufgelöst:
- Regelebene:
meta.i18n.titleKey/meta.i18n.descriptionKeylösentitle/descriptioneiner Regel in jedem Eintrag vonchecksResults[]auf. - HTML-Bericht: Die
report_*-Schlüssel beschriften die Seite, die@surea11y/core/reporterzeugt — Überschriften, Tabellenspalten, Namen von Ergebnissen und Schweregraden, die Kopfzeile, die Seitennavigation. Der Bericht liest sie in der Locale, auf die der Scan aufgelöst wurde; ein Wörterbuch übersetzt also auch den Bericht. - Auf Ebene der zusammengesetzten Regeln:
title/descriptionjeder Zusammenfassung inrulesResults[], mit dem veröffentlichten Namen des Erfolgskriteriums in jeder Sprache. - Vorkommensebene:
i18n.summaryKey/i18n.hintKey, miti18n.paramsfür die Interpolation von{{placeholder}}, lösensummary/hinteines Vorkommens auf.i18n.whyKey/i18n.cautionKeyeiner Tendenz lösen derenwhyundcautionauf dieselbe Weise auf. Siehe das Ausgabeschema. - Prüfung:
<prefix>_review_<CODE>_step<n>,_passund_fail, in den Prüf-Wörterbüchern: dashowToCheckeines offenen Vorkommens.
Die Schlüssel von Regel, Composite und Vorkommen stehen im Ergebnis neben dem bereits aufgelösten Text, sodass Sie ein gespeichertes Ergebnis in einer anderen Locale neu darstellen können, ohne erneut zu scannen.