Rino.js
Language

Content Navigation:


Published: 2026-01-24T10:30:00.000Z

Internationalization (i18n)

Rino.js provides JSON-based internationalization for both the development server and static generation. Use <lang>key</lang> in pages or components, then define the value in a JSON file that matches the page path.

Configuration

Add the locales to rino-config.js:

export default {
  i18n: {
    defaultLocale: "en",
    locales: ["en", "ko"],
  },
};

The default locale is generated at the normal page path. Other locales are generated under their locale prefix:

pages/index.html -> dist/index.html     (English)
                 -> dist/ko/index.html  (Korean)

Only locales listed in i18n.locales are generated.

Translation files

Locale files under i18n/{locale}/ must follow the same path as the corresponding page:

pages/index.html       i18n/en/index.json       i18n/ko/index.json
pages/about.html       i18n/en/about.json       i18n/ko/about.json
pages/docs/start.html  i18n/en/docs/start.json  i18n/ko/docs/start.json

In pages/index.html:

<h1><lang>header.title</lang></h1>
<p><lang>body.content[0]</lang></p>

In i18n/en/index.json:

{
  "header": { "title": "Welcome" },
  "body": { "content": ["Build a static site with Rino.js."] }
}

Nested objects use dot paths, and arrays use bracket paths such as items[0].label.

Fallbacks and literal tags

For a non-default locale, Rino.js merges its JSON over the default-locale JSON. A missing Korean value therefore falls back to English when English is the default locale. If a key is unavailable in both files, the <lang> tag remains in the output instead of failing the build.

Escape a language tag when you want to display it literally:

\<lang>header.title\</lang>

This produces:

<lang>header.title</lang>