GioJSdocs
On this page

<LocaleLink>

A GioLink that keeps the visitor's language: it adds the request locale as a path prefix when it is not the default locale.

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

<LocaleLink href="/pricing">Pricing</LocaleLink>
// on a French page: <a href="/fr/pricing">

Reference

PropTypeDefaultDescription
href (required)string-The path without a locale prefix, starting with /. Other URLs pass through unchanged (see Behavior).
defaultLocalestring[i18n] default_localeThe locale that gets no prefix. Leave it out: it is read from gio.toml. Pass it only to override that for one link.
classNamestring-Passed to the <a>.
children (required)React.ReactNode-The link content.

Behavior

The locale comes from useLocale(). When it is not empty and differs from defaultLocale, a path that starts with / gets /<locale> in front. Everything else is used as written: absolute URLs (https:, mailto:), protocol-relative ones (//cdn.example.com), relative paths, ?query and #hash hrefs, and paths whose first segment already is one of your locales. The result is a <GioLink> with its defaults: client-side navigation and hover prefetch. The locale is known during server rendering, so the prefixed href is already in the HTML.

With default_locale = "en":

Request localehrefRendered
'' (no [i18n])/pricing/pricing
en (the default)/pricing/pricing
fr/pricing/fr/pricing
fr//fr/
fr/de/preise/de/preise
frhttps://example.com/https://example.com/

The default locale is [i18n] default_locale. The server hands the [i18n] settings to the worker, and every hydration envelope of an app with locales carries them to the browser, so the server HTML and the hydrated link agree. A LocaleLink rendered outside a GioJS page tree (in a React root of your own) reads window.__GIO_DEFAULT_LOCALE__ and window.__GIO_LOCALES__, which the server puts in every page. Without them - in renderPage, for one - the default is en and only an href that starts with the current or default locale counts as already prefixed.

The request locale is what the server detected: the URL prefix, the Accept-Language header or the gio_locale cookie, in the order [i18n] detect_from sets. A French browser on /pricing - no prefix - therefore gets links to /fr/....

Examples

Localized navigation

gio.toml
[i18n]
locales = ["de", "en", "fr"]
default_locale = "de"
app/(site)/nav.tsx
import { LocaleLink } from '@gio.js/react';

export function Nav() {
  return (
    <nav>
      <LocaleLink href="/">Start</LocaleLink>
      <LocaleLink href="/preise">Preise</LocaleLink>
    </nav>
  );
}

A language switcher

LocaleLink always keeps the current locale. To switch, link to the path with the target locale's prefix - the default locale's too, since a path without a prefix is detected from the browser's language again. A plain <a> loads the page in full, so the server-only root layout is rendered in the new language too; a soft navigation would leave it as it was.

app/(site)/language-switcher.tsx
import { useLocale, usePathname } from '@gio.js/react';

const LANGUAGES = [
  { locale: 'de', label: 'Deutsch' },
  { locale: 'en', label: 'English' },
  { locale: 'fr', label: 'Français' },
];

export function LanguageSwitcher() {
  const current = useLocale();
  const pathname = usePathname(); // without the locale prefix
  return (
    <ul>
      {LANGUAGES.map(({ locale, label }) => (
        <li key={locale}>
          <a href={`/${locale}${pathname}`} hrefLang={locale} aria-current={locale === current ? 'page' : undefined}>
            {label}
          </a>
        </li>
      ))}
    </ul>
  );
}

Good to know

  • German pages of a site with default_locale = "de" link to /preise, English ones to /en/preise - no prop needed.
  • A path that already starts with a locale is left alone, so <LocaleLink href="/de/preise"> always points at the German page. Matching is exact, as for the URL prefix itself: /english is a path, not the en locale.
  • renderPage runs no [i18n]: there the default locale is en and only a path starting with the current or default locale is left alone, so pass defaultLocale in tests of a site whose default is another one.
  • Only href, defaultLocale, className and children are taken: prefetch, transition, replace and scroll keep the GioLink defaults.
  • GioJS never sets the gio_locale cookie. Set it yourself (for example from a route handler) to remember a choice for URLs without a prefix.
  • In the server-only root layout the link is a plain <a>, as for GioLink.

Version history

VersionChanges
v0.1.0-beta.8The prefixed href is rendered on the server, since useLocale() returns the request locale there. defaultLocale defaults to [i18n] default_locale instead of 'en'. Absolute, protocol-relative and relative URLs, ?query and #hash hrefs and paths that already start with a locale are no longer prefixed.
v0.1.0-beta.1Introduced.