Skip to main content
App Shell includes built-in internationalization support for creating multi-language applications. This guide shows you how to translate UI strings, module titles, and custom content.

How i18n Works in App Shell

App Shell provides two levels of internationalization:
  1. Built-in UI strings - Navigation, command palette, error messages (English and Japanese included)
  2. Your application strings - Module titles, page content, custom labels (you define these)
The locale is determined by:
  • Explicit locale prop on AppShell (if provided)
  • Browser language detection (if no prop provided)
  • Fallback to English if the detected language isn’t supported

Quick Start

Setting the Locale

Supported locales for built-in UI:
  • en - English (default)
  • ja - Japanese
You can pass any locale string (e.g., "fr", "de"), but built-in UI strings will fall back to English. Your custom labels defined with defineI18nLabels will work with any locale.

Defining Custom Labels

Use defineI18nLabels to create type-safe translations for your application:
1

Create a Labels File

Create i18n-labels.ts to define your translations:
The en locale is required and serves as the fallback for any missing translations.
2

Use in Module Definitions

Use labels.t() for module and resource titles:
3

Use in Components

Use the useT hook to translate strings in your components:

Dynamic Label Keys

For runtime-determined label keys (like status badges), use t.dynamic():
The second argument to t.dynamic() is the fallback text if the key doesn’t exist.

Switching Locales at Runtime

Allow users to change the language:

Real-World Example

Here’s a complete example from the App Shell source code:

Built-in UI Translations

App Shell includes these built-in translations: These translate automatically based on the locale prop.

Advanced Patterns

Pluralization

Handle singular and plural forms:

Nested Translations

Organize labels with dot notation:

Date and Number Formatting

Use browser APIs for locale-aware formatting:

Best Practices

Organization

  • Keep all labels in a single i18n-labels.ts file
  • Use consistent naming: "module.resource.label"
  • Group related labels together
  • Document complex pluralization rules

Translation Quality

  • Work with native speakers for accurate translations
  • Keep strings short and context-independent
  • Avoid hard-coded punctuation (it varies by language)
  • Test with real content, not placeholder text

Type Safety

Performance

  • Labels are loaded once and cached
  • No runtime overhead for static strings
  • Dynamic functions are memoized per locale

Limitations

  • Built-in UI strings only support English and Japanese
  • No automatic RTL (right-to-left) layout support
  • Date/time formatting requires manual integration with Intl APIs
For advanced i18n needs (ICU message format, context-aware translations), consider integrating a library like react-intl or i18next.