Translating JSX

How to internationalize JSX components

Overview

This guide will walk you through how to use the <T> component to internationalize JSX content.

By the end of this guide, you will know the correct syntax for using the <T> component and what to avoid.

We will cover the following:

How to use the <T> component

Additional options

When to use the <T> component

Examples

Production considerations

Common pitfalls

If you are looking for how to use Variable Components or Branching Components, please refer to their respective guides.


How to use the <T> component

Let's say you have some HTML content that you want to translate.

function Greeting() {
  return <p>Hello, world!</p>;
}

All you have to do is wrap the content in a <T> component.

import { T } from 'gt-react';

function Greeting() {
  return <T><p>Hello, world!</p></T>;
}

Depending on the current language your user has selected, this will render the appropriate translation. See switching languages for more information on how to allow your users to switch languages.


Additional Options

Context

In some cases, you may want to provide additional context to the translation. This can be done by passing a context prop to the <T> component.

<T context="toast, as in a pop-up notification">
  Click on the toast to dismiss it.
</T>

This is useful in cases where words may have multiple meanings depending on the context. For example, "toast" can refer to the food or a pop-up notification.

The context prop is helpful for the AI to understand the intent of the translation.

id

You can also pass an id prop to the <T> component. This is useful for debugging purposes and makes editing the translation easier.

<T id="toast">
  Click on the toast to dismiss it.
</T>

When to use the <T> component

While the <T> component is very flexible, it is not always the best solution.

You should always try to use the <T> component when you have any static HTML or JSX content.

When not to use the <T> component

DO NOT use the <T> component when you have any unsafe dynamic content.

Here, dynamic content means any content that could change at runtime. This rule does not apply if you are using Variable Components or Branching Components.

Note:

Variable components are a special case where the content is dynamic, but the content has been wrapped and sanitized, so it is safe to use the <T> component.

Content wrapped in variable components are never translated directly by the <T> component.

The following examples show invalid usage of the <T> component:

<T>
  <p>Your username is {username}</p>
</T>
<T>
  <p>Current date: {new Date().toLocaleDateString()}</p>
</T>
<T>
  <p>Logical Expressions: {username === 'admin' ? 'Yes' : 'No'}</p>
</T>
<T>
  <p>Conditional Rendering: {isAdmin ? 'Yes' : 'No'}</p>
</T>

In the above examples, the content can be safely internationalized using variable components and branching components.

const chatMessage = getChatMessageFromServer();
<T>
  <p>{chatMessage}</p>
</T>

In this example, the content is fully dynamic, so it should be translated on the server side before being passed to the client.

See the core library for more information on how to dynamically translate content via our API.


Examples

Here are some examples of how to use the <T> component. These are all correct.

  1. HTML content
<T>
  <p>Hello, world!</p>
</T>
<p>Hello, world!</p>
  1. Simple JSX content
<T>
  <Button>Click me!</Button>
</T>
<Button>Click me!</Button>
  1. Complex JSX content
<T>
  <Tooltip>
    <TooltipTrigger>
      <div className="flex items-center gap-2 rounded-full bg-destructive px-3 py-1.5 text-sm text-destructive-foreground">
        <AlertCircle className="h-4 w-4" />
        <span>Free Usage</span>
      </div>
    </TooltipTrigger>
    <TooltipContent>
      <p>
        You are nearing your free monthly limit. Please
        upgrade your plan to avoid any disruptions to your
        service.
      </p>
    </TooltipContent>
  </Tooltip>
</T>
<Tooltip>
  <TooltipTrigger>
    <div className="flex items-center gap-2 rounded-full bg-destructive px-3 py-1.5 text-sm text-destructive-foreground">
      <AlertCircle className="h-4 w-4" />
      <span>Free Usage</span>
    </div>
  </TooltipTrigger>
  <TooltipContent>
    <p>
      You are nearing your free monthly limit. Please
      upgrade your plan to avoid any disruptions to your
      service.
    </p>
  </TooltipContent>
</Tooltip>

The <T> component can handle any nested content in the same component.


Production Considerations

Deploying to production

Make sure to run the translate command before deploying to production, so that all translations are available at runtime. We recommend adding it to your CD pipeline or as a part of your build script.

package.json
{
  "scripts": {
    "build": "npx gtx-cli translate && <YOUR_BUILD_COMMAND>",
  }
}

For a more detailed guide on deploying your application, please refer to the Deployment tutorial. For more information on the command, please refer to the CLI Tool reference guide.

Behavior: Development vs Production

In development, the <T> component will translate content on-demand. This means that when the component is rendered, it will perform a translation immediately. The library does this for convenience to make development with other languages easier.

To enable this behavior, just add a Dev API key to your environment.

In production, all translations that the <T> component uses are completed at build time. This means that you have to run the translation command before deploying your application.

Tip: If you want to simulate production behavior in development, just use a production API key in your development build.

Privacy Concerns

With some exceptions, all content wrapped in a <T> component is sent to the General Translation API for translation. This might not be desirable for rendering sensitive data, such as usernames, account numbers, etc.

To circumvent this issue, use Variable Components to handle private information. This ensures that no sensitive data is sent to the General Translation API for translation. Localization of any content wrapped in a variable component is handled locally.


Common Pitfalls

Direct descendants only

The <T> component only translates text passed directly as a child. This means that if you have content inside a component that is not directly passed to <T>, it will not be translated.

Let's illustrate this with an example:

function UntranslatedContent() {
  return (
    <p>This content is not translated</p>
  );
}

export default function DisplayGreetings() {
  return (
    <T>
      <h1>Hello, this text will be translated</h1>
      <UntranslatedContent />
    </T>
  );
}

In this example, the content inside <UntranslatedContent> will not be translated. Only the content directly inside <T> will be translated, like the <h1> tag and its children.

Note: A good rule of thumb is that any content that is literally between the two <T> tags in the file will be translated. You can always add another <T> to translate the content that is not being translated, though nesting <T> components is not recommended.

What's the fix?

Wrap the text in the <T> component directly, like so:

function TranslatedContent() {
  return (
    <T>
      <p>This content <b>IS</b> translated</p>
    </T>
  );
}

export default function DisplayGreetings() {
  return (
    <>
      <T>
        <h1>Hello, this text will be translated</h1>
      </T>
      <TranslatedContent />
    </>
  );
}

Nested <T> Components

Nesting <T> components is not allowed. Because of React's rendering system, this can lead to unexpected behavior and performance issues.

Here is an example of what not to do:

function SomeComponent() {
  return (
    <T>
      Hello, friend!
    </T>
  );
}

export default function NestedTranslation() {
  return (
    <T>
      <T> {/* Don't do this! */} 
        Hello, world! 
      </T>
      <SomeComponent /> {/* This still counts. Don't do this! */}
    </T>
  );
}

The solution here is to remove the outtermost <T> component.

Translating dynamic content

If you attempt to wrap dynamic content with the <T> component, the CLI tool will error.

For example, the following will error:

const username = 'John Doe';
<T>
  <p>Your username is {username}</p>
</T>

To get around this, try to use Variable Components or Branching Components to wrap the dynamic content.


Summary

  • <T> components are used to internationalize arbitrary JSX Content.
  • <T> components should not be used for dynamic content, without using variable components or branching components.
  • In development, the <T> component will translate content on-demand.
  • In production, all translations that the <T> component uses are completed at build time.

Next Steps

How is this guide?