xPulse
πŸ‡¬πŸ‡§ EN
Pages
Contents

Spec β€” @xpulse/i18n

Status: ACCEPTED Β· March 2026 Dependencies: @xpulse/event, @xpulse/config, @xpulse/router Optional: @xpulse/template

Principles

Route wrapping

@xpulse/i18n wraps router.register() during its own init. All subsequent route registrations (doc, controller, ...) are automatically extended with /:lang/ variants β€” regardless of their init order.

@xpulse/router:init
└── router.register() = originalRegister()
@xpulse/i18n:init (depends: ["xpulse-router"])
└── router.register() = wrapper()
@xpulse/doc:init
└── router.register('GET', '/doc/...', handler)
└── wrapper automatically registers:
GET /doc/... req.lang = detect(req)
GET /de/doc/... req.lang = 'de'
GET /en/doc/... req.lang = 'en'

FOUC redirect script

Inline script in <head>, injected into all HTML responses via http:response:before:

(function(){try{
var l=localStorage.getItem('xpulse_lang');
var s=["en"]; // non-default langs
if(l&&s.includes(l)&&!location.pathname.startsWith('/'+l+'/')){
location.replace('/'+l+location.pathname+location.search);
}
}catch(e){}})();

No FOUC β€” the browser never sees the wrong language version.

SEO

With use-seo: true, automatically injected into all HTML responses:

<link rel="alternate" hreflang="de" href="https://xpulse.one/tool/chat/" />
<link rel="alternate" hreflang="en" href="https://xpulse.one/en/tool/chat/" />
<link rel="alternate" hreflang="x-default" href="https://xpulse.one/tool/chat/" />

Package structure

@xpulse/i18n/
src/
index.js ← init, lang, t, router-wrap
detect.js ← detectLang, stripLang, langFromPath
middleware.js ← langHandler, detectHandler, hookResponses
template-methods/
lang-switcher.js ← langSwitcher()
html-lang.js ← htmlLang()
xpulse.json
package.json
en/spec.md 2026-03-31