hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

multilingual.md (18103B)

    1 ---
    2 title: Multilingual Mode
    3 linktitle: Multilingual
    4 description: Hugo supports the creation of websites with multiple languages side by side.
    5 date: 2017-01-10
    6 publishdate: 2017-01-10
    7 lastmod: 2017-01-10
    8 categories: [content management]
    9 keywords: [multilingual,i18n, internationalization]
   10 menu:
   11   docs:
   12     parent: "content-management"
   13     weight: 150
   14 weight: 150	#rem
   15 draft: false
   16 aliases: [/content/multilingual/,/tutorials/create-a-multilingual-site/]
   17 toc: true
   18 ---
   19 
   20 You should define the available languages in a `languages` section in your site configuration.
   21 
   22 > Also See [Hugo Multilingual Part 1: Content translation]
   23 
   24 ## Configure Languages
   25 
   26 The following is an example of a site configuration for a multilingual Hugo project:
   27 
   28 {{< code-toggle file="config" >}}
   29 defaultContentLanguage = "en"
   30 copyright = "Everything is mine"
   31 
   32 [params]
   33 [params.navigation]
   34 help  = "Help"
   35 
   36 [languages]
   37 [languages.en]
   38 title = "My blog"
   39 weight = 1
   40 [languages.en.params]
   41 linkedin = "https://linkedin.com/whoever"
   42 
   43 [languages.fr]
   44 title = "Mon blogue"
   45 weight = 2
   46 [languages.fr.params]
   47 linkedin = "https://linkedin.com/fr/whoever"
   48 [languages.fr.params.navigation]
   49 help  = "Aide"
   50 
   51 [languages.ar]
   52 title = "مدونتي"
   53 weight = 2
   54 languagedirection = "rtl"
   55 
   56 [languages.pt-pt]
   57 title = "O meu blog"
   58 weight = 3
   59 {{< /code-toggle >}}
   60 
   61 Anything not defined in a `languages` block will fall back to the global value for that key (e.g., `copyright` for the English `en` language). This also works for `params`, as demonstrated with `help` above: You will get the value `Aide` in French and `Help` in all the languages without this parameter set.
   62 
   63 With the configuration above, all content, sitemap, RSS feeds, paginations,
   64 and taxonomy pages will be rendered below `/` in English (your default content language) and then below `/fr` in French.
   65 
   66 When working with front matter `Params` in [single page templates], omit the `params` in the key for the translation.
   67 
   68 `defaultContentLanguage` sets the project's default language. If not set, the default language will be `en`.
   69 
   70 If the default language needs to be rendered below its own language code (`/en`) like the others, set `defaultContentLanguageInSubdir: true`.
   71 
   72 Only the obvious non-global options can be overridden per language. Examples of global options are `baseURL`, `buildDrafts`, etc.
   73 
   74 **Please note:** use lowercase language codes, even when using regional languages (ie. use pt-pt instead of pt-PT). Currently Hugo language internals lowercase language codes, which can cause conflicts with settings like `defaultContentLanguage` which are not lowercased. Please track the evolution of this issue in [Hugo repository issue tracker](https://github.com/gohugoio/hugo/issues/7344)
   75 
   76 ### Disable a Language
   77 
   78 You can disable one or more languages. This can be useful when working on a new translation.
   79 
   80 {{< code-toggle file="config" >}}
   81 disableLanguages = ["fr", "ja"]
   82 {{< /code-toggle >}}
   83 
   84 Note that you cannot disable the default content language.
   85 
   86 We kept this as a standalone setting to make it easier to set via [OS environment]:
   87 
   88 ```bash
   89 HUGO_DISABLELANGUAGES="fr ja" hugo
   90 ```
   91 
   92 If you have already a list of disabled languages in `config.toml`, you can enable them in development like this:
   93 
   94 ```bash
   95 HUGO_DISABLELANGUAGES=" " hugo server
   96 ```
   97 
   98 ### Configure Multilingual Multihost
   99 
  100 From **Hugo 0.31** we support multiple languages in a multihost configuration. See [this issue](https://github.com/gohugoio/hugo/issues/4027) for details.
  101 
  102 This means that you can now configure a `baseURL` per `language`:
  103 
  104 > If a `baseURL` is set on the `language` level, then all languages must have one and they must all be different.
  105 
  106 Example:
  107 
  108 {{< code-toggle file="config" >}}
  109 [languages]
  110 [languages.fr]
  111 baseURL = "https://example.fr"
  112 languageName = "Français"
  113 weight = 1
  114 title = "En Français"
  115 
  116 [languages.en]
  117 baseURL = "https://example.com"
  118 languageName = "English"
  119 weight = 2
  120 title = "In English"
  121 {{</ code-toggle >}}
  122 
  123 With the above, the two sites will be generated into `public` with their own root:
  124 
  125 ```text
  126 public
  127 ├── en
  128 └── fr
  129 ```
  130 
  131 **All URLs (i.e `.Permalink` etc.) will be generated from that root. So the English home page above will have its `.Permalink` set to `https://example.com/`.**
  132 
  133 When you run `hugo server` we will start multiple HTTP servers. You will typically see something like this in the console:
  134 
  135 ```text
  136 Web Server is available at 127.0.0.1:1313 (bind address 127.0.0.1)
  137 Web Server is available at 127.0.0.1:1314 (bind address 127.0.0.1)
  138 Press Ctrl+C to stop
  139 ```
  140 
  141 Live reload and `--navigateToChanged` between the servers work as expected.
  142 
  143 
  144 ## Translate Your Content
  145 
  146 There are two ways to manage your content translations. Both ensure each page is assigned a language and is linked to its counterpart translations.
  147 
  148 ### Translation by filename
  149 
  150 Considering the following example:
  151 
  152 1. `/content/about.en.md`
  153 2. `/content/about.fr.md`
  154 
  155 The first file is assigned the English language and is linked to the second.
  156 The second file is assigned the French language and is linked to the first.
  157 
  158 Their language is __assigned__ according to the language code added as a __suffix to the filename__.
  159 
  160 By having the same **path and base filename**, the content pieces are __linked__ together as translated pages.
  161 
  162 {{< note >}}
  163 If a file has no language code, it will be assigned the default language.
  164 {{</ note >}}
  165 
  166 ### Translation by content directory
  167 
  168 This system uses different content directories for each of the languages. Each language's content directory is set using the `contentDir` param.
  169 
  170 {{< code-toggle file="config" >}}
  171 languages:
  172   en:
  173     weight: 10
  174     languageName: "English"
  175     contentDir: "content/english"
  176   fr:
  177     weight: 20
  178     languageName: "Français"
  179     contentDir: "content/french"
  180 {{< /code-toggle >}}
  181 
  182 The value of `contentDir` can be any valid path -- even absolute path references. The only restriction is that the content directories cannot overlap.
  183 
  184 Considering the following example in conjunction with the configuration above:
  185 
  186 1. `/content/english/about.md`
  187 2. `/content/french/about.md`
  188 
  189 The first file is assigned the English language and is linked to the second.
  190 The second file is assigned the French language and is linked to the first.
  191 
  192 Their language is __assigned__ according to the content directory they are __placed__ in.
  193 
  194 By having the same **path and basename** (relative to their language content directory), the content pieces are __linked__ together as translated pages.
  195 
  196 ### Bypassing default linking
  197 
  198 Any pages sharing the same `translationKey` set in front matter will be linked as translated pages regardless of basename or location.
  199 
  200 Considering the following example:
  201 
  202 1. `/content/about-us.en.md`
  203 2. `/content/om.nn.md`
  204 3. `/content/presentation/a-propos.fr.md`
  205 
  206 {{< code-toggle >}}
  207 translationKey: "about"
  208 {{< /code-toggle >}}
  209 
  210 By setting the `translationKey` front matter param to `about` in all three pages, they will be __linked__ as translated pages.
  211 
  212 ### Localizing permalinks
  213 
  214 Because paths and filenames are used to handle linking, all translated pages will share the same URL (apart from the language subdirectory).
  215 
  216 To localize the URLs, the [`slug`]({{< ref "/content-management/organization/index.md#slug" >}}) or [`url`]({{< ref "/content-management/organization/index.md#url" >}}) front matter param can be set in any of the non-default language file.
  217 
  218 For example, a French translation (`content/about.fr.md`) can have its own localized slug.
  219 
  220 {{< code-toggle >}}
  221 Title: A Propos
  222 slug: "a-propos"
  223 {{< /code-toggle >}}
  224 
  225 At render, Hugo will build both `/about/` and `/fr/a-propos/` while maintaining their translation linking.
  226 
  227 {{% note %}}
  228 If using `url`, remember to include the language part as well: `/fr/compagnie/a-propos/`.
  229 {{%/ note %}}
  230 
  231 ### Page Bundles
  232 
  233 To avoid the burden of having to duplicate files, each Page Bundle inherits the resources of its linked translated pages' bundles except for the content files (markdown files, html files etc...).
  234 
  235 Therefore, from within a template, the page will have access to the files from all linked pages' bundles.
  236 
  237 If, across the linked bundles, two or more files share the same basename, only one will be included and chosen as follows:
  238 
  239 * File from current language bundle, if present.
  240 * First file found across bundles by order of language `Weight`.
  241 
  242 {{% note %}}
  243 Page Bundle resources follow the same language assignment logic as content files, both by filename (`image.jpg`, `image.fr.jpg`) and by directory (`english/about/header.jpg`, `french/about/header.jpg`).
  244 {{%/ note %}}
  245 
  246 ## Reference the Translated Content
  247 
  248 To create a list of links to translated content, use a template similar to the following:
  249 
  250 {{< code file="layouts/partials/i18nlist.html" >}}
  251 {{ if .IsTranslated }}
  252 <h4>{{ i18n "translations" }}</h4>
  253 <ul>
  254   {{ range .Translations }}
  255   <li>
  256     <a href="{{ .Permalink }}">{{ .Lang }}: {{ .Title }}{{ if .IsPage }} ({{ i18n "wordCount" . }}){{ end }}</a>
  257   </li>
  258   {{ end }}
  259 </ul>
  260 {{ end }}
  261 {{< /code >}}
  262 
  263 The above can be put in a `partial` (i.e., inside `layouts/partials/`) and included in any template, whether a [single content page][contenttemplate] or the [homepage]. It will not print anything if there are no translations for a given page.
  264 
  265 The above also uses the [`i18n` function][i18func] described in the next section.
  266 
  267 ### List All Available Languages
  268 
  269 `.AllTranslations` on a `Page` can be used to list all translations, including the page itself. On the home page it can be used to build a language navigator:
  270 
  271 {{< code file="layouts/partials/allLanguages.html" >}}
  272 <ul>
  273 {{ range $.Site.Home.AllTranslations }}
  274 <li><a href="{{ .Permalink }}">{{ .Language.LanguageName }}</a></li>
  275 {{ end }}
  276 </ul>
  277 {{< /code >}}
  278 
  279 ## Translation of Strings
  280 
  281 Hugo uses [go-i18n] to support string translations. [See the project's source repository][go-i18n-source] to find tools that will help you manage your translation workflows.
  282 
  283 Translations are collected from the `themes/<THEME>/i18n/` folder (built into the theme), as well as translations present in `i18n/` at the root of your project. In the `i18n`, the translations will be merged and take precedence over what is in the theme folder. Language files should be named according to [RFC 5646] with names such as `en-US.toml`, `fr.toml`, etc.
  284 
  285 Artificial languages with private use subtags as defined in [RFC 5646 &#167; 2.2.7](https://datatracker.ietf.org/doc/html/rfc5646#section-2.2.7) are also supported. You may omit the `art-x-` prefix for brevity. For example:
  286 
  287 ```text
  288 art-x-hugolang
  289 hugolang
  290 ```
  291 
  292 Private use subtags must not exceed 8 alphanumeric characters.
  293 
  294 ### Query basic translation
  295 
  296 From within your templates, use the `i18n` function like this:
  297 
  298 ```go-html-template
  299 {{ i18n "home" }}
  300 ```
  301 
  302 The function will search for the `"home"` id:
  303 
  304 {{< code-toggle file="i18n/en-US" >}}
  305 [home]
  306 other = "Home"
  307 {{< /code-toggle >}}
  308 
  309 The result will be
  310 
  311 ```text
  312 Home
  313 ```
  314 
  315 ### Query a flexible translation with variables
  316 
  317 Often you will want to use the page variables in the translation strings. To do so, pass the `.` context when calling `i18n`:
  318 
  319 ```go-html-template
  320 {{ i18n "wordCount" . }}
  321 ```
  322 
  323 The function will pass the `.` context to the `"wordCount"` id:
  324 
  325 {{< code-toggle file="i18n/en-US" >}}
  326 [wordCount]
  327 other = "This article has {{ .WordCount }} words."
  328 {{< /code-toggle >}}
  329 
  330 Assume `.WordCount` in the context has value is 101. The result will be:
  331 
  332 ```text
  333 This article has 101 words.
  334 ```
  335 
  336 ### Query a singular/plural translation
  337 
  338 In order to meet singular/plural requirement, you must pass a dictionary (map) with a numeric `.Count` property to the `i18n` function. The below example uses `.ReadingTime` variable which has a built-in `.Count` property.
  339 
  340 ```go-html-template
  341 {{ i18n "readingTime" .ReadingTime }}
  342 ```
  343 
  344 The function will read `.Count` from `.ReadingTime` and evaluate where the number is singular (`one`) or plural (`other`). After that, it will pass to `readingTime` id:
  345 
  346 {{< code-toggle file="i18n/en-US" >}}
  347 [readingTime]
  348 one = "One minute to read"
  349 other = "{{.Count}} minutes to read"
  350 {{< /code-toggle >}}
  351 
  352 Assume `.ReadingTime.Count` in the context has value of 525600. The result will be:
  353 
  354 ```text
  355 525600 minutes to read
  356 ```
  357 
  358 If `.ReadingTime.Count` in the context has value is 1. The result is:
  359 
  360 ```text
  361 One minute to read
  362 ```
  363 
  364 In case you need to pass custom data: (`(dict "Count" 25)` is minimum requirement)
  365 
  366 ```go-html-template
  367 {{ i18n "readingTime" (dict "Count" 25 "FirstArgument" true "SecondArgument" false "Etc" "so on, so far") }}
  368 ```
  369 
  370 ## Localization
  371 
  372 The following localization examples assume your site's primary language is English, with translations to French and German.
  373 
  374 {{< code-toggle file="config" >}}
  375 defaultContentLang = 'en'
  376 
  377 [languages]
  378 [languages.en]
  379 contentDir = 'content/en'
  380 languageName = 'English'
  381 weight = 1
  382 [languages.fr]
  383 contentDir = 'content/fr'
  384 languageName = 'Français'
  385 weight = 2
  386 [languages.de]
  387 contentDir = 'content/de'
  388 languageName = 'Deutsch'
  389 weight = 3
  390 
  391 {{< /code-toggle >}}
  392 
  393 ### Dates
  394 
  395 With this front matter:
  396 
  397 {{< code-toggle >}}
  398 date = 2021-11-03T12:34:56+01:00
  399 {{< /code-toggle >}}
  400 
  401 And this template code:
  402 
  403 ```go-html-template
  404 {{ .Date | time.Format ":date_full" }}
  405 ```
  406 
  407 The rendered page displays:
  408 
  409 Language|Value
  410 :--|:--
  411 English|Wednesday, November 3, 2021
  412 Français|mercredi 3 novembre 2021
  413 Deutsch|Mittwoch, 3. November 2021
  414 
  415 See [time.Format] for details.
  416 
  417 ### Currency
  418 
  419 With this template code:
  420 
  421 ```go-html-template
  422 {{ 512.5032 | lang.FormatCurrency 2 "USD" }}
  423 ```
  424 
  425 The rendered page displays:
  426 
  427 Language|Value
  428 :--|:--
  429 English|$512.50
  430 Français|512,50 $US
  431 Deutsch|512,50 $
  432 
  433 See [lang.FormatCurrency] and [lang.FormatAccounting] for details.
  434 
  435 ### Numbers
  436 
  437 With this template code:
  438 
  439 ```go-html-template
  440 {{ 512.5032 | lang.FormatNumber 2 }}
  441 ```
  442 
  443 The rendered page displays:
  444 
  445 Language|Value
  446 :--|:--
  447 English|512.50
  448 Français|512,50
  449 Deutsch|512,50
  450 
  451 See [lang.FormatNumber] and [lang.FormatNumberCustom] for details.
  452 
  453 ### Percentages
  454 
  455 With this template code:
  456 
  457 ```go-html-template
  458 {{ 512.5032 | lang.FormatPercent 2 }} ---> 512.50%
  459 ```
  460 
  461 The rendered page displays:
  462 
  463 Language|Value
  464 :--|:--
  465 English|512.50%
  466 Français|512,50 %
  467 Deutsch|512,50 %
  468 
  469 See [lang.FormatPercent] for details.
  470 
  471 ## Menus
  472 
  473 You can define your menus for each language independently. Creating multilingual menus works just like [creating regular menus][menus], except they're defined in language-specific blocks in the configuration file:
  474 
  475 {{< code-toggle file="config" >}}
  476 defaultContentLanguage = "en"
  477 
  478 [languages.en]
  479 weight = 0
  480 languageName = "English"
  481 
  482 [[languages.en.menu.main]]
  483 url    = "/"
  484 name   = "Home"
  485 weight = 0
  486 
  487 [languages.de]
  488 weight = 10
  489 languageName = "Deutsch"
  490 
  491 [[languages.de.menu.main]]
  492 url    = "/"
  493 name   = "Startseite"
  494 weight = 0
  495 {{< /code-toggle >}}
  496 
  497 The rendering of the main navigation works as usual. `.Site.Menus` will just contain the menu in the current language. Note that `absLangURL` below will link to the correct locale of your website. Without it, menu entries in all languages would link to the English version, since it's the default content language that resides in the root directory.
  498 
  499 ```go-html-template
  500 <ul>
  501     {{- $currentPage := . -}}
  502     {{ range .Site.Menus.main -}}
  503     <li class="{{ if $currentPage.IsMenuCurrent "main" . }}active{{ end }}">
  504         <a href="{{ .URL | absLangURL }}">{{ .Name }}</a>
  505     </li>
  506     {{- end }}
  507 </ul>
  508 ```
  509 
  510 ## Missing Translations
  511 
  512 If a string does not have a translation for the current language, Hugo will use the value from the default language. If no default value is set, an empty string will be shown.
  513 
  514 While translating a Hugo website, it can be handy to have a visual indicator of missing translations. The [`enableMissingTranslationPlaceholders` configuration option][config] will flag all untranslated strings with the placeholder `[i18n] identifier`, where `identifier` is the id of the missing translation.
  515 
  516 {{% note %}}
  517 Hugo will generate your website with these missing translation placeholders. It might not be suitable for production environments.
  518 {{% /note %}}
  519 
  520 For merging of content from other languages (i.e. missing content translations), see [lang.Merge].
  521 
  522 To track down missing translation strings, run Hugo with the `--printI18nWarnings` flag:
  523 
  524 ```bash
  525 hugo --printI18nWarnings | grep i18n
  526 i18n|MISSING_TRANSLATION|en|wordCount
  527 ```
  528 
  529 ## Multilingual Themes support
  530 
  531 To support Multilingual mode in your themes, some considerations must be taken for the URLs in the templates. If there is more than one language, URLs must meet the following criteria:
  532 
  533 * Come from the built-in `.Permalink` or `.RelPermalink`
  534 * Be constructed with the [`relLangURL` template function][rellangurl] or the [`absLangURL` template function][abslangurl] **OR** be prefixed with `{{ .LanguagePrefix }}`
  535 
  536 If there is more than one language defined, the `LanguagePrefix` variable will equal `/en` (or whatever your `CurrentLanguage` is). If not enabled, it will be an empty string (and is therefore harmless for single-language Hugo websites).
  537 
  538 [abslangurl]: /functions/abslangurl
  539 [config]: /getting-started/configuration/
  540 [contenttemplate]: /templates/single-page-templates/
  541 [go-i18n-source]: https://github.com/nicksnyder/go-i18n
  542 [go-i18n]: https://github.com/nicksnyder/go-i18n
  543 [homepage]: /templates/homepage/
  544 [Hugo Multilingual Part 1: Content translation]: https://regisphilibert.com/blog/2018/08/hugo-multilingual-part-1-managing-content-translation/
  545 [i18func]: /functions/i18n/
  546 [lang.FormatAccounting]: /functions/lang/#langformataccounting
  547 [lang.FormatCurrency]: /functions/lang/#langformatcurrency
  548 [lang.FormatNumber]: /functions/lang/#langformatnumber
  549 [lang.FormatNumberCustom]: /functions/lang/#langformatnumbercustom
  550 [lang.FormatPercent]: /functions/lang/#langformatpercent
  551 [lang.Merge]: /functions/lang.merge/
  552 [menus]: /content-management/menus/
  553 [OS environment]: /getting-started/configuration/#configure-with-environment-variables
  554 [rellangurl]: /functions/rellangurl
  555 [RFC 5646]: https://tools.ietf.org/html/rfc5646
  556 [single page templates]: /templates/single-page-templates/
  557 [time.Format]: /functions/dateformat