Hugo I18n JS Module

A super simple and lightweight i18n JS module for Hugo, used to render i18n stuff in JS way.

Modulegithub.com/hugomods/i18n-js
StatsGitHub Stars Used By Used By Used By Used By

Motivation

Hugo provides the i18n feature for templates, it works fine on most cases. However we may want to render the some HTML blocks in JS way in some cases. Imagine there is a JS component requires a Modal to be rendered on pages.

1<div class="my-modal">
2    <div class="my-modal-header">{{ i18n "my_modal_title" }}</div>
3    <div class="my-modal-body">
4      ...
5    </div>
6    <div class="my-modal-footer"></div>
7</div>

The modal markup will be part of every single HTML pages with using Hugo templates, which increase all HTML files size.

It would be better if render in JS way, since only the file size of JS will be increased. So this module comes up, to be used to handle the i18n part in JS.

How it works?

  • Store all translations in memory, you should exclude unused translations yourself.
  • Uses the language specified on the <html> tag when translating, i.e. <html lang="en">, then the en will be used as current language.

Installation

hugo.yaml

1module:
2  imports:
3  - path: github.com/hugomods/i18n-js

hugo.toml

1[module]
2  [[module.imports]]
3    path = 'github.com/hugomods/i18n-js'

hugo.json

1{
2   "module": {
3      "imports": [
4         {
5            "path": "github.com/hugomods/i18n-js"
6         }
7      ]
8   }
9}

APIs

Translator

  • constructor(translations: Translations, fallback: string)
  • translate(key: string, ctx: Context)

Translations

The translations is an object that mapping from language to a set of translation.

Translation

A translation is an object that mapping from key to their formats.

1Record<string, {
2    one?: string;
3    other: string;
4}>

A translation can have one or two formats as following.

  • one: signalize format, optional.
  • other: pluralize format.

The format is a string, which can be formatted with Context, you’ll need to wrap the parameter/placeholder by curly brackets, i.e., Hello {name}.

Context

The context is a name-value pairs.

1Record<string, number | string>
  • count is the reserved name, if count === 1 the one translation’s format will be used, otherwise other will be used.

Let’s say there is a translation.

1{
2    one: "Found {count} result in {time}.",
3    other: "Found {count} results in {time}."
4}
ContextOutput
{ count: 1, time: '1ms'}Found 1 result in 1ms.
{ count: 34, time: '10ms'}Found 34 results in 10ms.

It’s common that to highlight the count, we can achieve this via defining an extra parameter, such as total.

1{
2    one: "Found {total} result in {time}.",
3    other: "Found {total} results in {time}."
4}

And then highlight it in the context, i.e.

1{
2  count: 34,
3  time: '10ms',
4  total: '<span class="highlight">34</span>'
5}

Example

Learn how to use by an example.

 1import Translator from "mods/i18n/translator"
 2// You can also read the translations from .Site.Data and pass it via params.
 3// See https://gohugo.io/hugo-pipes/js/#options.
 4// import { default as params } from '@params'
 5// const translations = params.translations
 6const translations = {
 7    en: {
 8        home: {
 9            other: 'Home'
10        },
11        'search-result': {
12            one: 'Found {count} result.',
13            other: 'Found {count} results.'
14        }
15    },
16    'zh-hans': {
17        home: {
18            other: '主页'
19        },
20        'search-result': {
21            one: '找到 {count} 条结果。',
22            other: '找到 {count} 条结果。'
23        }
24    }
25}
26const i18n = new Translator(translations, "en")
27
28console.log(i18n.translate('home')) // Home
29console.log(i18n.translate('search-result', { count: 1 })) // Found 1 result.
30console.log(i18n.translate('search-result', { count: 8 })) // Found 8 results.