Deutsch
Lokalen beitragen
@templatical/quality liefert lokal-aware Datensätze, getrennt nach Sprache:
Barrierefreiheits-Regelnachrichten (
src/accessibility/messages/{locale}.ts) — die Texte, die der Editor für jedesa11y.*-Issue zeigt.Vague-Text-Dictionaries (
src/accessibility/dictionaries/{locale}.ts) — Phrasenlisten, die vona11y.link-vague-text,a11y.button-vague-labelunda11y.img-linked-no-contextgenutzt werden.Struktur-Regelnachrichten (
src/structure/messages/{locale}.ts) — Texte für jedesstructure.*-Issue.Link-Regelnachrichten (
src/links/messages/{locale}.ts) — Texte für jedeslink.*-Issue.Zustellbarkeits-Regelnachrichten (
src/deliverability/messages/{locale}.ts) — Texte für jedesdeliverability.*-Issue.Kompatibilitäts-Regelnachrichten (
src/compatibility/messages/{locale}.ts) —messageundsuggestionprocompat.*-Regel, dazu Client-Gruppenbezeichnungen.Lokalisierungs-Regelnachrichten (
src/localization/messages/{locale}.ts) —messageundsuggestionfür jedeslocalization.*-Issue.
Nachrichtendatensätze können unterschiedliche Locales abdecken; eine nicht gebündelte Sprache fällt auf Englisch zurück. Nur die Barrierefreiheit verwendet Vague-Text-Dictionaries; die übrigen Linter übersetzen ihre Nachrichtentexte ohne Phrasen-Dictionary.
Verzeichnisstruktur
packages/quality/src/accessibility/messages/
en.ts ← Source of Truth (implizit typisiert)
de.ts ← annotiert mit `typeof en`
index.ts ← exportiert formatMessage(), getMessages()
packages/quality/src/accessibility/dictionaries/
en.ts
de.ts
index.ts ← exportiert getDictionary(), normalizeForMatch()
packages/quality/src/structure/messages/
en.ts ← Source of Truth
de.ts ← annotiert mit `typeof en`
index.ts ← exportiert formatStructureMessage(), getStructureMessages()
packages/quality/src/links/messages/
en.ts ← Source of Truth
de.ts ← annotiert mit `typeof en`
index.ts ← exportiert formatLinkMessage(), getLinkMessages()
packages/quality/src/compatibility/messages/
en.ts
de.ts
index.ts
packages/quality/src/deliverability/messages/
en.ts ← Source of Truth
de.ts ← annotiert mit `typeof en`
index.ts ← exportiert formatDeliverabilityMessage(), getDeliverabilityMessages()
packages/quality/src/localization/messages/
en.ts ← Source of Truth
de.ts ← annotiert mit `typeof en`
index.ts ← exportiert formatLocalizationMessage(), getLocalizationMessages()Eine Locale hinzufügen
Sie brauchen eine Nachrichtendatei pro Linter und optional ein Vague-Text-Dictionary. Dateien ablegen — sie werden automatisch erkannt. Jede Locale-Registry wird zur Compile-Zeit per import.meta.glob gebaut, es gibt keine Map zu pflegen.
Folgen Sie dem typeof en-Muster in jeder Datei. Die Annotation ist der Vertrag: jeder fehlende Key, jeder zusätzliche Key oder jeder falsche Typ lässt pnpm run typecheck scheitern. Laufzeit-Paritätstests prüfen zusätzlich, dass {name}-Platzhalter über Locales hinweg übereinstimmen.
1. Barrierefreiheits-Regelnachrichten
accessibility/messages/<lang>.ts ablegen und für jeden Wert message und suggestion übersetzen — {name}-Platzhalter exakt beibehalten:
ts
// accessibility/messages/pt.ts
import type en from "./en";
const pt: typeof en = {
"a11y.img-missing-alt":
{ message: "Imagem sem texto alternativo.", suggestion: "Adicione uma descrição curta ou marque a imagem como decorativa." },
"a11y.img-alt-too-long":
{ message: "Texto alternativo tem {length} caracteres.", suggestion: "Mantenha abaixo de {max}." },
// …ein Key pro Barrierefreiheits-Regel
};
export default pt;2. Vague-Text-Dictionary
accessibility/dictionaries/<lang>.ts ablegen:
ts
// accessibility/dictionaries/pt.ts
import type en from "./en";
const pt: typeof en = {
vagueLinkText: ["clique aqui", "aqui", "leia mais", "saiba mais"],
vagueButtonLabels: ["clique aqui", "clique", "enviar"],
linkedImageActionHints: ["compre", "leia", "veja", "baixe", "descubra"],
};
export default pt;3. Struktur-Regelnachrichten
structure/messages/<lang>.ts ablegen:
ts
// structure/messages/pt.ts
import type en from "./en";
const pt: typeof en = {
"structure.duplicate-block-id":
{ message: "ID de bloco aparece {count} vezes na árvore.", suggestion: "Dê a cada bloco um ID único." },
"structure.section-column-mismatch":
{ message: "Seção usa layout {layout}: esperadas {expected} colunas, encontradas {actual}.", suggestion: "Corrija as colunas." },
// …ein Key pro Struktur-Regel
};
export default pt;4. Link-Regelnachrichten
links/messages/<lang>.ts ablegen:
ts
// links/messages/pt.ts
import type en from "./en";
const pt: typeof en = {
"link.javascript-protocol":
{ message: "URL usa o protocolo javascript:.", suggestion: "Substitua por um link real ou remova a URL." },
"link.unsupported-protocol":
{ message: "URL usa o protocolo {protocol}, que muitos clientes não suportam.", suggestion: "Use http, https, mailto, tel ou sms." },
// …ein Key pro Link-Regel
};
export default pt;5. Zustellbarkeits-Regelnachrichten
Legen Sie deliverability/messages/<lang>.ts an und übersetzen Sie alle Schlüssel aus en.ts. Erhalten Sie die Platzhalter {textHost}, {linkHost}, {host}, {count} und {min}.
ts
import en from "./en";
const pt: typeof en = {
...en,
"deliverability.link-text-domain-mismatch":
{ message: "O texto mostra {textHost}, mas o link leva a {linkHost}.", suggestion: "Alinhe o texto com o destino." },
};
export default pt;Das war's — SUPPORTED_MESSAGE_LOCALES, SUPPORTED_DICTIONARY_LOCALES, SUPPORTED_STRUCTURE_MESSAGE_LOCALES, SUPPORTED_LINK_MESSAGE_LOCALES, SUPPORTED_DELIVERABILITY_MESSAGE_LOCALES, SUPPORTED_COMPATIBILITY_MESSAGE_LOCALES und SUPPORTED_LOCALIZATION_MESSAGE_LOCALES reflektieren die neue Locale automatisch. Es ist keine Registry zu editieren. Aktualisieren Sie beim Hinzufügen eines Datensatzes die zugehörigen Locale- und Paritätstests.
Phrasen-Richtlinien (Vague-Text-Dictionary)
- Match, nicht Regex. Die Vague-Text-Regeln normalisieren den Anchor- / Button-Text — kleinschreiben, Whitespace zusammenfassen, führende/abschließende nicht-alphanumerische Zeichen (Interpunktion, Pfeile, dekorative Anführungszeichen) entfernen — und testen dann
phrases.includes(text). „Click here!", „→ click here" und „»click here«" kollabieren also alle zuclick hereund matchen denselben Dictionary-Eintrag. Fügen Sie keine Interpunktionsvarianten hinzu — sie sind redundant. Jeder Eintrag ist trotzdem ein exakter Phrasen-Match; versuchen Sie nicht, Regex-Muster zu codieren. - Nur Kleinbuchstaben. Der Vergleich ist auf der Input-Seite case-insensitive.
- Häufig, nicht erschöpfend. Ziel ist, die häufigsten vagen Phrasen zu erwischen, die Autoren der Sprache schreiben. Eine 50-Einträge-Liste richtet mehr Schaden an als Nutzen (False Positives).
- Englische Phrasen nicht übersetzen. Das Dictionary ist eine sprachübergreifende Vereinigung — die Phrasen jeder registrierten Locale matchen unabhängig von der aktiven
locale-Option. Ihrept.tsbraucht also nur portugiesische Phrasen; das englischeclick hereist über die Vereinigung bereits abgedeckt. - Keine Regions-Duplikate.
de-ATlöst sich auf dieselbe Vereinigung auf; ein Eintrag pro Sprache. linkedImageActionHintsist pro Token, nicht pro Phrase.a11y.img-linked-no-contexttokenisiert den Alt-Text an Nicht-Buchstaben/Ziffer-Grenzen und prüft jeden Token gegen die Hint-Liste. Tragen Sie einzelne Action-Verben in der Form ein, in der Autoren sie schreiben („buy", „kaufen", „compre") — nicht Mehrwort-Phrasen. „jetzt kaufen" wird nie matchen, weil Tokens einzeln geprüft werden.
Match-Reihenfolge
- Vague-Text-Dictionary —
getDictionary(locale)liefert eine Vereinigung der Phrasen (und Action-Hints) aller registrierten Locales. Daslocale-Argument wird der API-Symmetrie wegen akzeptiert, ändert aber aktuell nichts an der zurückgegebenen Menge — eine vage Phrase ist universell vage, und ein Action-Verb in einer beliebigen registrierten Sprache zählt als Link-Ziel-Kontext. Die Erkennung ist by design sprachübergreifend. - Regelnachrichten —
formatMessage(locale, ruleId, params?)(Barrierefreiheit),formatStructureMessage(locale, ruleId, params?)(Struktur),formatLinkMessage(locale, ruleId, params?)(Links),formatDeliverabilityMessage(locale, ruleId, params?)(Zustellbarkeit),formatCompatibilityMessage(locale, ruleId, params?)(Kompatibilität) undformatLocalizationMessage(locale, ruleId, params?)(Lokalisierung) lösen das lokalisierte Template über die jeweiligemessages/{locale}.ts-Datei auf und interpolieren{name}-Platzhalter. Alle Nachrichtenformatierer fallen auf Englisch zurück, wenn die Locale nicht gebündelt ist.
6. Kompatibilitäts-Regelnachrichten
Übersetzen Sie beide Felder jedes { message, suggestion }-Eintrags in compatibility/messages/en.ts. Erhalten Sie {feature}, {unsupported}, {partial}, {size}, {max} und Platzhalter der Merkmale. Übersetzen Sie Familien-/Plattformnamen und die Restanzahl. Der Formatter liefert { message, suggestion }; die neue Locale-Datei wird über den bestehenden Glob geladen.
7. Lokalisierungs-Regelnachrichten
Erstellen Sie localization/messages/<lang>.ts aus localization/messages/en.ts. Verwenden Sie einen Basissprachen-Dateinamen wie pt.ts: Die Suche verwendet die kleingeschriebene Basissprache der angeforderten Locale und fällt auf Englisch zurück, wenn deren Map fehlt. Importieren Sie die englische Map als Typ mit import type en from "./en", annotieren Sie die Locale-Map mit typeof en und exportieren Sie sie als Default, nach dem Muster von de.ts.
Übersetzen Sie message und suggestion für localization.untranslated, localization.stale und localization.merge-tags-differ. Erhalten Sie jeden {field}-Platzhalter in beiden Feldern. import.meta.glob lädt die Datei automatisch; es ist kein Registry-Eintrag nötig. SUPPORTED_LOCALIZATION_MESSAGE_LOCALES enthält die gebündelten Locale-Schlüssel; getLocalizationMessages und formatLocalizationMessage verwenden die neue Map.
Aktualisieren Sie tests/localization/messages.test.ts: Ergänzen Sie die neue Locale in der erwarteten SUPPORTED_LOCALIZATION_MESSAGE_LOCALES-Liste und erweitern Sie die Regel-Schlüssel- und Platzhalterparitätstests auf die neue Map; vergleichen Sie message und suggestion mit Englisch. Die vorhandenen Fälle vergleichen en und de. Führen Sie danach pnpm --filter @templatical/quality run typecheck und pnpm --filter @templatical/quality run test aus. Rufen Sie formatLocalizationMessage für die neue Locale auf und bestätigen Sie, dass beide Rückgabefelder übersetzt und der {field}-Parameter eingesetzt sind.