or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdcontext.mdi18n.mdindex.mdplugin-system.mdrouting.mdswizzling.md
tile.json

i18n.mddocs/

Internationalization

Multi-language support including locale configuration, translation files, and runtime i18n state.

Capabilities

I18nConfig

Main internationalization configuration for multi-language sites.

/**
 * Main i18n configuration for multi-language support
 */
interface I18nConfig {
  /** 
   * Default locale that:
   * - Has no locale prefix in URLs
   * - Is used by `docusaurus start` without --locale option
   * - Gets the `<link hrefLang="x-default">` tag
   */
  defaultLocale: string;
  
  /** 
   * Root folder for all locale folders
   * Can be absolute or relative to config file
   */
  path: string;
  
  /** List of all locales. Must include defaultLocale. */
  locales: [string, ...string[]];
  
  /** Individual configuration for each locale */
  localeConfigs: {[locale: string]: Partial<I18nLocaleConfig>};
}

Usage Example:

import type { I18nConfig } from '@docusaurus/types';

const i18nConfig: I18nConfig = {
  defaultLocale: 'en',
  path: 'i18n',
  locales: ['en', 'fr', 'ja'],
  localeConfigs: {
    en: {
      label: 'English',
      direction: 'ltr',
      htmlLang: 'en-US'
    },
    fr: {
      label: 'Français',
      direction: 'ltr',
      htmlLang: 'fr-FR'
    },
    ja: {
      label: '日本語',
      direction: 'ltr',
      htmlLang: 'ja-JP'
    }
  }
};

I18nLocaleConfig

Configuration for individual locales including display settings and paths.

/**
 * Configuration for an individual locale
 */
interface I18nLocaleConfig {
  /** Display label for this locale in dropdowns */
  label: string;
  
  /** 
   * BCP 47 language tag for:
   * - <html lang="..."> attribute
   * - <link hreflang="..."> tags
   */
  htmlLang: string;
  
  /** Text direction for CSS and HTML attributes */
  direction: 'ltr' | 'rtl';
  
  /** 
   * Calendar system for date formatting
   * Controls date era calculation, not display format
   */
  calendar: string;
  
  /** 
   * Root folder for this locale's translations
   * Relative to i18n.path, defaults to locale name
   */
  path: string;
}

Runtime I18n State

Runtime internationalization state available throughout the application.

/**
 * Runtime i18n state with complete configuration
 */
interface I18n extends DeepRequired<I18nConfig> {
  /** Currently active locale */
  currentLocale: string;
}

Usage Example:

import { useDocusaurusContext } from '@docusaurus/core';

function LocaleInfo() {
  const { i18n } = useDocusaurusContext();
  
  const currentLocaleConfig = i18n.localeConfigs[i18n.currentLocale];
  
  return (
    <div dir={currentLocaleConfig.direction}>
      <p>Current locale: {i18n.currentLocale}</p>
      <p>Label: {currentLocaleConfig.label}</p>
      <p>HTML lang: {currentLocaleConfig.htmlLang}</p>
      <p>Available locales: {i18n.locales.join(', ')}</p>
    </div>
  );
}

Translation System

Translation File Structure

Structure for managing translation files and their content.

/**
 * Individual translation message with optional description
 */
interface TranslationMessage {
  /** The translated text */
  message: string;
  /** Optional description for translators */
  description?: string;
}

/**
 * Content of a translation file mapping message IDs to translations
 */
interface TranslationFileContent {
  [msgId: string]: TranslationMessage;
}

/**
 * Abstract representation of a translation file
 */
interface TranslationFile {
  /** 
   * File path relative to plugin's i18n directory
   * Should NOT include file extension
   */
  path: string;
  /** Translation content */
  content: TranslationFileContent;
}

Usage Example:

// Example translation file content
const blogTranslations: TranslationFileContent = {
  'blog.title': {
    message: 'Blog',
    description: 'Title for the blog section'
  },
  'blog.readMore': {
    message: 'Read more',
    description: 'Link text to read full blog post'
  },
  'blog.author': {
    message: 'By {author}',
    description: 'Author attribution with placeholder'
  }
};

// Creating translation file
const translationFile: TranslationFile = {
  path: 'blog',  // Will be saved as blog.json
  content: blogTranslations
};

Plugin Translation Integration

How plugins provide and use translations:

import type { Plugin, TranslationFile } from '@docusaurus/types';

const blogPlugin: Plugin = {
  name: 'blog-plugin',
  
  // Provide translation files
  async getTranslationFiles({ content }) {
    return [
      {
        path: 'blog',
        content: {
          'blog.title': {
            message: 'Blog',
            description: 'Blog section title'
          },
          'blog.posts.count': {
            message: '{count} posts',
            description: 'Number of posts with count placeholder'
          }
        }
      }
    ];
  },
  
  // Provide default code translations
  getDefaultCodeTranslationMessages() {
    return {
      'theme.blog.readMore': 'Read more',
      'theme.blog.author': 'By {author}'
    };
  },
  
  // Translate content using translation files
  translateContent({ content, translationFiles }) {
    // Apply translations to content
    return translatedContent;
  },
  
  // Translate theme configuration
  translateThemeConfig({ themeConfig, translationFiles }) {
    // Apply translations to theme config
    return translatedThemeConfig;
  }
};

Code Translations

Runtime code translations for use in React components.

/**
 * Runtime code translations mapping message IDs to translated strings
 */
interface CodeTranslations {
  [msgId: string]: string;
}

Usage Example:

import { translate } from '@docusaurus/Translate';
import { useDocusaurusContext } from '@docusaurus/core';

function BlogPost({ author, readingTime }: Props) {
  const { codeTranslations } = useDocusaurusContext();
  
  // Using translate function with message ID
  const readMoreText = translate({
    id: 'theme.blog.readMore',
    message: 'Read more',
    description: 'Link to read full blog post'
  });
  
  // Direct access to code translations
  const authorText = codeTranslations['theme.blog.author'];
  
  return (
    <article>
      <p>{authorText.replace('{author}', author)}</p>
      <p>Reading time: {readingTime} min</p>
      <a href="#full-post">{readMoreText}</a>
    </article>
  );
}

Translation File Organization

Translation files are organized by plugin and locale:

i18n/
├── en/
│   ├── docusaurus-plugin-content-docs/
│   │   ├── current/
│   │   │   └── docs.json
│   │   └── version-1.0/
│   │       └── docs.json
│   ├── docusaurus-plugin-content-blog/
│   │   └── blog.json
│   └── docusaurus-theme-classic/
│       └── theme.json
├── fr/
│   ├── docusaurus-plugin-content-docs/
│   │   └── current/
│   │       └── docs.json
│   └── docusaurus-theme-classic/
│       └── theme.json
└── ja/
    └── docusaurus-theme-classic/
        └── theme.json

Locale-Aware URL Generation

import { useDocusaurusContext } from '@docusaurus/core';

function LocalizedNavigation() {
  const { i18n, siteConfig } = useDocusaurusContext();
  
  // Generate locale-aware URLs
  const getLocalizedUrl = (path: string, locale?: string) => {
    const targetLocale = locale || i18n.currentLocale;
    const isDefaultLocale = targetLocale === i18n.defaultLocale;
    
    const baseUrl = siteConfig.baseUrl;
    const localePrefix = isDefaultLocale ? '' : `/${targetLocale}`;
    
    return `${baseUrl}${localePrefix}${path}`;
  };
  
  return (
    <nav>
      {i18n.locales.map(locale => (
        <a 
          key={locale}
          href={getLocalizedUrl('/docs', locale)}
          hrefLang={i18n.localeConfigs[locale].htmlLang}
        >
          {i18n.localeConfigs[locale].label}
        </a>
      ))}
    </nav>
  );
}