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:

create my own layouts/alias.html ; use javascript to detect user’s language preference and redirect; 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