i18n plugin is used to automatically redirect your website visitors from specific countries or with a specific browser language setting to a corresponding internationalized version of the URL. For example, a common practice is to have alternate translated versions of webpages with a langage code prefix, i.e. the Spanish version of
/about/ would be located at
/es/about/ and the French version at
i18n plugin can be configured to redirect based on either the
Accept-Language header or the country of the visitor based on a geo-ip lookup.
The url prefixes such as
fr/, etc. are called "locales". While they commonly are based on ISO 639-1 two letter codes, you can use any strings you like.
The plugin assumes that the build process that generates your static site duplicates the site content in sub-folders corresponding to your locale names, in this case
es. The pages not nested beneath one of the locale folders represents the
├── 2018 │ └── 11 │ └── 04 │ └── welcome │ └── index.html ├── about │ └── index.html ├── de │ ├── 2018 │ │ └── 11 │ │ └── 04 │ │ └── welcome │ │ └── index.html │ ├── about │ │ └── index.html │ └── index.html ├── es │ ├── 2018 │ │ └── 11 │ │ └── 04 │ │ └── welcome │ │ └── index.html │ ├── about │ │ └── index.html │ └── index.html ├── fr │ ├── 2018 │ │ └── 11 │ │ └── 04 │ │ └── welcome │ │ └── index.html │ ├── about │ │ └── index.html │ └── index.html └── index.html
Static Site Generators
This plugin works extremely well in conjunction with the i18n capabilities of popular static site generators. All of the following emit a static site in the structure described above.
- Jekyll Polyglot plugin
- Jekyll Multiple Languages plugin
- Hugo multilingual mode
- Gatsby i18n plugin
- Hexo Internationalization (i18n)
- VuePress Internationalization
Check the documentation for your static generator of choice. Chances are it either supports i18n output natively, or there exists a plugin that enables it. Checkout our demo site which uses jekyll-polyglot.
i18n plugin in your
plugins: - name: i18n options: defaultLocale: en locales: # Redirect users whose Accept-Language header is Spanish "es" *OR* if they are # located in Mexico, Costa Rica, or Spain. es: languages: [es] countries: [mx, cr, es] de: languages: [de] fr: languages: [fr] countries: [fr] - name: webpage
defaultLocaleThe name of your site's default locale. This locale is not represented in the url path.
localesDictionary of your alternative locales. The keys represent the locale prefixes that appear in your site's locale specific urls, i.e. the
locale.languagesThe list of languages that should redirect to the locale URL. Each language must be a two letter ISO 639-1 code. Typically you will only have a single language specified, but there may be cases where you want two closely related languages to share the same content. If the
Accept-Languageheader corresponds to _any_ of the specified languages, they will be redirected to the corresponding locale URL.
The list of countries that should redirect to the locale URL. Each value must be an ISO 3166-1 alpha-2 country code. The country is based on a conversion of the incoming request IP address. If the request country matches any value in the list, the request is redirected to the locale specific URL.
Locale redirect logic
- When a request arrives, the browser language from the
Accept-Languageand the country identified by the IP address are extracted.
- Look for the first locale with a match in either the
- If a match is found, determine if the locale in the request is different than the locale matching the request. If so,
302redirect to the corresponding locale URL.
- If there is a cookie
aerobatic-locale, it takes precedence over the HTTP headers. See allowing user to select locale
The following table depicts what would happen under different sceneario assuming the sample configuration show above is in effect and the incoming request is for homepage, i.e. https://www.site.com:
|US||en||Render the homepage||Country no language match a locale, so render the default|
|US||es||Redirect to ||The language |
|ES||en||Redirect to ||The country |
|US||de||Redirect to ||The language |
|DE||en||Render the default homepage||The |
|IT||it||Render the default homepage||The plugin configuration does not specify any locale for the Italian language or the country of Italy|
Although the examples on this page use English (
en) as the default, that's definitely not
required. Your default locale could just as well be Chinese, Swedish, Russian, or Portugese.
Allowing user to select locale
So far we have only discussed automatically redirecting the user to a locale based on their request headers. However you might wish to allow the user to manually choose their locale and have this value override whatever their headers say. A typical UX for this is to provide some sort of language selector widget like so:
You can tack on a special querystring parameter
?__locale=es. This will cause the server to set a cookie called
aerobatic-locale with the specified locale then redirect to the appropriate locale-specific URL. For example a request to
https://site.com/about?__locale=es will redirect to
https://site.com/es/about. Subsequent requests will continue to honor the value in the cookie rather than inspect the
Accept-Language header and the origin country.
Fallback to default locale
It might not be practical or desirable to provide a translated version of every single page on your site. If a locale specific URL is requested and a webpage does not exist the user is redirected to the default locale. For example
https://site.com/fr/english-only-page will redirect to
https://site.com/english-only-page. In this case a
301 permanant redirect is used.
Note that the static site generator may create a duplicate copy of the page in the default language at the locale specific path. This is how
jekyll-polyglot works (see fallback language support). In this case just make sure that the
<link rel="canonical"> points to the default locale URL to avoid duplicate content issues for SEO.
Other use cases
i18n plugin for translations to different languages is the most common use case, however there are other use cases as well. For example, say you have a statically generated English language eCommerce site and you'd like to show localized currencies to users from a select set of countries. In this case the locale names would refer to countries rather than languages. Here's how you could configure that:
plugins: - name: i18n options: defaultLocale: en locales: # Redirect Canadian visitors to /ca/* ca: countries: [ca] # Redirect users in Great Britian, Gibralter, and Zimbabe to /uk/* uk: countries: [gb, uk, gi, zw] # Redirect Chinese users to /cn/* cn: countries: [cn]
In order to test that the i18n plugin is behaving as expected, it is useful to be able to simulate HTTP requests with different languages and from different countries. Changing your browser language is straightforward using Postman or a browser extension such as Quick Language Switcher.
Simulating a different country is tricker since it entails proxying your request through an IP address in that country. To make this easier we provide a special querystring parameter
__country that you can append to a URL that will override the IP based country logic. For example to simulate a request from China, just request
?__localequerystring which you can use in your site's locale selector, the
?__countryquerystring is only intended for your personal testing.