Skip to content

Repository files navigation

hexo-fluent

Project Fluent localization support for Hexo themes.

hexo-fluent is additive. It does not replace Hexo's existing hexo-i18n integration or the __() and _p() template functions. A theme may use either system, or both during a migration.

Important

This project is currently experimental. Until a 1.0 release, minor versions may refine the resource conventions and template API based on theme-author feedback.

Requirements

  • Hexo 8 or later
  • Node.js 20.19 or later

Installation

Until the first npm release, install the plugin directly from GitHub in a Hexo site or declare it as a dependency of a theme:

npm install github:hexojs/hexo-fluent

After the package is published to npm, it can be installed with:

npm install hexo-fluent

Hexo automatically loads dependencies whose names start with hexo-.

Translation resources

Place Fluent Translation List (.ftl) resources below either languages/ or locales/ in the theme. Both a single file per locale and multiple files per locale are supported:

themes/example/
├── languages/
│   ├── en.ftl
│   └── zh-CN.ftl
└── locales/
    ├── en/
    │   ├── navigation.ftl
    │   └── posts.ftl
    └── zh-CN/
        ├── navigation.ftl
        └── posts.ftl

For a nested resource, the first directory after languages/ or locales/ is the locale. Locale names are normalized as BCP 47 language tags. For example, zh_cn is normalized to zh-CN.

An optional default.ftl resource acts as the last fallback:

languages/default.ftl

Example resource:

welcome = Welcome, { $name }!

post-count =
    { $count ->
        [one] One post
       *[other] { $count } posts
    }

open-post =
    .title = Open this post

Resources are reloaded when running Hexo in watch or server mode. Multiple files for the same locale are loaded in path order. Duplicate message IDs are reported as warnings and the first definition wins.

Template API

The plugin adds fluent() and fluent_attr() to template locals:

<h1><%= fluent('welcome', { name: config.author }) %></h1>

<p><%= fluent('post-count', { count: site.posts.length }) %></p>

<a title="<%= fluent_attr('open-post', 'title') %>">...</a>

The formatter also exposes attr() and has():

fluent.attr('open-post', 'title')
fluent.has('post-count')

If a message or attribute cannot be found in the negotiated fallback chain, its ID is returned. Fluent formatting errors are reported as Hexo warnings, while Fluent still produces its best-effort result.

Locale selection and fallback

The current page locale is selected in this order:

  1. page.lang or page.language
  2. A locale prefix matched by Hexo's i18n_dir
  3. The first locale in the site's language configuration
  4. The first available Fluent locale

Message fallback uses Fluent language negotiation, followed by the configured site languages and then default.ftl.

Configuration

Fluent isolates interpolated variables with Unicode bidi isolation characters by default. This is useful for mixed left-to-right and right-to-left text and matches Fluent's default behavior. It can be disabled in the site configuration:

fluent:
  use_isolating: false

Existing Hexo internationalization

The existing template functions remain unchanged:

<%= __('menu.home') %>
<%= _p('posts', site.posts.length) %>
<%= fluent('post-count', { count: site.posts.length }) %>

hexo.theme.i18n continues to use hexo-i18n. Fluent bundles are available to theme scripts as hexo.theme.fluent.

Development

npm install
npm test

The test suite covers resource paths, locale negotiation, fallback, plural selection, attributes, resource updates and deletion, diagnostics, and Hexo plugin registration.

About

Fluent localization support for Hexo themes.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages