Lingx i18n Patterns
Type-safe internationalization patterns using the Lingx SDK.
Quick Reference
import { useTranslation, tKey, tKeyUnsafe, type TKey } from '@lingx/sdk-nextjs';
// In component
const { t, td } = useTranslation('namespace');
t('key.path') // Static key
td(tKey('key.path')) // Dynamic key, type-safe
td(tKeyUnsafe(`${var}.title`)) // Dynamic key, escape hatch
File Organization
apps/web/public/locales/
├── en.json # Root namespace (common strings)
├── ru.json
├── dashboard/ # Dashboard namespace
│ ├── en.json
│ └── ru.json
├── settings/ # Settings namespace
│ ├── en.json
│ └── ru.json
├── projects/ # Projects namespace
│ ├── en.json
│ └── ru.json
└── workbench/ # Workbench namespace
├── en.json
└── ru.json
Documentation
Core Concepts
Translation Functions
| Function |
Use Case |
Type Safety |
t('key') |
Static string literal keys |
Full |
td(dynamicKey) |
Dynamic keys from variables |
Via tKey |
tKey('key') |
Create type-safe key reference |
Full |
tKeyUnsafe('key') |
Escape hatch for dynamic keys |
None |
Namespace Usage
// Using namespace - looks in [namespace]/en.json
const { t } = useTranslation('settings');
t('title'); // Looks for "title" in settings/en.json
// Root namespace - looks in en.json
const { t } = useTranslation();
t('common.save'); // Looks for "common.save" in en.json
Basic Usage
'use client';
import { useTranslation } from '@lingx/sdk-nextjs';
export function SettingsPage() {
const { t } = useTranslation('settings');
return (
<div>
<h1>{t('title')}</h1>
<p>{t('description')}</p>
<button>{t('actions.save')}</button>
</div>
);
}
With Dynamic Keys
import { useTranslation, tKey, type TKey } from '@lingx/sdk-nextjs';
interface NavItem {
href: string;
labelKey: TKey; // Type-safe key reference
}
const navItems: NavItem[] = [
{ href: '/', labelKey: tKey('nav.home') },
{ href: '/projects', labelKey: tKey('nav.projects') },
];
function Nav() {
const { td } = useTranslation();
return (
<nav>
{navItems.map((item) => (
<a key={item.href} href={item.href}>
{td(item.labelKey)} {/* Use td() for dynamic keys */}
</a>
))}
</nav>
);
}
Decision Tree
What translation function to use?
Is the key a string literal in code?
└─ YES → Use t('key')
└─ NO → Is the key from a typed variable/prop?
└─ YES → Use td(tKey('key')) or td(prop.labelKey)
└─ NO → Use td(tKeyUnsafe(dynamicKey))
---
Where to put the key?
Is it used across multiple pages/namespaces?
└─ YES → Root en.json (common.*)
Is it specific to one feature/page?
└─ YES → [namespace]/en.json
Best Practices
DO
// ✅ Use namespace in useTranslation
const { t } = useTranslation('settings');
t('security.title');
// ✅ Use tKey for typed dynamic keys
const items = [{ labelKey: tKey('nav.home') }];
// ✅ Use ICU for plurals
t('items.count', { count: 5 });
// "items.count": "{count, plural, one {# item} other {# items}}"
DON'T
// ❌ Don't use variables directly in t()
t(variableName); // No type checking!
// ❌ Don't concatenate keys
t('section.' + name); // No type checking!
// ❌ Don't use template literals in t()
t(`${section}.title`); // No type checking!
Common Patterns
Conditional Text with ICU Select
// Translation file
{
"status": "{state, select, enabled {Enabled} disabled {Disabled} other {Unknown}}"
}
// Usage
t('status', { state: isEnabled ? 'enabled' : 'disabled' })
Pluralization
{
"items": "{count, plural, one {# item} other {# items}}"
}
t('items', { count: 1 }); // "1 item"
t('items', { count: 5 }); // "5 items"
With Variables
{
"greeting": "Hello, {name}!"
}
t('greeting', { name: user.name });