TrademarkTrademark
Composition

Languages

Give an app one language, or several with language URLs, from one config line.
Every app has a language. It lives in src/resources/once-ui.config.js: The default language sets <html lang> and how prices are formatted, and it picks which entry of each labels file the interface shows. Set it when you scaffold:

Interface text

A surface keeps its interface text in one file, src/content/<surface>/labels.ts, with one entry per language. Translating the surface means adding an entry, not editing components: Every entry has the type of the first one, so a missing key is a type error. Text that depends on a value is a function, such as the footer's rights(year). Components read their entry with labelsFor(storeLabels, locale), where the locale comes from getLocale() on the server or useLocale() in a client component. The storefront has a labels file today; other surfaces follow.

Several languages

Two or more locales add the i18n slice:
  • /hu/store renders the same page as /store, in Hungarian. The default language has no prefix, and /en/store redirects to /store.
  • The visitor's language is remembered in a cookie, so ordinary links such as href="/store" keep a Hungarian reader in Hungarian. On the first visit the browser's language decides.
  • The store header shows a language switcher.
  • localeMeta() gives each page its own canonical URL and hreflang alternates, so search engines index every language.
Pages render per request in this mode, because the language is part of the request. A one-language app keeps static pages. Content such as products and collections is not interface text: it comes from the catalog in whatever language the catalog is written in.
Last updated October 21, 2026
Edit this page on GitHub