# Multi-language Support

> Support multiple languages in your site.

---

LLMS index: [llms.txt](/llms.txt)

---

If you'd like to provide site content in multiple languages, the Docsy theme and
Hugo make it easy to both add your translated content and for your users to
navigate between language versions.

## Content and configuration

To add content in multiple languages, you first need to define the available
languages in a `languages` section in your site configuration. Each language can
have its own language-specific configuration. For example, the [Docsy example]
site config specifies that it provides content in English, Norwegian, and
Persian. The default language is English:

<!-- markdownlint-disable -->
<!-- prettier-ignore-start -->





<ul class="nav nav-tabs" id="tabs-0" role="tablist">
  <li class="nav-item">
      <button class="nav-link disabled"
          id="tabs-00-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-00" role="tab"
          aria-controls="tabs-00-00" aria-selected="false">
        Configuration file:
      </button>
    </li><li class="nav-item">
      <button class="nav-link active"
          id="tabs-00-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-01" role="tab"
          data-td-tp-persist="toml" aria-controls="tabs-00-01" aria-selected="true">
        hugo.toml
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-00-02-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-02" role="tab"
          data-td-tp-persist="yaml" aria-controls="tabs-00-02" aria-selected="false">
        hugo.yaml
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-00-03-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-03" role="tab"
          data-td-tp-persist="json" aria-controls="tabs-00-03" aria-selected="false">
        hugo.json
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-0-content">
    <div class="tab-pane fade"
        id="tabs-00-00" role="tabpanel" aria-labelled-by="tabs-00-00-tab" tabindex="0">
        <pre tabindex="0"><code></code></pre>
    </div>
    <div class="tab-pane fade show active"
        id="tabs-00-01" role="tabpanel" aria-labelled-by="tabs-00-01-tab" tabindex="0">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">contentDir</span> <span class="p">=</span> <span class="s2">&#34;content/en&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">defaultContentLanguage</span> <span class="p">=</span> <span class="s2">&#34;en&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">defaultContentLanguageInSubdir</span> <span class="p">=</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="nx">languages</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="nx">languages</span><span class="p">.</span><span class="nx">en</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">languageName</span> <span class="p">=</span><span class="s2">&#34;English&#34;</span>
</span></span><span class="line"><span class="cl"><span class="c"># Weight used for sorting.</span>
</span></span><span class="line"><span class="cl"><span class="nx">weight</span> <span class="p">=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="nx">languages</span><span class="p">.</span><span class="nx">en</span><span class="p">.</span><span class="nx">params</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">title</span> <span class="p">=</span> <span class="s2">&#34;Goldydocs&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">description</span> <span class="p">=</span> <span class="s2">&#34;Docsy does docs&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="nx">languages</span><span class="p">.</span><span class="nx">no</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">languageName</span> <span class="p">=</span><span class="s2">&#34;Norsk&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">contentDir</span> <span class="p">=</span> <span class="s2">&#34;content/no&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="nx">languages</span><span class="p">.</span><span class="nx">no</span><span class="p">.</span><span class="nx">params</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">title</span> <span class="p">=</span> <span class="s2">&#34;Goldydocs&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">description</span> <span class="p">=</span> <span class="s2">&#34;Docsy er operativsystem for skyen&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">time_format_default</span> <span class="p">=</span> <span class="s2">&#34;02.01.2006&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">time_format_blog</span> <span class="p">=</span> <span class="s2">&#34;02.01.2006&#34;</span></span></span></code></pre></div>
    </div>
    <div class="tab-pane fade"
        id="tabs-00-02" role="tabpanel" aria-labelled-by="tabs-00-02-tab" tabindex="0">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">contentDir</span><span class="p">:</span><span class="w"> </span><span class="l">content/en</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">defaultContentLanguage</span><span class="p">:</span><span class="w"> </span><span class="l">en</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">defaultContentLanguageInSubdir</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="l">…</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">languages</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">en</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">languageName</span><span class="p">:</span><span class="w"> </span><span class="l">English</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">weight</span><span class="p">:</span><span class="w"> </span><span class="m">1</span><span class="w"> </span><span class="c"># used for sorting</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">params</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">Docsy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l">Docsy does docs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#39;no&#39;</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">languageName</span><span class="p">:</span><span class="w"> </span><span class="l">Norsk</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">contentDir</span><span class="p">:</span><span class="w"> </span><span class="l">content/no</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">params</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">Docsy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l">Docsy er operativsystem for skyen</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">time_format_default</span><span class="p">:</span><span class="w"> </span><span class="m">02.01.2006</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">time_format_blog</span><span class="p">:</span><span class="w"> </span><span class="m">02.01.2006</span></span></span></code></pre></div>
    </div>
    <div class="tab-pane fade"
        id="tabs-00-03" role="tabpanel" aria-labelled-by="tabs-00-03-tab" tabindex="0">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;contentDir&#34;</span><span class="p">:</span> <span class="s2">&#34;content/en&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;defaultContentLanguage&#34;</span><span class="p">:</span> <span class="s2">&#34;en&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;defaultContentLanguageInSubdir&#34;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;languages&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;en&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;languageName&#34;</span><span class="p">:</span> <span class="s2">&#34;English&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;weight&#34;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;params&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;title&#34;</span><span class="p">:</span> <span class="s2">&#34;Docsy&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;Docsy does docs&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;no&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;languageName&#34;</span><span class="p">:</span> <span class="s2">&#34;Norsk&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;contentDir&#34;</span><span class="p">:</span> <span class="s2">&#34;content/no&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;params&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;title&#34;</span><span class="p">:</span> <span class="s2">&#34;Docsy&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;Docsy er operativsystem for skyen&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;time_format_default&#34;</span><span class="p">:</span> <span class="s2">&#34;02.01.2006&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;time_format_blog&#34;</span><span class="p">:</span> <span class="s2">&#34;02.01.2006&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div>
    </div>
</div>

<!-- prettier-ignore-end -->
<!-- markdownlint-restore -->

Any setting not defined in a `[languages]` block will fall back to the global
value for that setting: so, for example, the content directory used for the site
above will be `content/en` unless the user selects the Norwegian language
option.

Once you've updated your site config, you create a content root directory for
each language version in your source repo, such as `content/en` for English
text, and add your [content](/docs/content/adding-content/) as usual. See the
[Hugo Docs](https://gohugo.io/content-management/multilingual) on multi-language
support for more information.

<!-- markdownlint-disable no-blanks-blockquote -->

> [!WARNING] Attention (only when using Docsy as hugo module)
>
> If you have a multi language installation, ensure that the section
> `[languages]` inside your
> [configuration file](https://gohugo.io/getting-started/configuration/#configuration-file)
> is declared **before** the section `[module]` with the module imports.
> Otherwise you will run into trouble!

> [!TIP]
>
> If there's any possibility your site might be translated into other languages,
> consider creating your site with your content in a language-specific
> subdirectory, as it means you don't need to move it if you add another
> language.

For adding multiple language versions of other site elements such as button
text, see the [internationalization bundles](#internationalization-bundles)
section below.

<!-- markdownlint-disable heading-increment -->

### Right-to-left languages

<!-- markdownlint-restore -->

Docsy supports top-down Right-To-Left (RTL) languages such as Persian through
[Bootstrap's RTL feature][bs-rtl], which uses [RTLCSS].

If your multilingual site includes an RTL language (configured with
`languageDirection: rtl`), then your project needs to include the [`rtlcss`
package]. You can add this package to your dev dependencies as follows:

```sh
npm install rtlcss --save-dev
```

For an example of Docsy's RTL support, see the [Persian pages] of the [Docsy
example].

[bs-rtl]: https://getbootstrap.com/docs/5.3/getting-started/rtl/
[RTLCSS]: https://rtlcss.com/
[`rtlcss` package]: https://www.npmjs.com/package/rtlcss
[Persian pages]: https://example.docsy.dev/fa/

## Selecting a language from the language menu

If you configure more than one language in your
[configuration file](https://gohugo.io/getting-started/configuration/#configuration-file),
the Docsy theme adds a language drop down to the navbar. Selecting a language
takes the user to the translated version of the current page, or the home page
for the given language. For details, see
[Adding a language menu](/docs/content/navigation/#language-menu).

## Internationalization bundles

All UI strings (text for buttons, repository links, etc.) are bundled inside
`/i18n` in the theme, with a `.yaml` file for each language.

If your chosen language isn't currently in the theme and you create your own
`.yaml` file for all the common UI strings (for example, if you translate the UI
text into Esperanto and create a copy of `en.yaml` called `eo.yaml`), we
recommend you do this **in the theme** rather than in your own project. You can
then open a
[pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request)
to contribute your translation to the Docsy community.

> [!TIP] Hugo Tip
>
> Run `hugo server --printI18nWarnings` when doing translation work, as it will
> give you warnings on what strings are missing.

### Create custom UI strings

If any of the Docsy theme UI strings in your chosen language aren't suitable for
your project, or if you need additional strings for your site, you can create
your own project-specific internationalization file in your project's `/i18n`
directory. For example, if you want to override any of Docsy's
[English-language strings](https://github.com/google/docsy/blob/main/i18n/en.yaml),
create your own `/i18n/en.yaml` with just your custom strings. Any values you
specify in this file will override the theme versions, while the remaining
strings will come from the theme's corresponding internationalization bundle.

[Docsy example]: https://example.docsy.dev/
