# General Translation Knowledge Base: How do I translate strings outside JSX?
URL: https://generaltranslation.com/en-GB/kb/translate-strings-outside-jsx.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Pass each string that isn't a JSX child, such as a placeholder or a module-scope constant, through a translation function where it renders. General Translation's useGT hook returns that function, and msg with useMessages translates constants defined outside a component.
Category: Internationalisation
Last updated: 2026-10-21
Authors: Kevin Liu, Kevin Wu
Published: 2026-10-21

Strings outside JSX are text that isn&#39;t a JSX child, so a translation component can&#39;t wrap it: attribute values such as `placeholder` and `aria-label`, strings built in code, and constants defined at module scope. Each goes through a translation function from a hook (`useTranslation` in `react-i18next`, for example), and hooks run only inside a component. A module-scope constant is evaluated once, when the file loads, so translating it there locks in whichever language was active at that moment (on a server, one language for every user). Instead, the constant holds a reference, and the string is translated where it renders.

## Video

The video is narrated in English, with English captions.

[How do I translate strings outside JSX?](https://caxecubb9c64cezv.public.blob.vercel-storage.com/films/kb-translate-strings-outside-jsx.mp4) (49 secs)

General Translation translates placeholders with `useGT` and constants with `msg` and `useMessages`. Call `useGT` and pass the placeholder to the function it returns, await `getGT` in async components, register each constant string with `msg` and resolve it with `useMessages`, then run `npx gt translate`.

## Ways to translate strings outside JSX

| Approach                                                                         | What it does well                                                                                                                         | In the code                                                                                                                                                                                                                                                                                | What it leaves to you                                                                                                                                 |
| -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`i18next`](/kb/general-translation-vs-i18next) (`react-i18next`) or `next-intl` | Mature runtimes with a translation function for any string                                                                                | [`t`](https://www.i18next.com/overview/api#t) from [`useTranslation`](https://react.i18next.com/latest/usetranslation-hook) or [`useTranslations`](https://next-intl.dev/docs/environments/server-client-components) takes a key; a constant stores the key, which is translated at render | Inventing a key for each string, writing one file per language, and keeping every file in sync as copy changes                                        |
| [`react-intl`](/kb/general-translation-vs-react-intl)                            | Message descriptors carry an ID, a default message, and a description for translators                                                     | `defineMessages` declares descriptors in a constant, and [`formatMessage`](https://formatjs.github.io/docs/react-intl/api#formatmessage) from [`useIntl`](https://formatjs.github.io/docs/react-intl/api#useintl-hook) translates one at render                                            | An ID for each message, extracting messages into a file per language, and producing every translation                                                 |
| [Lingui](/kb/general-translation-vs-lingui)                                      | The source text is the message, so there are no keys to invent                                                                            | The [`msg`](https://lingui.dev/ref/macro#definemessage) macro defines a message in a constant, and `_` from [`useLingui`](https://lingui.dev/ref/react) translates it at render                                                                                                            | Running `lingui extract` and `lingui compile`, and translating each catalogue                                                                         |
| General Translation (`gt-react` and `gt-next`)                                   | [`npx gt translate`](/docs/cli/reference/commands/translate) finds each string in your code and translates it before the production build | [`useGT`](/docs/react/reference/hooks/use-gt) returns a function you call with the source string (no key); [`msg`](/docs/react/reference/functions/msg) registers each string in a constant, and [`useMessages`](/docs/react/reference/hooks/use-messages) translates it at render         | Passing each string as a literal so the CLI can find it, and rerunning [`npx gt translate`](/docs/cli/reference/commands/translate) when copy changes |

Use `i18next` or `next-intl` when your app already has key files and a translator keeps them up to date. Use `react-intl` or Lingui when translators work from extracted catalogues and need a description or the source text with each message. Use General Translation when strings are spread across components and shared constants and change with each release. If only one component uses a constant, simply moving it inside the component is enough: each value then becomes an ordinary translation call.

## Translate strings outside JSX with General Translation

General Translation&#39;s `gt-react` and `gt-next` translate a string in a component with the [`useGT`](/docs/react/reference/hooks/use-gt) hook, and a constant with [`msg`](/docs/react/reference/functions/msg) and [`useMessages`](/docs/react/reference/hooks/use-messages).

1. For a string in a component, call `const gt = useGT()`, which returns the function itself, and pass it a string literal with variables as named placeholders: `gt('Welcome back, {name}!', { name: user.name })`. Add `$context` so that an ambiguous word is given the right meaning.

2. For a constant, register each string with [`msg`](/docs/react/reference/functions/msg) and resolve it with [`useMessages`](/docs/react/reference/hooks/use-messages) where it renders:

   ```tsx
   import { msg, useMessages } from 'gt-react';

   const STATUS = { active: msg('Active'), paused: msg('Paused') };

   function Badge({ status }: { status: 'active' | 'paused' }) {
     const m = useMessages();
     return <span>{m(STATUS[status])}</span>;
   }
   ```

3. Run [`npx gt translate`](/docs/cli/reference/commands/translate) before the production build.

## Server components and module scope

Async Next.js App Router components can&#39;t call hooks, so they await [`getGT`](/docs/react/nextjs/reference/functions/get-gt) and [`getMessages`](/docs/react/nextjs/reference/functions/get-messages) from `gt-next/server`. In a client-side `gt-react` app set up with [`initializeGTSPA`](/docs/react/reference/config#initialize-spa), the [`t`](/docs/react/reference/functions/t-function) function also translates at module scope, but switching language requires a full page reload. The [Translating strings](/docs/react/guides/translating-strings) guide sets out the full steps for each framework.

## Related questions

- [How do I translate conditional text in JSX?](https://generaltranslation.com/en-GB/kb/translate-conditional-jsx.mdx): Keep the sentence whole and translate every version of it, because a ternary splits it into fragments that lose their meaning and their place in each language's word order. General Translation does this with `<Branch>` inside `<T>`, which translates the sentence as one unit.
- [How do I format numbers, dates and currencies for each locale?](https://generaltranslation.com/en-GB/kb/format-numbers-dates-currencies.mdx): Format each value when the page renders, using the reader's locale and JavaScript's Intl API, and keep it out of the translated sentence. General Translation's `<Num>`, `<Currency>`, `<DateTime>` and `<RelativeTime>` components do both inside a `<T>`, so one translation serves every value.
- [How do I translate a React app?](https://generaltranslation.com/en-GB/kb/translate-react-app.mdx): Translating a React app means internationalising its components so they render in the user's language, then translating every string into each language you support. General Translation's gt-react translates JSX in place in the `<T>` component, and npx gt translate writes one file per language.
- [Can I do i18n without translation files?](https://generaltranslation.com/en-GB/kb/i18n-without-translation-files.mdx): Yes. General Translation's gt-react and gt-next libraries do React and Next.js i18n with no translation keys and no JSON file per language to maintain. Copy stays inline in JSX inside the `<T>` component, and the gt translate command generates each language's translations in your build, with context from your code. Locadex can keep them up to date through pull requests.

## Previous and next questions

- Previous question: [How do I translate Google Slides?](https://generaltranslation.com/en-GB/kb/translate-google-slides.mdx)
- Next question: [What does the Locadex agent do?](https://generaltranslation.com/en-GB/kb/what-is-locadex.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/en-GB/kb/sitemap.md) for every article.
