zoonk-translations
0
总安装量
1
周安装量
安装命令
npx skills add https://github.com/zoonk/zoonk --skill zoonk-translations
Agent 安装分布
amp
1
opencode
1
cursor
1
kimi-cli
1
github-copilot
1
Skill 文档
Internationalization (i18n) Workflow
Overview
This project uses next-intl for internationalization. Translations are stored in JSON message files.
Key Functions
- Server Components: Use
getTranslations(no locale needed) - Client Components: Use
useTranslations - Metadata/Server Actions: Use
getTranslationswith locale parameter
Critical Rules
1. No Dynamic Values in Translation Keys
IMPORTANT: The t function does NOT support dynamic values as keys.
// BAD: Dynamic key - will NOT work
const category = getCategory();
t(category); // Error!
t(MYLABELS[category]);
// GOOD: String literals only
t("Arts courses");
t("Business courses");
t("Technology courses");
2. String Interpolation IS Supported
You CAN use string interpolation for dynamic values within translations:
// GOOD: Interpolation with static key
t("Explore all {category} courses", { category: "arts" });
t("Welcome, {name}!", { name: user.name });
t("{count} items remaining", { count: 5 });
3. Don’t Pass t Function Around
You can’t pass the t function to other functions or components:
// BAD: Passing t function
function myFunction(t, label) {
return t(label);
}
myFunction(t, "Some label");
// GOOD: Call t directly
function myFunction(translatedLabel: string) {
return translatedLabel;
}
myFunction(t("Some label"));
4. Locale Parameter Rules
// Server Component - no locale needed
const t = await getTranslations();
t("Hello");
// generateMetadata - needs locale
export async function generateMetadata({ params }) {
const { locale } = await params;
const t = await getTranslations({ locale });
return { title: t("Page Title") };
}
Workflow for Adding Translations
-
Add translation call in code:
const t = await getTranslations(); return <h1>{t("New page title")}</h1>; -
Add the key to message files:
Find JSON message files in your locales directory (e.g.,
messages/en.json,messages/es.json) and add the new key:{ "New page title": "New page title" } -
Translate for each locale:
// messages/es.json { "New page title": "Nuevo tÃtulo de página" }
Common Patterns
Conditional Text
// Use separate translation keys
const status = isActive ? t("Active") : t("Inactive");
Pluralization
// Use ICU message format
t("items", { count: 5 }); // "5 items"
In your messages file:
{
"items": "{count, plural, =0 {No items} =1 {1 item} other {# items}}"
}
Rich Text (with components)
t.rich("Read our {link}", {
link: (chunks) => <Link href="/terms">{chunks}</Link>,
});
In your messages file:
{
"Read our {link}": "Read our <link>terms of service</link>"
}
File Structure
messages/
en.json # English translations
es.json # Spanish translations
pt.json # Portuguese translations
Namespaces
For larger apps, organize translations by namespace:
// Server Component
const t = await getTranslations("Dashboard");
t("welcome"); // Looks up "Dashboard.welcome"
// Client Component
const t = useTranslations("Dashboard");
t("welcome");
{
"Dashboard": {
"welcome": "Welcome to your dashboard"
}
}