Strings
How to internationalise plain text strings using useGT and getGT
String translation provides direct access to text translations without JSX — ideal for attributes, object properties, and plain text values. Use useGT in synchronous components and getGT in asynchronous components.
Synchronous vs Asynchronous Use
- Synchronous components:
useGThook for React components - Asynchronous components:
getGTasync 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 address')}
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 address')}
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 catalogue')}
/>Object properties
const t = useGT();
const user = {
name: 'John',
role: 'admin',
bio: t('Experienced software developer with 5 years’ experience 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 shop</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 {count, plural, =0 {are no items} =1 {is one item} other {are {count} items}} in the basket', { count: 10 });Learn more about the 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>
);
}Navigation menu
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 despatch'),
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 Catalogue – 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 can’t 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 Rule Violations
Follow the React Hooks 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 correct 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 genuinely dynamic content that requires translation at runtime, see the Dynamic Content Guide.
Next steps
- Dynamic Content Guide - Handle runtime translation
- Shared Strings Guide - Organise reusable translations
- API references:
How is this guide?