Theme

Advanced Guides

Internationalization (i18n)

Internationalization (i18n) in Velocity Core is a powerful feature that enables the creation of multi-lingual applications with localized content and formatting. This is crucial for applications targeting a global audience, ensuring that text, dates, numbers, and other elements are presented in the user’s preferred language and locale.

Velocity Core leverages the @formatjs/intl package to provide robust support for translations and locale-based formatting. This allows developers to build applications that are not only internationalized but also flexible enough to handle various linguistic and regional variations.

Translation Files

Translations in Velocity Core are managed through JSON files stored in the src/i18n/ directory. Each file corresponds to a different locale and is named with the locale code (e.g., en.json, de.json). This format integrates seamlessly with translation management tools like Crowdin or Phrase, simplifying the workflow for translators and developers alike.

The translation strings use the standardized ICU message syntax, which enables the inclusion of dynamic values, plural rules, and conditional logic. This ensures that your content is properly formatted based on locale-specific rules.

Here's an example of a translation file:

{
  "account": {
    "firstName": "First Name",
    "lastName": "Last Name"
  },
  "cart": {
    "items": "{itemCount, plural, one {# item} other {# items}}"
  },
  "checkout": {
    "termsAndConditions": "I agree to the <termsAndConditionsLink>Terms and Conditions<termsAndConditionsLink>."
  }
}

Accessing Translations in Your Components

To access these translations within your Velocity Core components, use the useI18n() utility, which provides a t function that can be used for dynamic text rendering.

Basic Usage

import useI18n from '~/i18n';

const MyComponent = () => {
  const { t } = useI18n();
  return <div>{t('account.firstName')}</div>;
};

Using Dynamic Values

To include dynamic values in your translations, pass them as arguments to the t function:

const MyComponent = () => {
  const { t } = useI18n();
  return <div>{t('cart.items', { itemCount: 14 })}</div>;
};

This will output the appropriate plural form based on the value of itemCount (e.g., "14 items").

Using Rich Text Elements

For more complex cases where rich text elements are needed, you can include them using placeholders:

const MyComponent = () => {
  const { t } = useI18n();
  return (
    <div>
      {t('checkout.termsAndConditions', {
        termsAndConditionsLink: chunk => <a href="https://example.com/terms-and-conditions">{chunk}</a>
      })}
    </div>
  );
};

Formatting Dates, Numbers, and More

useI18n() provides convenient functions for formatting dates, numbers, and other locale-sensitive data:

const MyComponent = () => {
  const { formatDate, formatNumber } = useI18n();
  return (
    <div>
      <p>{formatDate(new Date())}</p>
      <p>{formatNumber(123456.789)}</p>
    </div>
  );
};

To both these functions, you can pass additional options to customize the formatting as a second parameter.

Getting the Current Locale

To determine the current locale being used, you can access it through the useI18n() utility:

const { locale } = useI18n();

This is useful for displaying locale-specific information or for programmatically determining the current language setting within your components.

Locale-Prefixed Navigation

The useI18n() utility also provides the addLocalePrefix function. This function ensures that your links include the current locale as a prefix.

const MyComponent = () => {
  const { addLocalePrefix } = useI18n();
  return <a href={addLocalePrefix('/my-new-page')}>Go to New Page</a>;
};

Configuring Available Locales

By default, the base project comes with en (English) and de (German) preconfigured. If you need to add or modify the available locales:

  1. Update the availableLocales array in src/i18n/index.ts.
  2. Import and add the new JSON files to the messages object in the same file.
import * as de from './de.json';
import * as en from './en.json';
// Import additional locales as needed
import * as es from './es.json';

// Add your new locale codes here
export const availableLocales = ['en', 'de', 'es'] as const;

// Add your new locale messages here
const messages: Record<Locale, Record<string, any>> = { en, de, es };
Previous
Client-Side Interactivity