Strings

How to internationalize plain text strings using useGT and getGT

String translation provides direct access to text translations without JSX, perfect for attributes, object properties, and plain text values. Use useGT in synchronous components and getGT in asynchronous components.

Synchronous vs Asynchronous Usage

  • Synchronous Components: useGT hook for React components
  • Asynchronous Components: getGT async function for async components

Quick Start

Synchronous Components

import { useGT } from 'gt-next';

function MyComponent() {
  const t = useGT();
  return (
    <input 
      placeholder={t('Enter your email')}
      title={t('Email address field')}
    />
  );
}

Asynchronous Components

import { getGT } from 'gt-next/server';

async function MyServerComponent() {
  const t = await getGT();
  return (
    <input 
      placeholder={t('Enter your email')}
      title={t('Email address field')}
    />
  );
}

When to Use String Translation

String translation is ideal when you need plain text rather than JSX:

HTML Attributes

const t = useGT();

<input 
  placeholder={t('Search products...')}
  aria-label={t('Product search input')}
  title={t('Type to search our catalog')}
/>

Object Properties

const t = useGT();

const user = {
  name: 'John',
  role: 'admin',
  bio: t('Experienced software developer with 5 years in React'),
  status: t('Currently available for projects')
};

Configuration & Constants

const t = useGT();

const navigationItems = [
  { label: t('Home'), href: '/' },
  { label: t('Products'), href: '/products' },
  { label: t('Contact'), href: '/contact' }
];

When to Use <T> Instead

Use the <T> component for JSX content:

// ✅ Use <T> for JSX content
<T><p>Welcome to <strong>our store</strong>!</p></T>

// ✅ Use string translation for plain text
<input placeholder={t('Search products')} />

Using Variables

Basic Variables

Replace placeholders with dynamic values:

const t = useGT();
const itemCount = 5;

// String with placeholder
const message = t('You have {count} items in your cart', { count: itemCount });
// Result: "You have 5 items in your cart"

Multiple Variables

const t = useGT();
const order = { id: 'ORD-123', total: 99.99, date: '2024-01-15' };

const confirmation = t(
  'Order {orderId} for ${total} was placed on {date}',
  { 
    orderId: order.id, 
    total: order.total, 
    date: order.date 
  }
);

ICU Message Format

For advanced formatting, use ICU syntax:

const t = useGT();
translate('There are {count, plural, =0 {no items} =1 {one item} other {{count} items}} in the cart', { count: 10 });

Learn more about ICU Message Format in the Unicode documentation.

Examples

Form Inputs

import { useGT } from 'gt-next';

function ContactForm() {
  const t = useGT();
  
  return (
    <form>
      <input 
        type="email"
        placeholder={t('Enter your email address')}
        aria-label={t('Email input field')}
      />
      <textarea 
        placeholder={t('Tell us about your project...')}
        aria-label={t('Project description')}
      />
      <button type="submit">
        {t('Send Message')}
      </button>
    </form>
  );
}
import { useGT } from 'gt-next';

function Navigation() {
  const t = useGT();
  
  const menuItems = [
    { label: t('Home'), href: '/', icon: 'home' },
    { label: t('About Us'), href: '/about', icon: 'info' },
    { label: t('Services'), href: '/services', icon: 'briefcase' },
    { label: t('Contact'), href: '/contact', icon: 'mail' }
  ];

  return (
    <nav>
      {menuItems.map((item) => (
        <a key={item.href} href={item.href} title={item.label}>
          <Icon name={item.icon} />
          {item.label}
        </a>
      ))}
    </nav>
  );
}

Dynamic Content Factory

// utils/productData.js
export function getProductMessages(t) {
  return {
    categories: [
      { id: 'electronics', name: t('Electronics') },
      { id: 'clothing', name: t('Clothing') },
      { id: 'books', name: t('Books') }
    ],
    statusMessages: {
      available: t('In stock and ready to ship'),
      backordered: t('Currently backordered - ships in 2-3 weeks'),  
      discontinued: t('This item has been discontinued')
    },
    errors: {
      notFound: t('Product not found'),
      outOfStock: t('Sorry, this item is currently out of stock')
    }
  };
}

// components/ProductCard.jsx
import { useGT } from 'gt-next';
import { getProductMessages } from '../utils/productData';

function ProductCard({ product }) {
  const t = useGT();
  const messages = getProductMessages(t);
  
  return (
    <div>
      <h3>{product.name}</h3>
      <p>{messages.statusMessages[product.status]}</p>
      <span>{messages.categories.find(c => c.id === product.categoryId)?.name}</span>
    </div>
  );
}

Server Component with Metadata

import { getGT } from 'gt-next/server';

export async function generateMetadata({ params }) {
  const t = await getGT();
  
  return {
    title: t('Product Catalog - Find What You Need'),
    description: t('Browse our extensive collection of high-quality products'),
    openGraph: {
      title: t('Shop Our Products'),
      description: t('Discover amazing deals on top-rated items')
    }
  };
}

export default async function ProductPage() {
  const t = await getGT();
  
  return (
    <div>
      <h1>{t('Featured Products')}</h1>
      <p>{t('Check out our latest and most popular items')}</p>
    </div>
  );
}

Common Issues

Dynamic Content at Runtime

Strings must be known at build time - you cannot translate dynamic content:

// ❌ Dynamic content won't work
function MyComponent() {
  const [userMessage, setUserMessage] = useState('');
  const t = useGT();
  
  return <p>{t(userMessage)}</p>; // This will fail
}

// ✅ Use predefined strings
function MyComponent() {
  const [messageType, setMessageType] = useState('welcome');
  const t = useGT();
  
  const messages = {
    welcome: t('Welcome to our app!'),
    goodbye: t('Thanks for visiting!')
  };
  
  return <p>{messages[messageType]}</p>;
}

Hook Rules Violations

Follow React hook rules when using useGT:

// ❌ Don't call hooks conditionally
function MyComponent({ showMessage }) {
  if (showMessage) {
    const t = useGT(); // Hook rule violation
    return <p>{t('Hello!')}</p>;
  }
  return null;
}

// ✅ Always call hooks at top level
function MyComponent({ showMessage }) {
  const t = useGT();
  
  if (showMessage) {
    return <p>{t('Hello!')}</p>;
  }
  return null;
}

Synchronous vs Asynchronous Confusion

Use the right function for your component type:

// ❌ Wrong: useGT in async component
export default async function AsyncComponent() {
  const t = useGT(); // This won't work
  return <p>{t('Hello')}</p>;
}

// ✅ Correct: getGT in async component  
export default async function AsyncComponent() {
  const t = await getGT();
  return <p>{t('Hello')}</p>;
}

// ✅ Correct: useGT in synchronous component
export default function SyncComponent() {
  const t = useGT();
  return <p>{t('Hello')}</p>;
}

For truly dynamic content that needs runtime translation, see the Dynamic Content Guide.

Next Steps

How is this guide?

Strings