GioJSdocs
On this page

useLocale

Read the locale the server detected for this request, during server rendering and in the browser.

tsx
import { useLocale } from '@gio.js/react';

export function Price({ amount }: { amount: number }) {
  const locale = useLocale() || 'en';
  return <>{new Intl.NumberFormat(locale, { style: 'currency', currency: 'EUR' }).format(amount)}</>;
}

Reference

Parameters

useLocale takes no parameters.

Returns

A string:

  • with [i18n] locales set in gio.toml, one of them: the locale the server detected, or default_locale when nothing matched, spelled exactly as in locales;
  • without [i18n], ''.

How the locale is detected

The Rust server tries the sources in [i18n] detect_from order (default ["path", "accept-language", "cookie"]) and takes the first that names a configured locale:

  • path - a first path segment that is a locale (/fr/about). The prefix is always removed before routing, so the page is app/about/page.tsx and usePathname() is /about.
  • accept-language - the preferred language in the header that is a locale, by full tag (fr-CA) or language (fr). The languages are tried from the highest q weight down (the header's order breaks ties), and one marked q=0 is never picked.
  • cookie - the gio_locale cookie.

For HTML responses in a locale other than the default, the server also sets the <html> element's lang to the locale, replacing the one the root layout wrote.

Behavior

  • The value travels with the page, so the server render and the hydration render agree and the server HTML already holds locale-dependent output, such as a <LocaleLink>'s prefixed href.
  • After a soft navigation, hydrated components read the new page's locale.
  • Outside a tree GioJS rendered (a unit test, a separate React root), it returns '' on the first render and then document.documentElement.lang, read in an effect so hydration cannot mismatch.

Examples

Translating strings

app/(site)/greeting.tsx
import { useLocale } from '@gio.js/react';

const MESSAGES: Record<string, { hello: string }> = {
  en: { hello: 'Hello' },
  fr: { hello: 'Bonjour' },
};

export function Greeting() {
  const locale = useLocale();
  return <p>{(MESSAGES[locale] ?? MESSAGES.en).hello}</p>;
}

Formatting dates

tsx
const locale = useLocale() || 'en';
const published = new Intl.DateTimeFormat(locale, { dateStyle: 'long' }).format(new Date(post.publishedAt));

Good to know

  • On the server, route handlers and getServerSideProps read the same value as req.locale ('' without [i18n]) and ctx.locale (absent without [i18n]).
  • The page cache keeps one copy per locale. A URL without a locale prefix depends on the visitor's headers (unless detect_from is only ["path"]), so its response is never marked public for CDNs and carries no ETag; link to prefixed URLs where shared caching matters.
  • GioJS never sets the gio_locale cookie; set it yourself to remember a visitor's choice.
  • In the server-only root layout the value is that of the page loaded in full.
  • Locales are matched exactly as written in locales for the path and the cookie; the Accept-Language match ignores case. The value is always spelled as in locales: Accept-Language: pt-br with a configured pt-BR gives 'pt-BR'.

Version history

VersionChanges
v0.1.0-beta.8Returns the request locale during server rendering too, from the navigation state GioJS provides. A locale from Accept-Language is spelled as in locales (it was lowercased) and picked by q weight.
v0.1.0-beta.6No longer causes hydration mismatches.
v0.1.0-beta.1Introduced.