Skip to content

Localizing ReSpec

Marcos Caceres edited this page Sep 22, 2026 · 3 revisions

Localizing ReSpec

ReSpec generates boilerplate text (headers, section titles, references, notes) in the language of the spec being authored. This guide explains how that works and how to contribute translations for a new language.

This is a change to ReSpec itself, not to your spec. You are editing ReSpec's source and opening a pull request against it. Nothing here translates the prose you write in your own document; to do that, write it in your language and set lang on <html>.

To follow the steps below you need a clone of ReSpec:

git clone https://github.com/speced/respec.git
cd respec

How localization works

Each ReSpec source file that produces user-visible text keeps its own localizationStrings object. At the top of such a file you'll find something like:

const localizationStrings = {
  en: {
    references: "References",
    norm_references: "Normative references",
    info_references: "Informative references",
  },
  ja: {
    references: "参考文献",
    norm_references: "規範的参考文献",
    info_references: "参照用参考文献",
  },
};

const l10n = getIntlData(localizationStrings);

getIntlData returns a proxy backed by the localizationStrings object. At runtime it reads the lang attribute on the <html> element and returns the matching locale's strings. If a key is missing for the active locale, it falls back to en; if en is missing it too, ReSpec throws. A region subtag also falls back to its base language, so zh-Hans finds the zh strings.

Currently supported locales

Code Language
cs Czech
de German
en English (default)
es Spanish
fr French
ja Japanese
ko Korean
nl Dutch
zh Chinese (Simplified)

Not every module has translations for all locales. Partial coverage is fine — missing keys fall back to English automatically.

Adding a new language

Step 1 — Find all modules with localizable strings

grep -rn "localizationStrings" src/ | grep -v "getIntlData\|l10n ="

The command lists every file; there are 46 of them. They fall into three groups:

  • Profile boilerplatesrc/w3c/, src/aom/ and src/dini/ each carry their own headers, abstract and conformance strings. This is where most reader-visible text lives.
  • Core document furnituresrc/core/ holds the References, Index and Table of Contents headings, note/warning/issue labels, figure and table captions, and the "This section is non-normative." line.
  • Messages to the spec authorsrc/core/linter-rules/ and src/ui/ hold linter warnings and the ReSpec UI. These are seen by the person writing the spec, not by its readers, so translate them last if you are short on time.

Step 2 — Add your locale to each module

Open each file above and add a new key to its localizationStrings object. Use an existing locale as a template:

const localizationStrings = {
  en: {
    references: "References",
    norm_references: "Normative references",
    info_references: "Informative references",
  },
  // ... existing locales ...
  pt: {                                   // ← add your locale
    references: "Referências",
    norm_references: "Referências normativas",
    info_references: "Referências informativas",
  },
};

A few things to keep in mind:

  • The locale code must match a valid BCP 47 language tag primary subtag (e.g. pt, ar, hi).
  • Some string values are functions, not plain strings. For example, keywordInterpretation in w3c/conformance.js returns an HTMLElement. Translate the text inside the template literal, but keep the function signature and HTML structure intact.
  • Partial coverage is welcome. Only add keys you are confident about. Missing keys fall back to English.

Step 3 — Declare the language on a test spec

Take any small spec you can edit and set the lang attribute on its <html> element:

<html lang="pt">

Set it on the <html> element. lang is not a respecConfig option: core/l10n reads document.documentElement.lang when the module loads, so a value in respecConfig never reaches it. For a right-to-left language, set dir as well.

Step 4 — Check your strings in the browser

Editing src/ changes nothing until you build; the Developers-Guide covers running ReSpec from a working copy. Once your spec loads your build, check the places boilerplate actually shows up:

  • Section headings (Abstract, References, Index, TOC)
  • Header labels (Editor, Authors, This version)
  • Note/Warning/Issue blocks
  • The Conformance section (if your spec uses RFC 2119 keywords)

Changing document.documentElement.lang from the browser console does not switch locales. core/l10n reads the attribute once when the module loads, so edit the <html> element and reload instead.

Step 5 — Submit a pull request

  1. Fork speced/respec and create a branch named l10n-<locale> (e.g. l10n-pt).
  2. Commit your changes with a message like: l10n: add Portuguese (pt) translations.
  3. Open a pull request against main. Reference issue #4796 in the PR body.
  4. A maintainer will review and may ask native speakers to verify the translations.

Tips for translators

  • Do not translate element names or attribute names that appear in error/warning messages. For example, <section>, data-cite, testSuiteURI should remain as-is.
  • Preserve pluralization logic in function-valued strings. Languages differ in how they handle singular vs plural, so adapt the logic rather than collapsing it to one form.
  • Right-to-left languages (Arabic, Hebrew, etc.): translations are welcome. Note that the CSS layout may need a separate fix to fully support RTL; open an issue to track that work alongside the strings PR.
  • If you are unsure about a translation, leave a comment in the PR and mark it with (needs review).

Guides

Configuration options

W3C Configuration options

Linting rules

Internal properties

Handled by ReSpec for you.

Special <section> IDs

HTML elements

Custom Elements

HTML attributes

CSS Classes

Special properties

Clone this wiki locally