Строки
Как интернационализировать простые текстовые строки с помощью useGT и getGT
Перевод строк предоставляет прямой доступ к переводам текста без JSX — это удобно для атрибутов, свойств объектов и обычных текстовых значений. Используйте useGT в синхронных компонентах и getGT в асинхронных.
Синхронное и асинхронное использование
- Синхронные компоненты: хук
useGTдля React‑компонентов - Асинхронные компоненты: асинхронная функция
getGTдля асинхронных компонентов
Быстрый старт
Синхронные компоненты
import { useGT } from 'gt-next';
function MyComponent() {
const t = useGT();
return (
<input
placeholder={t('Введите вашу электронную почту')}
title={t('Поле адреса электронной почты')}
/>
);
}Асинхронные компоненты
import { getGT } from 'gt-next/server';
async function MyServerComponent() {
const t = await getGT();
return (
<input
placeholder={t('Введите ваш email')}
title={t('Поле ввода email-адреса')}
/>
);
}Когда использовать перевод строк
Перевод строк подходит, когда вам нужен обычный текст, а не JSX:
Атрибуты HTML
const t = useGT();
<input
placeholder={t('Поиск товаров...')}
aria-label={t('Поле для поиска товаров')}
title={t('Начните вводить текст для поиска в каталоге')}
/>Свойства объектов
const t = useGT();
const user = {
name: 'John',
role: 'admin',
bio: t('Опытный разработчик ПО с 5-летним опытом работы с React'),
status: t('Доступен для новых проектов')
};Конфигурация и константы
const t = useGT();
const navigationItems = [
{ label: t('Главная'), href: '/' },
{ label: t('Продукты'), href: '/products' },
{ label: t('Связаться'), href: '/contact' }
];Когда использовать <T>
Используйте компонент <T> для JSX‑контента:
// ✅ Используйте <T> для JSX‑контента
<T><p>Добро пожаловать в <strong>наш магазин</strong>!</p></T>
// ✅ Используйте строковый перевод для простого текста
<input placeholder={t('Искать товары')} />Работа с переменными
Базовые переменные
Заменяйте заполнительные значения динамическими:
const t = useGT();
const itemCount = 5;
// String with placeholder
const message = t('У вас {count} товара в корзине', { count: itemCount });
// Результат: «У вас 5 товаров в корзине»Несколько переменных
const t = useGT();
const order = { id: 'ORD-123', total: 99.99, date: '2024-01-15' };
const confirmation = t(
'Заказ {orderId} на сумму ${total} оформлен {date}',
{
orderId: order.id,
total: order.total,
date: order.date
}
);Формат сообщений ICU
Для расширенного форматирования используйте синтаксис ICU:
const t = useGT();
translate('В корзине {count, plural, =0 {нет товаров} one {# товар} few {# товара} many {# товаров} other {# товара}}', { count: 10 });Подробнее о формате сообщений ICU см. в документации Unicode.
Примеры
Элементы формы
import { useGT } from 'gt-next';
function ContactForm() {
const t = useGT();
return (
<form>
<input
type="email"
placeholder={t('Введите адрес электронной почты')}
aria-label={t('Поле для ввода email')}
/>
<textarea
placeholder={t('Расскажите о вашем проекте...')}
aria-label={t('Описание проекта')}
/>
<button type="submit">
{t('Отправить')}
</button>
</form>
);
}Навигационное меню
import { useGT } from 'gt-next';
function Navigation() {
const t = useGT();
const menuItems = [
{ label: t('Главная'), href: '/', icon: 'home' },
{ label: t('О нас'), href: '/about', icon: 'info' },
{ label: t('Услуги'), href: '/services', icon: 'briefcase' },
{ label: t('Контакты'), 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>
);
}Фабрика динамического контента
// utils/productData.js
export function getProductMessages(t) {
return {
categories: [
{ id: 'electronics', name: t('Электроника') },
{ id: 'clothing', name: t('Одежда') },
{ id: 'books', name: t('Книги') }
],
statusMessages: {
available: t('В наличии, готово к отправке'),
backordered: t('Временно отсутствует — отправка через 2–3 недели'),
discontinued: t('Товар снят с производства')
},
errors: {
notFound: t('Товар не найден'),
outOfStock: t('К сожалению, товар временно отсутствует')
}
};
}
// 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>
);
}Компонент сервера с метаданными
import { getGT } from 'gt-next/server';
export async function generateMetadata({ params }) {
const t = await getGT();
return {
title: t('Каталог товаров — найдите всё, что вам нужно'),
description: t('Просмотрите нашу обширную коллекцию качественных товаров'),
openGraph: {
title: t('Покупайте у нас'),
description: t('Откройте отличные предложения на самые популярные товары')
}
};
}
export default async function ProductPage() {
const t = await getGT();
return (
<div>
<h1>{t('Рекомендуемые товары')}</h1>
<p>{t('Ознакомьтесь с нашими новинками и самыми популярными товарами')}</p>
</div>
);
}Распространённые проблемы
Динамический контент во время выполнения
Строки должны быть определены на этапе сборки — переводить динамический контент нельзя:
// ❌ Динамический контент не будет работать
function MyComponent() {
const [userMessage, setUserMessage] = useState('');
const t = useGT();
return <p>{t(userMessage)}</p>; // Это не сработает
}
// ✅ Используйте заранее определённые строки
function MyComponent() {
const [messageType, setMessageType] = useState('welcome');
const t = useGT();
const messages = {
welcome: t('Добро пожаловать в наше приложение!'),
goodbye: t('Спасибо, что заглянули!')
};
return <p>{messages[messageType]}</p>;
}Нарушения правил хуков
Соблюдайте правила хуков React при использовании useGT:
// ❌ Не вызывайте хуки условно
function MyComponent({ showMessage }) {
if (showMessage) {
const t = useGT(); // Нарушение правила хуков
return <p>{t('Привет!')}</p>;
}
return null;
}
// ✅ Всегда вызывайте хуки на верхнем уровне
function MyComponent({ showMessage }) {
const t = useGT();
if (showMessage) {
return <p>{t('Привет!')}</p>;
}
return null;
}Синхронно vs асинхронно: частая путаница
Используйте подходящую функцию для вашего типа компонента:
// ❌ Неверно: useGT в асинхронном компоненте
export default async function AsyncComponent() {
const t = useGT(); // Это не сработает
return <p>{t('Hello')}</p>;
}
// ✅ Правильно: getGT в асинхронном компоненте
export default async function AsyncComponent() {
const t = await getGT();
return <p>{t('Hello')}</p>;
}
// ✅ Правильно: useGT в синхронном компоненте
export default function SyncComponent() {
const t = useGT();
return <p>{t('Hello')}</p>;
}Для по‑настоящему динамического контента, которому нужен перевод на этапе выполнения, см. руководство по динамическому контенту.
Дальнейшие шаги
- Руководство по динамическому контенту — Обработка переводов во время выполнения
- Руководство по общим строкам — Организация повторно используемых переводов
- Справочные материалы по API:
Насколько полезно это руководство?