General Translation  
Next.js

<T> Reference

This is a detailed dive into the <T> component and the gt-next library.

Overview

This article will take an in depth dive into how to use the <T> component in the gt-next library. Please feel free to skip around this page as needed. We will cover the following:

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


What is the <T> Component?

The <T> component is the primary way to translate text and content in the gt-next library. It allows for inline translation of text and JSX structures, providing a more direct way to manage translations in your application. This is often times more convenient for the developer as it allows for more direct control over the translation content.

The <T> component supports static text, JSX structures, and context-aware translations. When no translation is available, it gracefully falls back to displaying the content in the application's default locale.


Design Patterns

In this section, we will detail common design patterns used with the <T> component. This will also touch on topics that are tangentially related to the <T> component, but equally important, such as string translation, translating content in advanced, and privacy concerns.

Wrapping your <T> components in a <GTProvider>

<T> is used to translate static text and JSX structures. For client-side components, <T> MUST be wrapped in a <GTProvider> at a higher level. Our advice is to wrap your application in a <GTProvider> at the root level to provide this context.

import { GTProvider } from 'gt-next';
import { getLocale } from "gt-next/server";
 
export default async function RootLayout({ children }) {
  const locale = await getLocale();
  return (
    <html lang={locale}>
      <body>
        <GTProvider>{children}</GTProvider>
      </body>
    </html>
  );
}

Exceptions: Server-Side <T> Components

For server-side rendering, the <GTProvider> is optional for <T> components.

import { GTProvider } from 'gt-next';
import { getLocale } from "gt-next/server";
 
export default function RootLayout({ children }) {
  const locale = await getLocale();
  return (
    <html lang={locale}>
      <body>
        <T> Hello, world! </T>
        
        <GTProvider>{children}</GTProvider>
      </body>
    </html>
  );
}

Variables in <T> Components

Variables components can be used in <T> components to (1) display dynamic values and/or (2) mark content that should not be translated. Think of things like a user's name: it's (1) different from person to person and (2) should not change even when the language changes.

DynamicGreeting.js
import { T, Var } from 'gt-next';
 
export default function DynamicGreeting({ user }) {
  return (
    <T>
      Hello, <Var>{user.name}</Var>!
    </T>
  );
}

There are many variable components: <Var>, <Num>, <Currency> and <DateTime>. Some of these will automatically reformat the content based on the user's locale. Others will simply mark the content as "do not translate". Also, these components don't necessarily need to be wrapped in a <T> component to reformat content.

Read more about it in this article about variable components.

Branching in <T> Components

Branching components can be used to display different content based on conditions for translations. These include <Plural> and <Branch> components. We use these components because they allow for a more optimized translation process.

For example, the <Plural> component allows you to mark a sentences that should be pluralized when translation occurs.

Count.js
import { T, Plural } from 'gt-next';
 
export default function Count({ num }) {
  return (
    <T>
      <Plural
        n={num} // <-- variable to check
        singular={<p>There is one item.</p>}  
        plural={<p>There are multiple items.</p>}  
      />
    </T>
  );
}

It is also useful as it standardizes your pluralization logic across your application in your base language.

You can specify different options depending on which component you use. Read more about it in the Branching Components article.

Translating Strings

If you want to translate just a string, you can use useGT(), getGT(), or tx().

useGT() and getGT() are used for translating strings at buildtime.

Greeting.js
function Greeting() {
  const t = useGT();  // client side
  const t = await getGT(); // server side
  return <p>{t('Hello, my friend!')}</p>; 
}

tx() is used for translating strings at runtime.

FavoriteFlavor.js
function async FavoriteFlavor({ flavor }) {
  return <p>{await tx(`Your favorite ice cream flavor is ${flavor}`)}</p>; 
}

For more information, you can refer to our guide on translating strings.

Adding ids to <T> Components

A handy debugging trick is to add an id prop to your <T> components. This allows you to track which translations are being used in your application. It also allows you to use the Translation Editor to make changes to your translations without redeploying.

Greeting.js
import { T } from 'gt-next';
 
export default function Greeting() {
  return (
    <T id="greeting">
      Hello, world!
    </T>
  );
}

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 in your CD pipeline or as a part of your build script.

package.json
{
  "scripts": {
    "build": "npx gt-next-cli translate --languages fr es ja && next build",
  }
}

That's it! You have successfully translated your application into French, Spanish, and Japanese.

For a more detailed guide on deploying your application, please refer to the Deployment guide. 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. We do 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, the <T> component will translate content 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 APIs 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 APIs for translation. The localization of all content wrapped in any Variable Component is handled locally.


Examples

Basic Usage

The simplest use case for <T> is to translate static text.

import { T } from 'gt-next';
 
export default function BasicUsage() {
  return (
    <T>
      Hello, world!
    </T>
  );
}

This example ensures that "Hello, world!" is translated based on the user's locale. For example, in a Spanish locale, it may render as "¡Hola, mundo!".

Context

The <T> component supports additional context to refine translations. Adding a context prop allows the same id to resolve to different translations depending on the context provided.

import { T } from 'gt-next';
 
export default function FormalGreeting() {
  return (
    <T context="formal">
      Hi there!
    </T>
  );
}

For example, the context "formal" could yield a translation such as "Good day, everyone!", while the same id without context might yield "Hi there!" in the other language. Of course, no change would occur for the base language.

Nested Components

The <T> component can also translate JSX structures. Any children of the <T> will be translated.

import { T } from 'gt-next';
import CustomButton from './CustomButton';
 
export default function Page() {
  return (
    <T>
      This will be translated
      <div>
        <div>
          <div>
            <div>
              <CustomButton>This text will also be translated!</CustomButton>
            </div>
          </div>
        </div>
      </div>
    </T>
  );
}

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.

This occurs because of how React renders components. It is a bit complicated, but the gist is that React does not know the content of a component until it has rendered. Therefore, the contents of components like <UntranslatedContent> are not translated. However, any text directly between the two <T> tags will be translated.

Note: A good rule of thumb is that any content that is literally between the two <T> 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?

Your first instinct might be to add an additional <T> component inside <UntranslatedContent>, but this is not recommended. We discuss this more below.

The solution is to always 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 />
    </>
  );
}

What about variables?

Variables are a little more complicated because they have the tendency to change their values. We recommend using Variable Components for displaying dynamic values and Branching Components for conditional logic.

If you want to translate dynamic contents at runtime, checkout tx() and <Tx>.

Nested <T> Components

Nesting <T> components is not allowed. Because of react's rendering system, this can lead to unexpected behavior and performance issues when translating on-demand.

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.

Conditional Content

Similar to rendering variable content, conditional content within a <T> component needs to be handled properly. It is always best practice to wrap the conditional content in a Branching Component to optimize the translation of content.

import { T, Branch } from 'gt-next';
 
export default function Header({ user }) {
  return (
    <T>
      <h2>
        <Branch
          branch={user.hasAccount}
          true={<p>Welcome back, {user.name}!</p>}
          false={<p>Please log in to continue.</p>}
        />
      </h2>
    </T>
  );
}

Notes

  • <T> components are used to translate arbitrary JSX Content.
  • Wrap your app with a <GTProvider> to enable translations in client components.
  • <T> translates contents at buildtime, not runtime. Development will perform on-demand translation for convenience, but this is not the case in production.

Next Steps

On this page