⚠️ AlabJS is under active development and not yet production-ready. APIs may change before v1.0. Feel free to explore, contribute, or star the repo.
Skip to content

AlabJS's i18n module adds locale prefixes to your routes (/en/, /fil/, etc.), detects the user's preferred language from the Accept-Language header, and provides React context for the active locale.

Setup

ts
// i18n.config.ts (project root)
import { createI18nConfig } from "alabjs/i18n";

export default createI18nConfig({
  locales: ["en", "fil", "es"],
  defaultLocale: "en",
});
ts
// alabjs.config.ts
import i18n from "./i18n.config";

export default {
  i18n,
};

With this config, AlabJS rewrites your route manifest so every route is available under a locale prefix:

FileRoutes
app/page.tsx/en/, /fil/, /es/
app/about/page.tsx/en/about, /fil/about, /es/about
app/posts/[slug]/page.tsx/en/posts/:slug, /fil/posts/:slug, /es/posts/:slug

The bare / path redirects to the default locale.

Reading the active locale

tsx
import { useLocale } from "alabjs/i18n";

export default function Nav() {
  const { locale, locales, setLocale } = useLocale();

  return (
    <nav>
      <span>Current: {locale}</span>
      {locales.map((l) => (
        <button key={l} onClick={() => setLocale(l)}>
          {l}
        </button>
      ))}
    </nav>
  );
}

setLocale navigates to the same page under the new locale prefix using history.pushState.

LocaleLink is a drop-in replacement for <a> that automatically prefixes hrefs with the current locale:

tsx
import { LocaleLink } from "alabjs/i18n";

// Current locale: "fil"
// Renders: <a href="/fil/about">About</a>
<LocaleLink href="/about">About</LocaleLink>

Server-side locale detection

Use detectLocale inside a server function to resolve the locale from the incoming request:

ts
import { defineServerFn } from "alabjs/server";
import { detectLocale } from "alabjs/i18n";
import i18nConfig from "../../i18n.config";

export const getContent = defineServerFn(async (_, { headers }) => {
  const locale = detectLocale(headers.get("accept-language") ?? "", i18nConfig);
  // locale: "fil" | "en" | "es"

  const content = await db.content.findFirst({ where: { locale } });
  return content;
});

Translations

AlabJS does not ship a built-in translation runtime. Use any i18n library alongside the locale context:

ts
// Using your preferred library (e.g. i18next, lingui, typesafe-i18n)
import i18next from "i18next";
import { useLocale } from "alabjs/i18n";

export function useT() {
  const { locale } = useLocale();
  return (key: string) => i18next.t(key, { lng: locale });
}

API Reference

createI18nConfig(options): I18nConfig

OptionTypeDescription
localesstring[]All supported locale codes
defaultLocalestringLocale used when no prefix is present
detection"header" | "cookie" | "path"Detection strategy (default: "header")

useLocale(): LocaleContext

React hook. Returns { locale, locales, setLocale }. Must be inside a LocaleProvider.

LocaleProvider

The root layout automatically wraps pages in LocaleProvider. You do not need to add it manually unless building a custom entry point.

Props: all <a> props. Automatically injects the current locale prefix into href.

detectLocale(acceptLanguage: string, config: I18nConfig): string

Parses Accept-Language and returns the best-matching locale from the config, falling back to defaultLocale.

Released under the MIT License.