Skip to main content

useTranslation()

The useTranslation hook returns the translated string for a text, inside a component. It is the hook behind I18nKeylessText — the component is this hook plus a fragment — so it takes the same options and resolves the text the same way.

Use it where an element will not do: a placeholder, a title, an aria-label, a string handed to another library (a markdown renderer, a navigator's tabBarLabel). Everywhere else, prefer <I18nKeylessText>.

Called without a text, it returns a reactive t() function instead — for a component with many strings, or strings inside an array or a .map(). See The function form.

Available since i18n-keyless-react@3.3.0; the function form since 3.6.0.

Function Signature

// docs-check: skip — a signature listing, not a snippet to run
useTranslation(
text: string,
options?: {
context?: string;
namespace?: string;
unpersistedNamespace?: boolean;
replace?: Record<string, string>;
forceTemporary?: Record<string, string>;
originLanguage?: Lang;
debug?: boolean;
}
): string

// The function form: no text, same options as defaults.
useTranslation(options?: TranslationOptions): (text: string, options?: TranslationOptions) => string

Parameters

text

type: string (required)

The text to translate, written in your primary language. It is also the translation key.

options

type: TranslationOptions

The same options as the props of I18nKeylessTextcontext, namespace, unpersistedNamespace, replace, forceTemporary, originLanguage, debug.

Return Value

type: string

The translated text in the current language. The source text when the current language is the primary language, or while the translation has not arrived yet.

Basic Usage

import { useTranslation } from 'i18n-keyless-react';

export function SearchBox() {
const placeholder = useTranslation('Search products...');
const label = useTranslation('Search input');

return <input type="search" placeholder={placeholder} aria-label={label} />;
}

The function form

For one or two strings, one hook call per string reads well. For a nav with twenty labels, a table header, or strings inside an array or a .map() — where the rules of hooks forbid a hook — call useTranslation() without a text. It returns a reactive t(text, options?) function with the same resolution as the string form. The options given to the hook are the defaults; the options given to a call merge over them.

import { useTranslation } from 'i18n-keyless-react';

const links = [
{ to: '/dashboard', label: 'Dashboard' },
{ to: '/inbox', label: 'Inbox' },
{ to: '/activity', label: 'Audit' },
];

export function Nav() {
const t = useTranslation({ context: 'navigation menu item' });

return (
<nav>
{links.map((link) => (
<a key={link.to} href={link.to}>
{t(link.label)}
</a>
))}
</nav>
);
}

The one difference with the string form: t() cannot know its strings ahead of time, so the component re-renders on every translation batch that lands, not only when its own strings change. That is the right trade for a nav; for a single placeholder, pass the text to the hook.

A call site uses one form or the other. The two forms call different hooks, so never switch a given call between them at runtime.

Under SSR the function form reads <I18nKeylessProvider> like the string form does, so it is correct in a TanStack Start component tree. Before init() has run (Storybook, a unit test), t() returns the text as-is.

useTranslation vs getTranslation

useTranslation(text)getTranslation(text)
Whereinside a component (const t = useTranslation() for many strings)outside a component: a loader, head(), a utility
Reactiveyes — re-renders when the translation lands or the language changesno — reads the store once
SSRreads <I18nKeylessProvider>, like <I18nKeylessText>reads the runWithI18nKeyless scope

Under TanStack Start the component tree renders outside the runWithI18nKeyless scope, so getTranslation() in a component body renders the primary language on the server. useTranslation is the string API that is correct there.

Notes

  • Must be called in a React component or another hook, unconditionally — the rules of hooks apply
  • Queues the text for translation on first sight, like <I18nKeylessText> does; nothing else to wire
  • Do not re-implement the lookup by reading useI18nKeyless((s) => s.translations) yourself: the storage key format, the primary-language shortcut, originLanguage and the SSR snapshot are all inside this hook. When you need a function, use the function form