← 목록

How to translate MDN web docs to spanish.

devto 2026-09-04 원문 보기 ↗


Good day, for the past 3 weeks I have been busy translating the popular documentation platform known as MDN web docs into the Spanish version, to help Spanish-speaking readers as it had been outdated for years with respect to the English version.

This has been part of my open-source journey. In this article, I want to talk about the process, to enable future contributors to seamlessly contribute one day.

Here are the rules to follow when trying to do the Spanish-translation work. Everything that I am going to write here is already mentioned inside of the rules.

Here is one rule to just bear in mind

is this text something a human reads (translate it) or something the code/interpreter looks up by exact name (leave it untouched)

File Paths

This is the most important one; File paths (bolded or inline) are never translated. It stays the same. Below, we will discuss the only thing that changes, which is en-US to es

English: docs/Web/JavaScript/Reference/Global_Objects/Object/assign

Spanish: docs/Web/JavaScript/Reference/Global_Objects/Object/assign

Front-matter

Links

External links: These are links point to external web pages and they should be left as is. For example: https://validator.w3.org/ or https://developer.flutterwave.com/docs/testing

Internal links: All the internal links that point to pages with in the MDN web docs website have to be changed from /en-US/ to /es/.

For example:

Original (English source):

/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

This has to be changed to point to a spanish file now.

/es/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

Link Text: (ONLY the visible label) gets translated when it's an internal MDN link.

For example

Original (English source):

[Object basics](/en-US/docs/Learn_web_development/Core/Scripting/Object_basics)

We have to translate The link text "Object basics" to "Fundamentos de objetos"

Translated (Spanish):

[Fundamentos de objetos](/es/docs/Learn_web_development/Core/Scripting/Object_basics)

Anchors: when you have an anchor like this, #heading_about_a_paragraph. Two things are involved:

  1. You need to check if that section that the anchor is referring to exists.
  2. If it exists, then you should translate it to Spanish #encabezado_sobre_un_párrafo

Bold / italics

Original (English source):

_this is supposed to be italic_ and **this is supposed to be bold**

Translated (Spanish):

_esto se supone que debe estar en cursiva_ and **esto se supone que debe estar en negrita**

Image(s)

For example:

Original (English source)

![Prototype chain for myObject](myobject-prototype-chain.svg)

Translated (Spanish)

![Cadena de prototipos para myObject](myobject-prototype-chain.svg)

Callouts

For example,

Original (English source)

>[!NOTE]
> See also the [glossary entry on API](/en-US/docs/Glossary/API) for more information.

Translated (Spanish)

>[!NOTE]
> Consulta también la [entrada del glosario sobre API](/es/docs/Glossary/API) para más información.

Notice: [!NOTE] remains untouched

Code

Plain Code blocks: These are code blocks that contain only literal data: no comments, no prose mixed in so there's nothing to translate at all.

https://example.com/articles/
https://example.com/articles/23
https://example.com/articles/?page=2

This stays exactly the same in the Spanish file — same URLs, same formatting, no changes whatsoever. There's no comment explaining anything and no prose sentence inside it.

name
age
city
greet

These are actual JavaScript property names being listed for the reader to look at, not descriptive text, so translating "city" to "ciudad" or "age" to "edad" would misrepresent what the code actually contains.

HTML table structure:
Table tags (<table>, <tr>, <th>, etc.) stay exactly the same, only the visible text inside is translated.

For example:

Original (English source):

<table class="properties">
  <tbody>
    <tr>
      <th scope="row">Prerequisites</th>
      <td>
        A basic understanding of <a href="/en-US/docs/Learn_web_development/Core/Scripting">JavaScript basics</a>.
      </td>
    </tr>
    <tr>
      <th scope="row">Objective</th>
      <td>To understand JavaScript's prototype-based inheritance model.</td>
    </tr>
  </tbody>
</table>

Translated (Spanish):

<table class="properties">
  <tbody>
    <tr>
      <th scope="row">Prerrequisitos</th>
      <td>
        Un entendimiento básico de <a href="/es/docs/Learn_web_development/Core/Scripting">los fundamentos de JavaScript</a>.
      </td>
    </tr>
    <tr>
      <th scope="row">Objetivo</th>
      <td>Comprender el modelo de herencia basado en prototipos de JavaScript.</td>
    </tr>
  </tbody>
</table>

Kumascript macros {{...}}

  1. Macro names and their arguments (page paths) are never translated. The macro names such as (NextMenu, PreviousMenuNext) stay in English because they're internal MDN template functions, not prose.

  2. {{glossary("term")}}: if the English term doesn't naturally read well in Spanish, add a second argument with the translated display text — {{glossary("term", "término")}}. If the term is used as-is in Spanish (e.g. HTTP, JavaScript, Python), leave it with no second argument.

  3. Navigation macros ({{NextMenu(...)}}, {{PreviousMenuNext(...)}}) always left fully untouched whether in English or Spanish.

{{NextMenu("Learn_web_development/Core/Scripting/Object_prototypes", "Learn_web_development/Core/Scripting")}}

{{PreviousMenuNext("Learn_web_development/Core/Scripting/Object_prototypes", "Learn_web_development/Core/Scripting/Object_building_practice", "Learn_web_development/Core/Scripting")}}

Headings

English (Original Source)

## Summary
## Basics: anatomy of a URL
## Scheme
## Authority
## Path to resource
## Parameters
## Anchor
## How to use URLs
## Absolute URLs vs. relative URLs
## URL usernames and passwords
## Semantic URLs
## See also

Translated (Spanish)

## Resumen
## Conceptos básicos: anatomía de una URL
## Esquema
## Autoridad
## Ruta al recurso
## Parámetros
## Ancla
## Cómo utilizar las URL
## URL absolutas frente a URL relativas
## Nombres de usuario y contraseñas en las URL
## URL semánticas
## Véase también

Link: /es/docs/Learn_web_development/Core/Forms/Form_validation#validación_html

For example;

English (Original source)

## Validation HTML

Here's a small but easy-to-miss detail about headings and links. When MDN builds a page, it auto-generates an anchor ID for every heading by lowercasing the text and replacing spaces with underscores. The catch is that it keeps accented characters exactly as they are.

Translated Spanish

## Validación HTML

Aquí hay un detalle pequeño pero fácil de pasar por alto sobre los encabezados y los enlaces. Cuando MDN construye una página, genera automáticamente un ancla para cada encabezado convirtiendo el texto a minúsculas y reemplazando los espacios con guiones bajos. La particularidad es que mantiene los caracteres acentuados exactamente como están.

Comments

Comments inside of Code blocks

This has two (2) cases:

Useful comment(s)

A comment explaining something (translate it):
This comment is real prose explaining why the line exists or what it does. A Spanish-speaking reader benefits from having this translated

English (Original Source)

# Number of visits to this view, as counted in the session
num_visits = request.session.get('num_visits', 0)

Translated (Spanish)

# Número de visitas a esta vista, contado en la sesión
num_visits = request.session.get('num_visits', 0)

Throwaway comment(s)

Example 1

INSTALLED_APPS = [
    # ...
    'django.contrib.sessions',
]

Here, # ... isn't explaining anything — it's just a visual placeholder telling the reader "there's more code here we're not showing." There's no real content to translate; translating ... doesn't mean anything different in Spanish. Best left as-is.

Example 2

const wheels = 'alloy'; // or comment

This kind of comment is minor, vague, and doesn't add much context either way, so it's genuinely a coin-flip: leave it in English since it's a throwaway aside, or translate it for full consistency with the rest of the document.

Keywords, Variables, Functions:

DO NOT TRANSLATE ANY OF THESE

Variable names — e.g. numOfVisits, myCar, count

Function/method names — e.g. getPrototypeOf(), index()

Class names — e.g. Person, Author

Property/dictionary keys — e.g. city, wheels, my_car['wheels']

Exception names — e.g. KeyError

Boolean values (true, false): remain untranslated in both English and Spanish

English (Original Source)

// Uses 'toString()' by default, returns true

Translated (Spanish)

// Usa 'toString()' por defecto, devuelve true

Methods

Method names mentioned inside comments stay untouched.

English (Original Source)

// Calls 'getPrototypeOf()' to find the parent

Translated (Spanish)

// Llama a 'getPrototypeOf()' para encontrar al padre

Console.log()

There are two (2) incidents here:

  1. For literal strings printed to the user, you should translate it. An example is

English (Original Source):

console.log("Greetings from Madrid");

Translated Spanish:

console.log("Saludos desde Madrid");
  1. short/generic literal, here it's a judgment call, and the practical approach is to flag it for the reviewer

Example:

function greet() {
  console.log("hello!");
}

Pluralization

If translating a word breaks a language feature (e.g. pluralization), adapt the word so the mechanism still works (e.g. "time" becomes "vece").

"time" plural form is "times" in English, but the literal spanish translation would be wrong (broken) spanish.

if we were to follow a literal translation of "time" into spanish "vez" literal plural translation "vezs" (which is wrong spanish)

"vez" correct plural form in spanish is "vece".

num_visits = 3, Here, pluralize looks at num_visits and, if it's more than 1, appends an "s" to whatever comes right before the template tag — turning "time" into "times".

English (Original Source)

You have visited this page {{ num_visits }} time{{ num_visits|pluralize }}.

Adapted translation (mechanism still works):

Has visitado esta página {{ num_visits }} vece{{ num_visits|pluralize }}.

More Information

npx prettier --write files/es/learn_web_development/core/scripting/object_prototypes/index.md
import unicodedata
import sys

INVISIBLE_CHARS = (0x200B, 0x200C, 0x200D, 0xFEFF)

def check_file(path):
    with open(path, encoding="utf-8") as f:
        for line_number, line in enumerate(f, 1):
            found = [
                unicodedata.name(char, "?")
                for char in line
                if ord(char) in INVISIBLE_CHARS
            ]
            if found:
                print(line_number, found, repr(line[:40]))

if __name__ == "__main__":
    check_file(sys.argv[1])

Thank you and please follow me.