Automatizar el control de calidad del lenguaje en Transloadit
Este artículo describe nuestra configuración de publicación de 2015. Los nombres de paquetes y la configuración que aparecen a continuación son históricos, no una guía de instalación para la cadena de herramientas actual.
Estaba escribiendo documentación interna sobre cómo configuré la revisión automatizada del lenguaje en Transloadit. A mitad de camino me di cuenta de que esto también podría ser útil para el resto del mundo 🌎, así que lo reescribí de forma más genérica. Primero intentaré dar una visión general del problema, antes de bajar hasta los detalles más concretos de cómo resolverlo. ¡Espero que lo disfrutes, allá vamos!
En Transloadit hemos estado extrayendo todos los fragmentos de texto de tamaño considerable (documentación, artículos del blog, páginas estáticas) a un repositorio de contenido aparte.
Hasta esta migración, nuestro texto estaba disperso en tablas MySQL, plantillas y archivos HTML. Una gran sopa de contenido, diseño, código y ubicaciones. Los desarrolladores podían acceder a todo, pero sin mucha alegría. Quienes no eran desarrolladores no tenían ninguna oportunidad.
Nos pareció interesante ver si podíamos atraer a redactores técnicos y darles acceso completo a nuestro contenido. Imaginábamos que podrían usar la interfaz web de GitHub al estilo de un wiki, para mejorar nuestro lenguaje sin distraerse con el código, cambiarlo por accidente o necesitar mucha destreza en esa área.
Esto todavía no ha alcanzado todo su potencial, pero:
- como desarrolladores, ya disfrutamos trabajar en el contenido (puramente Markdown)
- tener todo el contenido en un repositorio aparte abre las puertas a otras posibilidades geniales, como el control de calidad automatizado, o: la integración continua
Integración continua
La integración continua es un concepto que normalmente se asocia con el código. ThoughtWorks lo explica así:
La integración continua (CI) es una práctica de desarrollo que exige que los desarrolladores integren código en un repositorio compartido varias veces al día. Luego, cada check-in se verifica mediante una compilación automatizada, lo que permite a los equipos detectar problemas de forma temprana.
En Transloadit ya usábamos esto para todo nuestro código. Pero ¿podríamos usarlo también para nuestro inglés?
Esta pregunta era especialmente relevante para nosotros porque, si bien la mayoría de nuestros clientes vive en Estados Unidos, Transloadit tiene su sede en Berlín y nadie de nuestro equipo actual es hablante nativo de inglés.
Teniendo en cuenta lo dañinos que pueden ser los errores de lenguaje cuando la gente aún está en las primeras etapas de evaluar un producto, contar con algunas comprobaciones adicionales es aún más importante para nosotros.
Atacamos la mala calidad del contenido en tres áreas:
Escritura desconsiderada
Citando a npm weekly:
Lo más probable es que ninguno de nosotros pretenda excluir o herir a otros miembros de la comunidad, pero el lenguaje polarizador y que favorece a un género tiene la costumbre de colarse en lo que escribimos. A veces ayuda mucho tener un segundo par de ojos que revise las cosas, note lo que hemos pasado por alto y nos empuje a ser más considerados e inclusivos. Alex ayuda a «detectar la escritura insensible y desconsiderada» identificando lenguaje posiblemente ofensivo y sugiriendo alternativas útiles.
Para instalar alex, ejecutamos un simple npm install --save alex.
Alex no es tan inteligente como un humano, pero se esfuerza al máximo y a veces está demasiado ansioso por avisarte de que algo puede ser insensible.
Esto significa que de vez en cuando puede haber falsos positivos y, como no queremos que las advertencias de alex sean fatales, usamos
node_modules/.bin/alex || true
De esa manera, vemos el lenguaje que alex cree que podría mejorarse, pero no convertimos esas sugerencias en algo crítico.
Por ejemplo
74:74-74:76 warning $(he) may be insensitive, use $(they), $(it) instead
Actualmente estamos reescribiendo nuestra documentación para que sea más inclusiva, gracias a este proyecto.
Formato descuidado
Nuestros archivos de texto están en formato Markdown. Elegimos este formato porque:
- es bastante fácil de asimilar tanto para humanos como para computadoras,
- cuenta con un gran ecosistema de herramientas a su alrededor, y
- ofrece una buena separación entre la estructura de un documento y su diseño visual. Podemos indicar que algo va enfatizado, pero no que sea Comic Sans. Esas decisiones quedan en manos de los diseñadores.
A menudo hay varias maneras de lograr el mismo objetivo en Markdown. Al igual que con el código, ayuda acordar una convención y obligar a cada colaborador a seguirla. Al quitar algo de esta (inútil) libertad artística, el documento resultante se ve bien mantenido e invita a seguir contribuyendo.
Para esto usamos mdast con un plugin de lint:
npm install --save mdast mdast-lint
Como no queremos revisar proyectos externos (como el propio mdast) ni volver a revisar artefactos ya compilados, excluimos algunas ubicaciones
printf '%s\n' '_site/' 'node_modules/' >> .mdastignore
Luego guardamos la siguiente convención en .mdastrc, aunque esto depende, por supuesto, de tus
ajustes y
preferencias de lint
{
"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
}
}
Después ejecutamos el lint por primera vez
node_modules/.bin/mdast --frail .
Esto puede devolver
_posts/2015-09-15-spelling.md
246:1 warning Use spaces instead of hard-tabs no-tabs
Como bonus, mdast incluso puede intentar repararlo automáticamente
node_modules/.bin/mdast --output .
Nos impresionó cuánto pudo arreglar mdast. Asegúrate, eso sí, de que tus archivos estén confirmados en Git antes de ejecutar este comando. Querrás revisar los cambios realizados y revertirlos si hace falta. Lo más probable es que necesites unas cuantas iteraciones para dejar esto en buen estado.
Errores ortográficos
William Dutton, director del Oxford Internet Institute de la Universidad de Oxford, dice en Los errores ortográficos «cuestan millones» en ventas online perdidas que en algunas partes informales de internet, como Facebook, hay mayor tolerancia hacia la ortografía y la gramática.
Sin embargo, hay otros aspectos, como una página de inicio o una oferta comercial, que no se dan entre amigos y que generan preocupaciones sobre la confianza y la credibilidad. En esos casos, una palabra mal escrita puede ser un problema fatal.
Me convenciste con «preocupaciones». Manos a la obra. Para la revisión ortográfica en documentos
Markdown usamos npm install --save markdown-spellcheck.
Puede que no detecte la gramática ni muchas otras sutilezas («it's» frente a «its»), pero al menos muchos de mis desafortunados errores recurrentes se detectan antes de llegar a producción:
- mi propio inglés de fantasía («symbiose» frente a «symbiosis»)
- fallos recurrentes («editted» frente a «edited»), y
- mezclar inglés británico con estadounidense («summarise» frente a «summarize»)
(en mi defensa: no soy hablante nativo de inglés 😄)
Markdown-spellcheck incluso omite automáticamente los bloques de código y otras cosas propias de
Markdown, aunque, claro, aún tuvimos que ignorar manualmente cosas como Transloadit y FFmpeg
printf '%s\n' 'Transloadit' 'FFmpeg' >> .spelling
Ya estamos listos para revisar la ortografía de nuestros archivos Markdown
node_modules/.bin/mdspell \
--report \
--en-us \
--ignore-numbers \
--ignore-acronyms \
**/*.md \
_layouts/*.html \
_includes/*.html \
*.html
Esto podría devolver que «editted» no es una palabra.
Primera ejecución
Es muy probable que la primera ejecución destape muchos problemas, tanto en tus documentos como en
el diccionario. Por eso conviene ejecutar mdspell sin el flag --report, para que
entre en el modo interactivo predeterminado.

Esto te permitirá excluir ciertos archivos y construir un diccionario personalizado dentro de .spelling.
Probablemente tome un rato, pero puede ser una gran actividad para cuando quieras ser productivo en
una tarde sin inspiración.
A medida que agregues contenido nuevo, a veces tendrás que añadir palabras a la lista de permitidos. Pero al menos sabrás que todos los casos en los que las palabras se aparten del diccionario serán deliberados. Y esa es una buena sensación.
Combinar
Ahora juntemos todo esto.
Como instalamos todas estas herramientas desde npm, podría tener sentido usar scripts de npm run. Sin embargo, en nuestro caso elegí un Makefile, simplemente porque nos gusta ir con TAB por el autocompletado del shell y para tener el mismo punto de entrada para desarrolladores en todos nuestros proyectos, ya estén escritos en Node.js, Bash o Go.
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 : )"
Ahora podemos ejecutar make test para ver si pasan todas nuestras comprobaciones.
Podemos ejecutar make test-spelling para centrarnos únicamente en los errores ortográficos, o
make test-spelling-interactive si queremos entrar en modo interactivo después de escribir contenido con
muchas palabras nuevas que es poco probable que ya estén en el diccionario.
Si tienes
Bash Completion, solo escribe
make, presiona TAB y verás todos los atajos disponibles.
Automatizar
Para automatizar las pruebas necesitaremos un servidor de integración continua.
Travis CI, Strider y Drone.io sirven para el caso. Mientras tengamos un lugar central que ejecute código de forma fiable y repetible cada vez que se hace un cambio en tu repositorio.
Usamos Jenkins para proyectos privados, y creé tres nuevas tareas encadenadas para nuestro repositorio de contenido:
content-buildconvierte nuestro Markdown en contenido HTML estático con Jekyll y luego dispara:content-testejecuta todos los comandos de este artículo y luego dispara:content-injectguarda el HTML en nuestro sitio web y luego dispara:website-build,website-test,website-deploy. Una cadena que ya teníamos configurada para desplegar nuestro sitio web.

Ahora solo se puede inyectar y desplegar contenido nuevo si pasan todas las comprobaciones. Es una cadena bastante larga, pero por suerte una máquina se encarga de eso. 😄
Y cuando esa máquina detecta erratas en contenido nuevo, tenemos configurada una integración con Slack para que se nos notifique de inmediato.

¿Es esto perfecto ahora?
No. Los humanos son falibles, y también lo son sus máquinas y diccionarios.
Tendremos que seguir ajustando .spelling, y «eso» tiene que seguir corrigiéndome. Pero con este
control de calidad automatizado del lenguaje, nos vigilamos mutuamente y tenemos menos errores que
antes.
En el caso de Transloadit, pudimos corregir 151 errores en nuestra primera ejecución

Sí.. ¡resulta que somos éramos malísimos con la ortografía!
Qué sigue
Si conoces otras herramientas geniales de procesamiento de Markdown para añadir a nuestra cadena de compilación, avísanos en Twitter o comenta en HN.
Por último, seguimos buscando un buen redactor técnico que nos ayude a mejorar nuestro lenguaje, ya que las computadoras solo pueden llevarnos hasta cierto punto. 😄
Recuerda que solo trabajarías con archivos Markdown; del resto se encarga el sistema de forma automática. ¡Escríbenos si te interesa!
