---
title: Site localization
description: Creating and maintaining site pages in non-English localizations.
linkTitle: Localization
weight: 25
cSpell:ignore: shortcodes
---

The OTel website uses Hugo's [multilingual framework] to support page
localizations. English is the default language, with US English as the default
(implicit) localization. A growing number of other localizations are supported,
as can be seen from the languages dropdown menu in the top nav.

## Translation guidance

When translating website pages from English, we recommend that you follow the
guidance offered in this section.

### Summary

#### ✅ Do {#do}

<div class="border-start border-success bg-success-subtle">

- **Translate**:
  - Page content, including:
    - Mermaid [diagram](#images) text fields
    - Code comments from code excerpts (optional)
  - [Front matter][] field values for `title`, `linkTitle`, and `description`
  - **All** page content and front matter unless indicated otherwise
- **Preserve** the _content_, _meaning_, and _style_ of the original text
- **Ask** [maintainers] if you have any doubts or questions through:
  - [Slack] `#otel-docs-localization` or `#otel-comms` channels
  - [Discussion], issue, or PR comment

[Discussion]:
  https://github.com/open-telemetry/opentelemetry.io/discussions?discussions_q=is%3Aopen+label%3Ai18n

</div>

#### ❌ Do NOT {#do-not}

<div class="border-start border-warning bg-warning-subtle">

- **Translate**:
  - **File or directory** names of resources in this repository
  - [Links](#links), this includes [heading IDs](#headings) [^*]
  - Markdown [link definition labels](#link-labels)
  - Inline code-spans like these: `inline code example`
  - Markdown elements marked as `notranslate` (usually as a CSS class), in
    particular for [headings](#headings)
  - [Front matter][] fields other than those listed in [Do](#do). In particular,
    do not translate `aliases`. When in doubt, ask maintainers.
  - Code
- Create **copies of images**, unless you [localize text in the images](#images)
- Add new or change:
  - **Content** that would be different from the originally intended meaning
  - Presentation **style**, including: _formatting_, _layout_, and _design_
    style (typography, letter case, and spacing for example).

[^*]: For a possible exception, see [Links](#links).

</div>

### Heading IDs {#headings}

To ensure that heading anchor targets are uniform across localizations, when
translating headings:

- Preserve the heading's explicit ID if it has one. [Heading ID syntax][] is
  written after the heading text using syntax like `{ #some-id }`.
- Otherwise, explicitly declare a heading ID corresponding to the autogenerated
  ID of the original English heading.

[Heading ID syntax]:
  https://github.com/yuin/goldmark/blob/master/README.md#headings

### Links {#links}

Do **not** translate link references. This holds true for external links, and
paths to website pages and section-local resources such as [images](#images).

The only exception is for links to external pages (such as
<https://en.wikipedia.org>) that have a version specific to your local. Often
this means replacing the `en` in the URL by your locale's language code.

{{% alert title="Note" %}}

The OTel website repository has a custom render-link hook that Hugo uses to
convert absolute link paths referring to documentation pages. **Links of the
form `/docs/some-page` are made locale specific** by prefixing the path with the
page language code when rendering the link. For example, the previous sample
path would become `/ja/docs/some-page` when rendered from a Japanese page.

{{% /alert %}}

### Link definition labels {#link-labels}

Do **not** translate [labels] of Markdown [link definitions][]. Instead, rewrite
the label as translated link text. For example, consider the following Markdown:

```markdown
[Hello], world! Welcome to the [OTel website][].

[hello]: https://code.org/helloworld
[OTel website]: https://opentelementry.io
```

This would be translated in French as:

```markdown
[Bonjour][hello], le monde! Bienvenue sur le [site OTel][OTel website].

[hello]: https://code.org/helloworld
[OTel website]: https://opentelementry.io
```

[labels]: https://spec.commonmark.org/0.31.2/#link-label
[link definitions]:
  https://spec.commonmark.org/0.31.2/#link-reference-definitions

### Images and diagrams {#images}

Do **not** make copies of image files unless you localize text in the image
itself[^shared-images].

**Do** translate text in [Mermaid][] diagrams.

[^shared-images]:
    Hugo is smart about the way that it renders image files that are shared
    across site localizations. That is, Hugo will output a _single_ image file
    and share it across locales.

[Mermaid]: https://mermaid.js.org

### Include files {#includes}

**Do** translate page fragments found under `_includes` directories just as you
would translate any other page content.

### Shortcodes

{{% alert title="Note" %}}

As of February 2025, we are in the process of migrating from shortcodes to
[include files](#includes) as a means of supporting shared-page content.

{{% /alert %}}

Some of the base shortcodes contain English text that you might need to localize
-- this is particularly true of those contained in [layouts/shortcodes/docs].

If you need to create a localized version of a shortcode, place it under
`layouts/shortcodes/xx`, where `xx` is your localization's language code. From
there, use the same relative path as the original base shortcode.

[layouts/shortcodes/docs]:
  https://github.com/open-telemetry/opentelemetry.io/tree/main/layouts/shortcodes/docs

## Keeping track of localized-page drift {#track-changes}

One of the main challenges of maintaining localized pages, is identifying when
the corresponding English language pages have been updated. This section
explains how we handle this.

### The `default_lang_commit` front-matter field

When a localized page is written, such as `content/zh/<some-path>/page.md`, this
translation is based on a specific [`main` branch commit][main] of the
corresponding English language version of the page at
`content/en/<some-path>/page.md`. In this repository, every localized page
identifies the English page commit in the localized page's front matter as
follows:

```markdown
---
title: Your localized page title
# ...
default_lang_commit: <most-recent-commit-hash-of-default-language-page>
---
```

The front matter above would be in `content/zh/<some-path>/page.md`. The commit
hash would correspond to the latest commit of `content/en/<some-path>/page.md`
from the `main` branch.

### Tracking changes to English pages

As updates are made to English language pages, you can keep track of the
corresponding localized pages that need updating by running the following
command:

```console
$ npm run check:i18n
1       1       content/en/docs/platforms/kubernetes/_index.md - content/zh/docs/platforms/kubernetes/_index.md
...
```

You can restrict the target pages to one or more localizations by providing
path(s) like this:

```sh
npm run check:i18n -- content/zh
```

### Viewing change details

For any given localized pages that need updating, you can see the diff details
of the corresponding English language pages by using the `-d` flag and providing
the paths to your localized pages, or omit the paths to see all. For example:

```console
$ npm run check:i18n -- -d content/zh/docs/platforms/kubernetes
diff --git a/content/en/docs/platforms/kubernetes/_index.md b/content/en/docs/platforms/kubernetes/_index.md
index 3592df5d..c7980653 100644
--- a/content/en/docs/platforms/kubernetes/_index.md
+++ b/content/en/docs/platforms/kubernetes/_index.md
@@ -1,7 +1,7 @@
 ---
 title: OpenTelemetry with Kubernetes
 linkTitle: Kubernetes
-weight: 11
+weight: 350
 description: Using OpenTelemetry with Kubernetes
 ---
```

### Adding `default_lang_commit` to new pages

As you create pages for your localization, remember to add `default_lang_commit`
to the page front matter along with an appropriate commit hash from `main`.

If your page translation is based on an English page in `main` at `<hash>`, then
run the following command to automatically add `default_lang_commit` to your
page file's front matter using the commit `<hash>`. You can specify `HEAD` as an
argument if your pages are now synced with `main` at `HEAD`. For example:

```sh
npm run check:i18n -- -n -c 1ca30b4d content/ja
npm run check:i18n -- -n -c HEAD content/zh/docs/concepts
```

To list localization page files with missing hash keys, run:

```sh
npm run check:i18n -- -n
```

### Updating `default_lang_commit` for existing pages

As you update your localized pages to match changes made to the corresponding
English language page, ensure that you also update the `default_lang_commit`
commit hash.

{{% alert title="Tip" %}}

If your localized page now corresponds to the English language version in `main`
at `HEAD`, then erase the commit hash value in the front matter, and run the
**add** command given in the previous section to automatically refresh the
`default_lang_commit` field value.

{{% /alert %}}

If you have batch updated all of your localization pages that had drifted, you
can update the commit hash of these files using the `-c` flag followed by a
commit hash or 'HEAD' to use `main@HEAD`.

```sh
npm run check:i18n -- -c <hash> <PATH-TO-YOUR-NEW-FILES>
npm run check:i18n -- -c HEAD <PATH-TO-YOUR-NEW-FILES>
```

{{% alert title="Important" %}}

When you use `HEAD` as a hash specifier, the script will use the hash of `main`
at HEAD in your **local environment**. Make sure that you fetch and pull `main`,
if you want HEAD to correspond to `main` in GitHub.

{{% /alert %}}

### Drift status

Run `npm run fix:i18n:status` to add a front-matter field `drifted_from_default`
to those target localization pages that have drifted. This field will soon be
used to display a banner at the top of pages that have drifted relative to their
English counterparts.

### Script help

For more details about the script, run `npm run check:i18n -- -h`.

## New localizations

### New localization team

To start a new localization for the OpenTelemetry website you need:

1. A **localization mentor** who is familiar with your language, such as an
   [active approver][] of the [CNCF Glossary][], or the [Kubernetes website][].
2. At least two potential contributors.

[active approver]: https://github.com/cncf/glossary/blob/main/CODEOWNERS
[CNCF Glossary]: https://glossary.cncf.io/
[Kubernetes website]: https://github.com/kubernetes/website

Once you are ready:

1. Create a [new issue][] to share your interest to contribute.

2. Add the GitHub handles of the mentor and potential contributors.

3. Look up the official [ISO 639-1 code][] for the language you want to add.
   We'll refer to this language code as `LANG_ID` in the remainder of this
   section.

4. Add the following task list to your issue's opening comment:

   ```markdown
   - [ ] Language info:
     - ISO 639-1 language code: `LANG_ID`
     - Language name: ADD_NAME_HERE
   - [ ] Locale team info:
     - [ ] Locale mentor: @GITHUB_HANDLE1, @GITHUB_HANDLE2, ...
     - [ ] Contributors: @GITHUB_HANDLE1, @GITHUB_HANDLE2, ...
   - [ ] Read through
         [Localization](https://opentelemetry.io/docs/contributing/localization/)
         and all other pages in the Contributing section
   - [ ] Localize site homepage to YOUR_LANGUAGE_NAME
   - [ ] OTel maintainers:
     - [ ] Update `hugo.yaml`
     - [ ] Configure cSpell and other tooling support
     - [ ] Create an issue label for `lang:LANG_ID`
     - [ ] Create org-level group for `LANG_ID` approvers
     - [ ] Update components owners for `content/LANG_ID`
   ```

5. [Submit a pull request](../pull-requests/) with a translation of the website
   [homepage], and _nothing else_, in the file `content/LANG_ID/_index.md`.
   Ensure that maintainers have the necessary permissions to edit your PR, since
   they will add additional changes to your PR that are required to get your
   localization project started.

[ISO 639-1 code]: https://en.wikipedia.org/wiki/ISO_639-1
[homepage]:
  https://github.com/open-telemetry/opentelemetry.io/blob/main/content/en/_index.md

After your first PR is merged, maintainers will set up the issue label, the
org-level group and the component owners.

{{% alert title="Note" %}}

You don't have to be an existing contributor to the OpenTelemetry project, to
start a new localization. However, you will not be added as a member of the
[OpenTelemetry GitHub organization](https://github.com/open-telemetry/) or as a
member of the approvers group for your localization. You will need to satisfy
the requirements for becoming an established member and approver as outlined in
the
[membership guidelines](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md).

When starting the localization project, maintainers will treat your reviews as
if you are an approver already.

{{% /alert %}}

### OTel maintainer checklist

#### Hugo

Update `hugo.yaml`. Add appropriate entries for `LANG_ID` under:

- `languages`
- `module.mounts`. At a minimum, add a single `source`-`target` entry for
  `content`. Consider adding entries for `en` fallback pages only once the
  locale has enough content.

#### Spelling

Look for [cSpell dictionaries][] available as NPM packages
[@cspell/dict-LANG_ID][]. If a dictionary isn't available for your dialect or
region, choose the closest region.

If no dictionary is available, then skip the rest of this subsection. Otherwise:

- Add the NPM package as a dev dependency, for example:
  `npm install --save-dev @cspell/dict-bn`.
- Create `.cspell/LANG_ID-words.txt` as the site-local dictionary words for
  `LANG_ID`.
- In `.cspell.yml`, add entries for:
  - `import`
  - `dictionaryDefinitions`
  - `dictionaries`: add two entries here, one for `LANG_ID` and one for
    `LANG_ID-words.txt`

[cSpell dictionaries]: https://github.com/streetsidesoftware/cspell-dicts
[@cspell/dict-LANG_ID]: https://www.npmjs.com/search?q=%40cspell%2Fdict

#### Other tooling support

- Prettier support: if `LANG_ID` isn't well supported by Prettier, add ignore
  rules to `.prettierignore`

## English-language maintainer guidance

### Avoid PRs with doc changes across locales {#prs-should-not-span-locales}

Contributors should avoid submitting PRs that make doc changes spanning locales.
The only exception is documented in the next section.

### When link checking fails for non-English pages {#patch-locale-links}

Sometimes changes to English language documentation can result in link-check
failures for non-English locales. This happens when documentation pages are
moved or deleted.

In such situations, make the following updates to each non-English page that has
a path that fails link checking:

- Update the link reference to the new page path.
- Add the `# patched` YAML comment at the end of the line for the
  `default_lang_commit` front matter line.
- Make no other changes to the file.
- Rerun `npm run check:links` and ensure that no link failures remain.

[front matter]: https://gohugo.io/content-management/front-matter/
[main]: https://github.com/open-telemetry/opentelemetry.io/commits/main/
[maintainers]: https://github.com/orgs/open-telemetry/teams/docs-maintainers
[multilingual framework]: https://gohugo.io/content-management/multilingual/
[new issue]: https://github.com/open-telemetry/opentelemetry.io/issues/new
[slack]: https://slack.cncf.io/
