logo
  • Guide
  • Config
  • Plugin
  • API
  • Examples
  • Community
  • Modern.js 2.x Docs
  • English
    • 简体中文
    • English
    • Start
      Introduction
      Quick Start
      Upgrading
      Glossary
      Tech Stack
      Core Concept
      Page Entry
      Build Engine
      Web Server
      Basic Features
      Routes
      Routing
      Config Routes
      Data Solution
      Data Fetching
      Data Writing
      Data Caching
      Rendering
      Server-Side Rendering
      Streaming SSR
      Rendering Cache
      Static Site Generation
      Render Preprocessing
      Styling
      Styling
      Use CSS Modules
      Using CSS-in-JS
      Using Tailwind CSS
      HTML Template
      Import Static Assets
      Import JSON Files
      Import SVG Assets
      Import Wasm Assets
      Debug
      Data Mocking
      Network Proxy
      Using Rsdoctor
      Using Storybook
      Testing
      Playwright
      Vitest
      Jest
      Cypress
      Path Alias
      Environment Variables
      Output Files
      Deploy Application
      Advanced Features
      Using Rspack
      Using BFF
      Basic Usage
      Runtime Framework
      Extend BFF Server
      Extend Request SDK
      File Upload
      Cross-Project Invocation
      Optimize Page Performance
      Code Splitting
      Inline Static Assets
      Bundle Size Optimization
      React Compiler
      Improve Build Performance
      Browser Compatibility
      Low-Level Tools
      Source Code Build Mode
      Server Monitor
      Monitors
      Logs Events
      Metrics Events
      Internationalization
      Basic Concepts
      Quick Start
      Configuration
      Locale Detection
      Resource Loading
      Routing Integration
      API Reference
      Advanced Usage
      Best Practices
      Custom Web Server
      Topic Detail
      Module Federation
      Introduction
      Getting Started
      Application-Level Modules
      Server-Side Rendering
      Deployment
      Integrating Internationalization
      FAQ
      Dependencies FAQ
      CLI FAQ
      Build FAQ
      HMR FAQ
      Deprecated
      📝 Edit this page
      Previous pageConfigurationNext pageResource Loading

      #Locale Detection

      The plugin supports multiple language detection methods, which can be combined to meet different business requirements.

      #Detection Methods

      #1. URL Path Detection (localePathRedirect)

      When localePathRedirect is set to true, the plugin will detect the language from the URL path.

      Examples:

      • /zh/about → Detected language: zh
      • /en/about → Detected language: en
      • /about → If there's no language prefix, will redirect to the default language path

      Configuration:

      i18nPlugin({
        localeDetection: {
          localePathRedirect: true,
          languages: ['zh', 'en'],
          fallbackLanguage: 'en',
        },
      });

      Route Configuration (Convention-based Routing):

      When using convention-based routing, you need to create a [lang] directory under the routes/ directory to represent the language parameter:

      routes/
      ├── [lang]/
      │   ├── layout.tsx    # Layout component
      │   ├── page.tsx      # Home page
      │   └── about/
      │       └── page.tsx  # About page

      routes/[lang]/layout.tsx:

      import { Outlet } from '@modern-js/runtime/router';
      
      export default function Layout() {
        return <Outlet />;
      }

      routes/[lang]/page.tsx:

      export default function Home() {
        return <div>Home</div>;
      }

      routes/[lang]/about/page.tsx:

      export default function About() {
        return <div>About</div>;
      }
      Info

      If using custom routing (modern.routes.ts), you need to add :lang dynamic parameter in the route configuration. Convention-based routing will automatically generate corresponding routes based on the file structure.

      #2. i18next Language Detector

      When i18nextDetector is set to true, the i18next language detector will be enabled, supporting language detection from the following locations:

      • Cookie: Read language settings from cookies
      • LocalStorage: Read from browser LocalStorage
      • Query Parameters: Read from URL query parameters (e.g., ?lng=en)
      • Request Headers: Read from HTTP request headers (e.g., Accept-Language)
      • HTML Tag: Read from the lang attribute of HTML tags
      • Subdomain: Read from subdomain (e.g., en.example.com)

      Configuration:

      i18nPlugin({
        localeDetection: {
          i18nextDetector: true,
          detection: {
            order: ['cookie', 'querystring', 'header'],
            lookupCookie: 'i18next',
            lookupQuerystring: 'lng',
            lookupHeader: 'accept-language',
            caches: ['cookie'],
          },
        },
      });

      #3. Custom Detection Configuration

      You can customize detection behavior through the detection option:

      i18nPlugin({
        localeDetection: {
          i18nextDetector: true,
          detection: {
            // Detection order
            order: ['path', 'cookie', 'querystring', 'header'],
      
            // Cookie related
            lookupCookie: 'i18next',
            cookieExpirationDate: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000), // Expires in 1 year
            cookieDomain: '.example.com',
      
            // Query parameter related
            lookupQuerystring: 'lng',
      
            // Request header related
            lookupHeader: 'accept-language',
      
            // Cache configuration
            caches: ['cookie', 'localStorage'],
          },
        },
      });

      #Detection Priority

      The plugin's language detection follows the following priority order (from highest to lowest):

      1. SSR Data (highest priority): Read language from window._SSR_DATA set during server-side rendering, applicable to both SSR and CSR projects
      2. Path Detection: If localePathRedirect is true, detect language prefix from URL path
      3. i18next Detector: Execute detection according to the order configured in detection.order (Cookie, LocalStorage, query parameters, request headers, etc.)
      4. User Configured Language: Use the language configured in initOptions.lng
      5. Fallback Language: Use fallbackLanguage as the final fallback
      Info

      SSR data detection has the highest priority to ensure the client uses the language detected during server-side rendering, avoiding language flickering issues caused by client-side re-detection.

      Example:

      // Configured detection order (only affects priority within i18next detector)
      detection: {
        order: ['path', 'cookie', 'querystring', 'header'],
      }
      
      // Actual detection flow:
      // 1. First check SSR data (window._SSR_DATA)
      // 2. Then check URL path (if localePathRedirect is enabled)
      // 3. Then check i18next detector according to order:
      //    - Cookie
      //    - Query parameters
      //    - Request headers
      // 4. Then use initOptions.lng (if configured)
      // 5. Finally use fallbackLanguage

      #Detection Options

      #order (Detection Order)

      Specifies the order of language detection, optional values:

      • path: Detect from URL path
      • querystring: Detect from query parameters
      • cookie: Detect from cookies
      • localStorage: Detect from LocalStorage
      • sessionStorage: Detect from SessionStorage
      • navigator: Detect from browser language settings
      • htmlTag: Detect from HTML tags
      • header: Detect from HTTP request headers
      • subdomain: Detect from subdomain
      Warning

      path detection requires localePathRedirect to be true. localStorage, sessionStorage, navigator, and htmlTag are only available in browser environments.

      #caches (Cache Method)

      Specifies where the detected language should be cached, optional values:

      • false: No caching
      • ['cookie']: Cache to Cookie
      • ['localStorage']: Cache to LocalStorage (browser only)
      • ['cookie', 'localStorage']: Cache to both Cookie and LocalStorage

      #lookupQuerystring, lookupCookie, lookupLocalStorage, lookupSession, lookupHeader

      Specifies the key name used when reading language from query parameters, cookies, LocalStorage, SessionStorage, or request headers:

      • lookupQuerystring: Default 'lng', e.g., ?lng=en
      • lookupCookie: Default 'i18next'
      • lookupLocalStorage: Default 'i18nextLng' (browser only)
      • lookupSession: SessionStorage key name (browser only)
      • lookupHeader: Default 'accept-language'

      #lookupFromPathIndex

      Specifies which position in the URL path to start detecting language (when 'path' is included in order):

      • lookupFromPathIndex: Path segment index, defaults to 0 (first path segment)

      Example:

      // URL: /api/v1/en/users
      // If lookupFromPathIndex = 2, detection starts from the third path segment ('en')
      detection: {
        order: ['path'],
        lookupFromPathIndex: 2,
      }

      #cookieMinutes, cookieExpirationDate

      Controls Cookie expiration time:

      • cookieMinutes: Cookie expiration time (minutes), default 525600 (1 year)
      • cookieExpirationDate: Cookie expiration date (Date object), takes precedence over cookieMinutes

      Example:

      detection: {
        cookieMinutes: 60 * 24 * 7, // Expires in 7 days
        // or
        cookieExpirationDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // Expires in 7 days
      }

      #ignoreRedirectRoutes

      Specifies which routes should ignore automatic language redirection. This is very useful for API routes, static resources, and other paths that don't need language prefixes.

      Configuration:

      i18nPlugin({
        localeDetection: {
          localePathRedirect: true,
          languages: ['zh', 'en'],
          fallbackLanguage: 'en',
          // String array: supports exact match and prefix match
          ignoreRedirectRoutes: ['/api', '/admin', '/static'],
          // Or use function for more flexible judgment
          ignoreRedirectRoutes: pathname => {
            return pathname.startsWith('/api') || pathname.startsWith('/admin');
          },
        },
      });

      Matching Rules:

      • String array: Supports exact match ('/api') and prefix match ('/api' will match /api and /api/users)
      • Function: Receives pathname (with language prefix removed), returns true to indicate ignoring redirection

      Example:

      // Ignore all API routes and static resources
      ignoreRedirectRoutes: ['/api', '/static', '/assets'];
      
      // Use function to ignore all paths starting with /api
      ignoreRedirectRoutes: pathname => pathname.startsWith('/api');