Server Components are rendered on the server and can directly access server-side resources. With the internationalization package, you can load translations directly in your Server Components without additional client-side JavaScript.
You can combine translations with dynamic content:
// Assuming the translation has a placeholder: "Welcome, {name}!"<p>{dictionary.web.greeting.replace('{name}', user.name)}</p>// For more complex replacements, you can use a helper functionfunction formatMessage(template: string, values: Record<string, string>) { return template.replace(/{(\w+)}/g, (_, key) => values[key] || '');}<p> {formatMessage(dictionary.web.lastLogin, { date: new Date().toLocaleDateString(params.locale), time: new Date().toLocaleTimeString(params.locale) })}</p>
The getDictionary function includes built-in fallback handling. If a translation is not available in the requested locale, it will fall back to English:
// This will use the English translation if the Spanish one doesn't existconst dictionary = await getDictionary('es');
You can also implement your own fallback logic for specific cases:
const title = dictionary.web.specialPage?.title || dictionary.web.defaultPage.title;
Define types for your translations to get better IDE support and catch errors early:
import type { Dictionary } from '@repo/internationalization';// Now you get type checking for dictionary accessconst dictionary: Dictionary = await getDictionary(locale);
Avoid String Concatenation
Instead of concatenating strings:
{/* Don't do this */}<p>{dictionary.web.greeting} {user.name}!</p>
Use placeholders:
{/* Do this instead */}<p>{dictionary.web.greeting.replace('{name}', user.name)}</p>