Hugo i18n Automatic Language Redirection

      β˜• 3 min read

Hugo has really neat support for i18n. Unfortunately, it does not provide a straitforward way to redirect your visitors automatically according to their web browser language preferences. The good news is that Hugo authors leave a window open for solving this problem.

The Problem

My site is running on two languages: English and Chinese. I have defaultContentLanguageInSubdir set to true and defaultContentLanguage set to en. When visitors came to root / of my site, their web browsers got following response:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<!DOCTYPE html>
<html>
<head>
<title>https://nanmu.me/en</title>
<link rel="canonical" href="https://nanmu.me/en"/>
<meta name="robots" content="noindex">
<meta charset="utf-8" />
<meta http-equiv="refresh" content="0; url=https://nanmu.me/en" />
</head>
</html>

Browsers see http-equiv="refresh" meta and then redirect. Search engines see noindex meta and does not index this page.

However, redirecting every visitor to English version blindly is not very user-friendly, how to redirect by user’s language preference?

The Open Window

After digging into doc and code, I found one can actually customize these redirection pages by creating an alias.html template in the layouts folder of your site (i.e., layouts/alias.html).

For example, here is the default _internal/alias.html template, looking familiar, right?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<!DOCTYPE html>
<html>
<head>
<title>{{ .Permalink }}</title>
<link rel="canonical" href="{{ .Permalink }}"/>
<meta name="robots" content="noindex">
<meta charset="utf-8" />
<meta http-equiv="refresh" content="0; url={{ .Permalink }}" />
</head>
</html>

Solution

The road is straight now:

  1. create my own layouts/alias.html;
  2. use javascript to detect user’s language preference and redirect;
  3. visitors are happier! :D
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<!DOCTYPE html>
<html>
<head>
    <title>{{ .Permalink }}</title>
    <link rel="canonical" href="{{ .Permalink }}"/>
    <meta name="robots" content="noindex">
    <meta charset="utf-8"/>
    <noscript>
        <meta http-equiv="refresh" content="0; url={{ .Permalink }}"/>
    </noscript>
    <script>
      ;(function () {
        // Only do i18n at root, 
        // otherwise, redirect immediately
        if (window.location.pathname !== '/') {
          window.location.replace('{{ .Permalink }}')
          return
        }

        var getFirstBrowserLanguage = function () {
          var nav = window.navigator,
          browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'],
          i,
          language

          if (Array.isArray(nav.languages)) {
            for (i = 0; i < nav.languages.length; i++) {
              language = nav.languages[i]
              if (language && language.length) {
                return language
              }
            }
          }

          // support for other well known properties in browsers
          for (i = 0; i < browserLanguagePropertyKeys.length; i++) {
            language = nav[browserLanguagePropertyKeys[i]]
            if (language && language.length) {
              return language
            }
          }
          return 'en'
        }

        var preferLang = getFirstBrowserLanguage()
        if (preferLang.indexOf('zh') !== -1) {
          // visitor prefers Chinese
          window.location.replace('/zh-cn/')
        } else {
          // fallback to English
          window.location.replace('/en/')
        }
      })()
    </script>
</head>
<body>
<h1>Rerouting</h1>
<p>You should be rerouted in a jiff, if not, <a href="{{ .Permalink }}">click here</a>.</p>
</body>
</html>

Credits

Thanks to Thomas Enzinger for getFirstBrowserLanguage() in the Javascript above.

Share on

nanmu42
WRITTEN BY
nanmu42
To build beautiful things beautifully.


What's on this Page