diff --git a/content/content/multilingual.md b/content/content/multilingual.md
new file mode 100644
index 000000000..8edc6a600
--- /dev/null
+++ b/content/content/multilingual.md
@@ -0,0 +1,238 @@
+---
+date: 2016-01-02T21:21:00Z
+menu:
+ main:
+ parent: content
+next: /content/example
+prev: /content/summaries
+title: Multilingual Mode
+weight: 68
+toc: true
+---
+
+Since version 0.17, Hugo supports a native Multilingual mode. In your
+top-level `config.yaml` (or equivalent), you define the available
+languages in a `Multilingual` section such as:
+
+```
+Multilingual:
+ en:
+ weight: 1
+ title: "My blog"
+ params:
+ linkedin: "english-link"
+ fr:
+ weight: 2
+
+ title: "Mon blog"
+ params:
+ linkedin: "lien-francais"
+ copyright: "Tout est miens"
+
+copyright: "Everything is mine"
+```
+
+Anything not defined in a `[lang]:` block will fall back to the global
+value for that key (like `copyright` for the `en` lang in this
+example).
+
+With the config above, all content, sitemap, RSS feeds, paginations
+and taxonomy pages will be rendered under `/en` in English, and under
+`/fr` in French.
+
+Only those keys are read under `Multilingual`: `weight`, `title`,
+`author`, `social`, `languageCode`, `copyright`, `disqusShortname`,
+`params` (which can contain a map of several other keys).
+
+
+### Translating your content
+
+Translated articles are picked up by the name of the content files.
+
+Example of translated articles:
+
+1. `/content/about.en.md`
+2. `/content/about.fr.md`
+
+You can also have:
+
+1. `/content/about.md`
+2. `/content/about.fr.md`
+
+in which case the config variable `DefaultContentLanguage` will be
+used to affect the default language `about.md`. This way, you can
+slowly start to translate your current content without having to
+rename everything.
+
+If left unspecified, the value for `DefaultContentLanguage` defaults
+to `en`.
+
+By having the same _base file name_, the content pieces are linked
+together as translated pieces. Only the content pieces in the language
+defined by **.Site.CurrentLanguage** will be rendered in a run of
+`hugo`. The translated content will be available in the
+`.Page.Translations` so you can create links to the corresponding
+translated pieces.
+
+
+### Language switching links
+
+Here is a simple example if all your pages are translated:
+
+```
+{{if .IsPage}}
+ {{ range $txLang := .Site.Languages }}
+ {{if isset $.Translations $txLang}}
+ {{ i18n ( printf "language_switcher_%s" $txLang ) }}
+ {{end}}
+ {{end}}
+{{end}}
+
+{{if .IsNode}}
+ {{ range $txLang := .Site.Languages }}
+ {{ i18n ( printf "language_switcher_%s" $txLang ) }}
+ {{end}}
+{{end}}
+```
+
+This is a more complete example. It handles missing translations and will support non-multilingual sites. Better for theme authors:
+
+```
+{{if .Site.Multilingual}}
+ {{if .IsPage}}
+ {{ range $txLang := .Site.Languages }}
+ {{if isset $.Translations $txLang}}
+ {{ i18n ( printf "language_switcher_%s" $txLang ) }}
+ {{else}}
+ {{ i18n ( printf "language_switcher_%s" $txLang ) }}
+ {{end}}
+ {{end}}
+ {{end}}
+
+ {{if .IsNode}}
+ {{ range $txLang := .Site.Languages }}
+ {{ i18n ( printf "language_switcher_%s" $txLang ) }}
+ {{end}}
+ {{end}}
+{{end}}
+```
+
+This makes use of the **.Site.Languages** variable to create links to
+the other available languages. The order in which the languages are
+listed is defined by the `weight` attribute in each language under
+`Multilingual`.
+
+This will also require you to have some content in your `i18n/` files
+(see below) that would look like:
+
+```
+- id: language_switcher_en
+ translation: "English"
+- id: language_switcher_fr
+ translation: "Français"
+```
+
+and a copy of this in translations for each language.
+
+As you might notice, node pages link to the root of the other
+available translations (`/en`), as those pages do not necessarily have
+a translated counterpart.
+
+Taxonomies (tags, categories) are completely segregated between
+translations and will have their own tag clouds and list views.
+
+
+### Translation of strings
+
+Hugo uses [go-i18n](https://github.com/nicksnyder/go-i18n) to support
+string translations. Follow the link to find tools to manage your
+translation workflows.
+
+Translations are collected from the `themes/[name]/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. Files in
+there follow RFC 5646 and should be named something like `en-US.yaml`,
+`fr.yaml`, etc..
+
+From within your templates, use the `i18n` function as such:
+
+```
+{{ i18n "home" }}
+```
+
+to use a definition like this one in `i18n/en-US.yaml`:
+
+```
+- id: home
+ translation: "Home"
+```
+
+
+### Multilingual Themes support
+
+To support Multilingual mode in your themes, you only need to make
+sure URLs defined manually (those not using `.Permalink` or `.URL`
+variables) in your templates are prefixed with `{{
+.Site.LanguagePrefix }}`. If `Multilingual` mode is enabled, the
+`LanguagePrefix` variable will equal `"/en"` (or whatever your
+`CurrentLanguage` is). If not enabled, it will be an empty string, so
+it is harmless for non-multilingual sites.
+
+
+### Multilingual index.html and 404.html
+
+To redirect your users to their closest language, drop an `index.html`
+in `/static` of your site, with the following content (tailored to
+your needs) to redirect based on their browser's language:
+
+```
+
+
+
+```
+
+An even simpler version will always redirect your users to a given language:
+
+```
+
+
+
+```
+
+You can do something similar with your `404.html` page, as you don't
+know the language of someone arriving at a non-existing page. You
+could inspect the prefix of the navigator path in Javascript or use
+the browser's language detection like above.
+
+
+### Sitemaps
+
+As sitemaps are generated once per language and live in
+`[lang]/sitemap.xml`. Write this content in `static/sitemap.xml` to
+link all your sitemaps together:
+
+```
+
+
+
+ https://example.com/en/sitemap.xml
+
+
+ https://example.com/fr/sitemap.xml
+
+
+```
+
+and explicitly list all the languages you want referenced.
diff --git a/content/taxonomies/displaying.md b/content/taxonomies/displaying.md
index 8719807f9..c66c3de56 100644
--- a/content/taxonomies/displaying.md
+++ b/content/taxonomies/displaying.md
@@ -38,7 +38,7 @@ each content piece are located in the usual place
@@ -110,7 +110,8 @@ The following example displays all tag keys:
@@ -120,7 +121,7 @@ This example will list all taxonomies, each of their keys and all the content as
{{ range $taxonomyname, $taxonomy := .Site.Taxonomies }}
- - {{ $taxonomyname }}
+
- {{ $taxonomyname }}
{{ range $key, $value := $taxonomy }}
- {{ $key }}
@@ -135,4 +136,3 @@ This example will list all taxonomies, each of their keys and all the content as
{{ end }}
-
diff --git a/content/taxonomies/ordering.md b/content/taxonomies/ordering.md
index baecd7b4c..ac86bc69d 100644
--- a/content/taxonomies/ordering.md
+++ b/content/taxonomies/ordering.md
@@ -29,7 +29,7 @@ Taxonomies can be ordered by either alphabetical key or by the number of content
@@ -38,7 +38,7 @@ Taxonomies can be ordered by either alphabetical key or by the number of content
diff --git a/content/templates/functions.md b/content/templates/functions.md
index cd212b85d..aa55ced4f 100644
--- a/content/templates/functions.md
+++ b/content/templates/functions.md
@@ -435,6 +435,13 @@ e.g.
## Strings
+### printf
+
+Format a string using the standard `fmt.Sprintf` function. See [the go
+doc](https://golang.org/pkg/fmt/) for reference.
+
+e.g., `{{ i18n ( printf "combined_%s" $var ) }}` or `{{ printf "formatted %.2f" 3.1416 }}`
+
### chomp
Removes any trailing newline characters. Useful in a pipeline to remove newlines added by other processing (including `markdownify`).
@@ -726,7 +733,6 @@ CJK-like languages.
```
-
### md5
`md5` hashes the given input and returns its MD5 checksum.
@@ -752,6 +758,23 @@ This can be useful if you want to use Gravatar for generating a unique avatar:
```
+## Internationalization
+
+### i18n
+
+This translates a piece of content based on your `i18n/en-US.yaml`
+(and friends) files. You can use the
+[go-i18n](https://github.com/nicksnyder/go-i18n) tools to manage your
+translations. The translations can exist in both the theme and at the
+root of your repository.
+
+e.g.: `{{ i18n "translation_id" }}`
+
+
+### T
+
+`T` is an alias to `i18n`. E.g. `{{ T "translation_id" }}`.
+>>>>>>> Add multilingual support in Hugo
## Times
@@ -763,7 +786,6 @@ This can be useful if you want to use Gravatar for generating a unique avatar:
* `{{ (time "2016-05-28").YearDay }}` → 149
* `{{ mul 1000 (time "2016-05-28T10:30:00.00+10:00").Unix }}` → 1464395400000 (Unix time in milliseconds)
-
## URLs
### absURL, relURL
diff --git a/content/templates/terms.md b/content/templates/terms.md
index 3e6b43878..3711fd8aa 100644
--- a/content/templates/terms.md
+++ b/content/templates/terms.md
@@ -89,7 +89,7 @@ content tagged with each tag.
{{ $data := .Data }}
{{ range $key, $value := .Data.Terms }}
- - {{ $key }} {{ len $value }}
+ - {{ $key }} {{ len $value }}
{{ end }}
@@ -109,7 +109,7 @@ Another example listing the content for each term (ordered by Date):
{{ $data := .Data }}
{{ range $key,$value := .Data.Terms.ByCount }}
-
+
{{ range $value.Pages.ByDate }}
- {{ .Title }}
@@ -140,7 +140,7 @@ Hugo can order the meta data in two different ways. It can be ordered:
@@ -158,7 +158,7 @@ Hugo can order the meta data in two different ways. It can be ordered:
diff --git a/content/templates/variables.md b/content/templates/variables.md
index 953ba5cb6..8f37dd19f 100644
--- a/content/templates/variables.md
+++ b/content/templates/variables.md
@@ -58,6 +58,8 @@ matter, content or derived from file location.
**.IsPage** Always true for page.
**.Site** See [Site Variables]({{< relref "#site-variables" >}}) below.
**.Hugo** See [Hugo Variables]({{< relref "#hugo-variables" >}}) below.
+**.Translations** A map to other pages with the same filename, but with a different language-extension (like `post.fr.md`). Populated only if `Multilingual` is enabled in your site config.
+**.Lang** Taken from the language extension notation. Populated only if `Multilingual` is enabled for your site config.
## Page Params
@@ -119,9 +121,9 @@ includes taxonomies, lists and the homepage.
**.Site** See [Site Variables]({{< relref "#site-variables" >}}) below.
**.Hugo** See [Hugo Variables]({{< relref "#hugo-variables" >}}) below.
-### Taxonomy Term Variables
+### Taxonomy Terms Node Variables
-[Taxonomy Terms](/templates/terms/) pages are of the type "node" and have the following additional variables.
+[Taxonomy Terms](/templates/terms/) pages are of the type "node" and have the following additional variables. These are available in `layouts/_defaults/terms.html` for example.
**.Data.Singular** The singular name of the taxonomy
**.Data.Plural** The plural name of the taxonomy
@@ -132,14 +134,25 @@ includes taxonomies, lists and the homepage.
The last two can also be reversed: **.Data.Terms.Alphabetical.Reverse**, **.Data.Terms.ByCount.Reverse**.
+### Taxonomies elsewhere
+
+The **.Site.Taxonomies** variable holds all taxonomies defines site-wide. It is a map of the taxonomy name to a list of its values. For example: "tags" -> ["tag1", "tag2", "tag3"]. Each value, though, is not a string but rather a [Taxonomy variable](#the-taxonomy-variable).
+
+#### The Taxonomy variable
+
+The Taxonomy variable, available as **.Site.Taxonomies.tags** for example, contains the list of tags (values) and, for each of those, their corresponding content pages.
+
+
+
## Site Variables
Also available is `.Site` which has the following:
**.Site.BaseURL** The base URL for the site as defined in the site configuration file.
**.Site.RSSLink** The URL for the site RSS.
-**.Site.Taxonomies** The [taxonomies](/taxonomies/usage/) for the entire site. Replaces the now-obsolete `.Site.Indexes` since v0.11.
-**.Site.Pages** Array of all content ordered by Date, newest first. Replaces the now-deprecated `.Site.Recent` starting v0.13.
+**.Site.Taxonomies** The [taxonomies](/taxonomies/usage/) for the entire site. Replaces the now-obsolete `.Site.Indexes` since v0.11. Also see section [Taxonomies elsewhere](#taxonomies-elsewhere).
+**.Site.Pages** Array of all content ordered by Date, newest first. Replaces the now-deprecated `.Site.Recent` starting v0.13. This array contains only the pages in the current language.
+**.Site.AllPages** Array of all pages regardless of their translation.
**.Site.Params** A container holding the values from the `params` section of your site configuration file. For example, a TOML config file might look like this:
baseurl = "http://yoursite.example.com/"
@@ -152,7 +165,7 @@ Also available is `.Site` which has the following:
**.Site.Menus** All of the menus in the site.
**.Site.Title** A string representing the title of the site.
**.Site.Author** A map of the authors as defined in the site configuration.
-**.Site.LanguageCode** A string representing the language as defined in the site configuration.
+**.Site.LanguageCode** A string representing the language as defined in the site configuration. This is mostly used to populate the RSS feeds with the right language code.
**.Site.DisqusShortname** A string representing the shortname of the Disqus shortcode as defined in the site configuration.
**.Site.GoogleAnalytics** A string representing your tracking code for Google Analytics as defined in the site configuration.
**.Site.Copyright** A string representing the copyright of your web site as defined in the site configuration.
@@ -160,6 +173,10 @@ Also available is `.Site` which has the following:
**.Site.Permalinks** A string to override the default permalink format. Defined in the site configuration.
**.Site.BuildDrafts** A boolean (Default: false) to indicate whether to build drafts. Defined in the site configuration.
**.Site.Data** Custom data, see [Data Files](/extras/datafiles/).
+**.Site.Multilingual** Whether the site supports internationalization of the content. With this mode enabled, all your posts' URLs will be prefixed with the language (ex: `/en/2016/01/01/my-post`)
+**.Site.CurrentLanguage** This indicates which language you are currently rendering the website for. When using `Multilingual` mode, will render the site in this language. You can then run `hugo` again with a second `config` file, with the other languages. When using `i18n` and `T` template functions, it will use the `i18n/*.yaml` files (in either `/themes/[yourtheme]/i18n` or the `/i18n`, translations in the latter having precedence).
+**.Site.LanguagePrefix** When `Multilingual` is enabled, this will hold `/{{ .Site.CurrentLanguage}}`, otherwise will be an empty string. Using this to prefix taxonomies or other hard-coded links ensures your keep your theme compatible with Multilingual configurations.
+**.Site.Languages** An ordered list of languages when Multilingual is enabled. Used in your templates to iterate through and create links to different languages.
## File Variables