Automatisierte Qualitätskontrolle für Sprache bei Transloadit
Dieser Artikel beschreibt unser Publishing-Setup von 2015. Die nachfolgenden Paketnamen und Konfigurationen sind historisch und keine Installationsanleitung für die heutige Toolchain.
Ich habe gerade interne Dokumentation darüber geschrieben, wie ich bei Transloadit die automatisierte Sprachprüfung eingerichtet habe. Auf halbem Weg dachte ich mir, dass dies auch für den Rest der Welt 🌎 nützlich sein könnte, also habe ich sie in allgemeinerer Form neu geschrieben. Ich werde zunächst versuchen, einen Überblick auf hoher Ebene über das Problem zu geben, bevor ich bis hinunter zu den technischen Details der Lösung gehe. Ich hoffe, es gefällt Ihnen. Los geht’s!
Bei Transloadit haben wir alle nennenswert großen Textblöcke (Dokumentation, Blogbeiträge, statische Seiten) in ein separates Content-Repository ausgelagert.
Bis zu dieser Migration war unser Text über MySQL-Tabellen, Vorlagen und HTML-Dateien verstreut. Ein großer Brei aus Inhalt, Layout, Code und Speicherorten. Entwickler konnten auf alles zugreifen, allerdings ohne große Freude. Nicht-Entwickler hatten keine Chance.
Wir fanden es spannend, herauszufinden, ob wir technische Redakteure gewinnen und ihnen vollen Zugriff auf unsere Inhalte geben könnten. Wir stellten uns vor, dass sie die GitHub-Weboberfläche wie ein Wiki nutzen könnten, um unsere Sprache zu verbessern, ohne von Code abgelenkt zu werden, ihn versehentlich zu ändern oder viel Können in diesem Bereich zu benötigen.
Das volle Potenzial ist noch nicht ausgeschöpft, aber:
- als Entwickler arbeiten wir bereits gerne an den (rein in Markdown gehaltenen) Inhalten
- alle Inhalte in einem separaten Repository zu haben, öffnet Türen zu weiteren spannenden Möglichkeiten wie automatisierter Qualitätskontrolle oder: Continuous Integration
Continuous Integration
Continuous Integration ist ein Konzept, das man normalerweise mit Code verbindet. ThoughtWorks erklärt es wie folgt:
Continuous Integration (CI) ist eine Entwicklungspraxis, die von Entwicklern verlangt, mehrmals täglich Code in ein gemeinsames Repository zu integrieren. Jeder Check-in wird anschließend durch einen automatisierten Build verifiziert, sodass Teams Probleme frühzeitig erkennen können.
Bei Transloadit haben wir das bereits für unseren gesamten Code eingesetzt. Aber ließe sich das auch auf unser Englisch anwenden?
Diese Frage war für uns besonders relevant, denn während die Mehrheit unserer Kunden in den Vereinigten Staaten lebt, sitzt Transloadit in Berlin, und niemand in unserem aktuellen Team ist englischer Muttersprachler.
Wenn man bedenkt, wie schädlich Sprachfehler sein können, während Menschen ein Produkt noch in einer frühen Phase evaluieren, sind zusätzliche Prüfungen für uns umso wichtiger.
Wir gehen mangelhafte Inhaltsqualität in drei Bereichen an:
Rücksichtslose Formulierungen
Um npm weekly zu zitieren:
Wahrscheinlich beabsichtigt niemand von uns, andere Mitglieder der Community auszuschließen oder zu verletzen, doch polarisierende und ein Geschlecht bevorzugende Sprache schleicht sich leicht in das ein, was wir schreiben. Manchmal ist es eine große Hilfe, wenn ein zweites Paar Augen alles durchsieht, bemerkt, was wir übersehen haben, und uns ermutigt, rücksichtsvoller und inklusiver zu sein. Alex hilft dabei, „unsensible, rücksichtslose Formulierungen aufzuspüren“, indem es möglicherweise anstößige Sprache erkennt und hilfreiche Alternativen vorschlägt.
Um alex zu installieren, führen wir ein einfaches
npm install --save alex aus.
Alex ist nicht so klug wie ein Mensch, gibt aber sein Bestes und weist Sie manchmal übereifrig darauf hin, dass etwas unsensibel sein könnte.
Das bedeutet, dass es gelegentlich Fehlalarme geben kann, und da wir nicht möchten, dass die Warnungen von alex zum Abbruch führen, verwenden wir
node_modules/.bin/alex || true
So sehen wir, welche Formulierungen alex für verbesserungswürdig hält, ohne diese Vorschläge als kritisch einzustufen.
Zum Beispiel
74:74-74:76 warning $(he) may be insensitive, use $(they), $(it) instead
Dank dieses Projekts schreiben wir unsere Dokumentation derzeit inklusiver um.
Unordentliche Formatierung
Unsere Textdateien liegen im Markdown-Format vor. Dieses Format wurde gewählt, weil es:
- für Menschen und Computer recht leicht verständlich ist,
- ein großartiges Ökosystem an Werkzeugen um sich herum hat und
- eine gute Trennung zwischen der Struktur eines Dokuments und seinem Layout bietet. Wir können festlegen, dass etwas hervorgehoben ist, aber nicht Comic Sans. Diese Entscheidungen bleiben den Designern überlassen.
Oft gibt es in Markdown mehrere Wege, dasselbe Ziel zu erreichen. Wie bei Code hilft es, sich auf eine Konvention zu einigen und jeden Mitwirkenden dazu zu verpflichten, sie einzuhalten. Nimmt man einen Teil dieser (nutzlosen) künstlerischen Freiheit weg, wirkt das resultierende Dokument gut gepflegt und lädt zu weiteren Beiträgen ein.
Dafür verwenden wir mdast mit einem Lint-Plugin:
npm install --save mdast mdast-lint
Da wir keine externen Projekte (wie mdast selbst) prüfen und keine gebauten Artefakte erneut prüfen wollen, schließen wir einige Speicherorte aus
printf '%s\n' '_site/' 'node_modules/' >> .mdastignore
Anschließend haben wir die folgende Konvention in .mdastrc gespeichert, was
natürlich von Ihren Einstellungen und
Lint-Präferenzen abhängt
{
"plugins": {
"lint": {
"blockquote-indentation": 2,
"emphasis-marker": "*",
"first-heading-level": false,
"link-title-style": "\"",
"list-item-indent": false,
"list-item-spacing": false,
"no-shell-dollars": false,
"maximum-heading-length": false,
"maximum-line-length": false,
"no-duplicate-headings": false,
"no-blockquote-without-caret": false,
"no-file-name-irregular-characters": true,
"no-file-name-outer-dashes": false,
"no-heading-punctuation": false,
"no-html": false,
"no-multiple-toplevel-headings": false,
"ordered-list-marker-style": ".",
"ordered-list-marker-value": "one",
"strong-marker": "*"
}
},
"settings": {
"gfm": true,
"yaml": true,
"rule": "-",
"ruleSpaces": false,
"ruleRepetition": 70,
"emphasis": "*",
"listItemIndent": "1",
"incrementListMarker": false,
"spacedTable": false
}
}
Dann linten wir zum ersten Mal
node_modules/.bin/mdast --frail .
Das kann Folgendes zurückgeben
_posts/2015-09-15-spelling.md
246:1 warning Use spaces instead of hard-tabs no-tabs
Als Bonus kann mdast sogar versuchen, dies automatisch zu beheben
node_modules/.bin/mdast --output .
Wir waren beeindruckt, wie viel mdast beheben konnte. Stellen Sie jedoch sicher, dass Ihre Dateien in Git committet sind, bevor Sie diesen Befehl ausführen. Sie werden die vorgenommenen Änderungen prüfen und bei Bedarf zurücknehmen wollen. Höchstwahrscheinlich sind einige Durchläufe nötig, bis alles in einem guten Zustand ist.
Rechtschreibfehler
William Dutton, Direktor des Oxford Internet Institute an der Oxford University, sagt in Rechtschreibfehler „kosten Millionen“ an entgangenen Online-Umsätzen, dass in manchen informellen Bereichen des Internets, etwa auf Facebook, größere Toleranz gegenüber Rechtschreibung und Grammatik herrscht.
Es gibt jedoch andere Bereiche, etwa eine Startseite oder ein kommerzielles Angebot, bei denen man nicht unter Freunden ist und die Bedenken hinsichtlich Vertrauen und Glaubwürdigkeit wecken. In diesen Fällen kann ein falsch geschriebenes Wort zum entscheidenden Problem werden.
Spätestens bei „Bedenken“ hatten Sie mich überzeugt. Machen wir uns an die Arbeit. Für die
Rechtschreibprüfung in Markdown-Dokumenten verwenden wir npm install --save markdown-spellcheck.
Grammatik und viele andere Feinheiten („it's“ vs. „its“) erkennt es womöglich nicht, aber zumindest werden viele meiner leidigen hartnäckigen Fehler abgefangen, bevor sie in Produktion gelangen:
- mein eigenes Fantasie-Englisch („symbiose“ vs. „symbiosis“)
- hartnäckige Ausrutscher („editted“ vs. „edited“) und
- das Vermischen von britischem und US-amerikanischem Englisch („summarise“ vs. „summarize“)
(zu meiner Verteidigung: Ich bin kein englischer Muttersprachler 😄)
Markdown-spellcheck überspringt sogar automatisch Codeblöcke und andere Markdown-typische Dinge,
aber natürlich mussten wir Dinge wie Transloadit und
FFmpeg weiterhin manuell ignorieren
printf '%s\n' 'Transloadit' 'FFmpeg' >> .spelling
Jetzt sind wir bereit, unsere Markdown-Dateien auf Rechtschreibfehler zu prüfen
node_modules/.bin/mdspell \
--report \
--en-us \
--ignore-numbers \
--ignore-acronyms \
**/*.md \
_layouts/*.html \
_includes/*.html \
*.html
Das könnte zurückgeben, dass „editted“ kein Wort ist.
Erster Durchlauf
Die Chancen stehen gut, dass der erste Durchlauf viele Probleme aufdeckt, sowohl in Ihren Dokumenten
als auch im Wörterbuch. Daher ist es eine gute Idee, mdspell ohne das Flag
--report auszuführen, damit der standardmäßige interaktive Modus startet.

So können Sie bestimmte Dateien ausschließen und ein persönliches Wörterbuch in
.spelling aufbauen. Das dauert wahrscheinlich eine Weile, eignet sich aber
hervorragend, wenn Sie an einem ansonsten einfallslosen Nachmittag produktiv sein möchten.
Wenn Sie neue Inhalte hinzufügen, müssen Sie gelegentlich auch Wörter zur Allowlist hinzufügen. Aber zumindest wissen Sie, dass alle Fälle, in denen Wörter vom Wörterbuch abweichen, bewusst gewählt sind. Und das ist ein gutes Gefühl.
Kombinieren
Fügen wir nun alles zusammen.
Da wir all diese Werkzeuge aus npm installiert haben, läge es nahe, npm-run-Skripte zu verwenden. In unserem Fall habe ich mich jedoch für ein Makefile entschieden, einfach weil wir uns gerne per TAB durch die Shell-Autovervollständigung hangeln und weil wir so in allen unseren Projekten denselben Einstiegspunkt für Entwickler haben, egal ob sie in Node.js, Bash oder Go geschrieben sind.
SHELL := /usr/bin/env bash
tstArgs :=
tstPattern := **/*.md _layouts/*.html _includes/*.html *.html
.PHONY: fix-markdown
fix-markdown:
@echo "--> Fixing Messy Formatting.."
@node_modules/.bin/mdast --output .
.PHONY: test-inconsiderate
test-inconsiderate:
@echo "--> Searching for Inconsiderate Writing (non-fatal).."
@node_modules/.bin/alex $(tstArgs) || true
.PHONY: test-spelling
test-spelling:
@$(MAKE) test-spelling-interactive tstArgs=--report
.PHONY: test-spelling-interactive
test-spelling-interactive:
@echo "--> Searching for Spelling Errors.."
@node_modules/.bin/mdspell \
$(tstArgs) \
--en-us \
--ignore-numbers \
--ignore-acronyms \
$(tstPattern)
.PHONY: test-markdown-lint
test-markdown-lint:
@echo "--> Searching for Messy Formatting.."
@node_modules/.bin/mdast --frail $(tstArgs) .
.PHONY: test
test: test-inconsiderate test-spelling test-markdown-lint
@echo "All okay : )"
Jetzt können wir make test ausführen, um zu sehen, ob alle unsere Prüfungen
bestehen.
Wir können make test-spelling ausführen, um uns nur auf Rechtschreibfehler zu
konzentrieren, oder make test-spelling-interactive, wenn wir in den interaktiven Modus wechseln
möchten, nachdem wir Inhalte mit vielen neuen Wörtern geschrieben haben, die vermutlich noch nicht
im Wörterbuch stehen.
Wenn Sie Bash Completion haben, tippen Sie einfach
make, drücken Sie TAB und sehen Sie alle verfügbaren Kurzbefehle.
Automatisieren
Um das Testen zu automatisieren, benötigen wir einen Continuous-Integration-Server.
Travis CI, Strider und Drone.io kommen alle infrage. Hauptsache, wir haben einen zentralen Ort, der Code zuverlässig und wiederholbar ausführt, sobald eine Änderung an Ihrem Repository vorgenommen wird.
Für private Projekte verwenden wir Jenkins, und ich habe drei neue verkettete Jobs für unser Content-Repository angelegt:
content-buildwandelt unser Markdown mit Jekyll in statische HTML-Inhalte um und löst dann aus:content-testführt alle Befehle aus diesem Beitrag aus und löst dann aus:content-injectspeichert das HTML in unserer Website und löst dann aus:website-build,website-test,website-deploy. Eine Kette, die wir bereits für das Deployment unserer Website eingerichtet hatten.

Neue Inhalte können jetzt nur noch eingespielt und deployt werden, wenn alle Prüfungen bestehen. Es ist eine ziemlich lange Kette, aber zum Glück kümmert sich eine Maschine darum. 😄
Und wenn diese Maschine Tippfehler in neuen Inhalten entdeckt, haben wir eine Slack-Integration eingerichtet, sodass wir sofort benachrichtigt werden.

Ist das jetzt perfekt?
Nein. Menschen sind fehlbar und ihre Maschinen und Wörterbücher ebenso.
Wir werden .spelling weiter anpassen müssen, und „es“ muss mich weiterhin
korrigieren. Aber mit dieser automatisierten Qualitätskontrolle für Sprache halten wir uns
gegenseitig in Schach und haben weniger Fehler als zuvor.
Im Fall von Transloadit konnten wir im ersten Durchlauf 151 Fehler beheben

Ja.. wie sich herausstellt, sind waren wir wirklich miserable Rechtschreiber!
Wie es weitergeht
Wenn Sie weitere coole Werkzeuge zur Markdown-Verarbeitung kennen, die wir unserer Build-Kette hinzufügen sollten, sagen Sie uns auf Twitter Bescheid oder kommentieren Sie auf HN.
Schließlich suchen wir weiterhin einen guten technischen Redakteur, der uns hilft, unsere Sprache zu verbessern, denn Computer bringen uns nur bis zu einem gewissen Punkt. 😄
Denken Sie daran: Sie würden ausschließlich an Markdown-Dateien arbeiten, um den Rest kümmert sich die Automatik. Schreiben Sie uns, wenn Sie Interesse haben!
