DeepWiki Internationalization: How Multi-Language Support Works

DeepWiki provides full internationalization (i18n) support through a data-driven React architecture that dynamically loads JSON translation bundles based on browser detection and user preference, supporting nine languages including English, Japanese, Chinese, and Spanish.

DeepWiki is an open-source wiki generator that ships with comprehensive DeepWiki internationalization capabilities out of the box. The application implements a three-layer i18n stack that separates static translation data from runtime detection logic, making it straightforward to add new languages without modifying core application code.

The Three-Layer DeepWiki i18n Architecture

DeepWiki’s internationalization system is organized into three coordinated layers that handle static assets, server-side configuration, and client-side runtime detection.

Static Language Data (JSON Message Bundles)

All UI translations reside in src/messages/*.json files. Each file maps translation keys to localized strings for a specific locale. For example, en.json contains English strings, while ja.json holds Japanese translations.

This static approach allows translators to work independently by editing JSON files without touching React components or Python backend code.

Server-Side Language Configuration

The backend exposes supported languages through a centralized configuration system. In api/config.py, the application loads config/lang.json into configs["lang_config"], which contains the list of supported languages and the default locale.

The FastAPI endpoint defined in api/api.py at lines 49-51 serves this configuration:

@router.get("/lang/config")
def get_lang_config():
    return configs["lang_config"]

The frontend accesses this endpoint at runtime to determine which languages are available. The rewrite rule in next.config.ts (lines 62-65) ensures that requests to /api/lang/config are properly proxied to the backend server.

Client-Side Runtime Detection

The React frontend handles dynamic language loading through two key files. src/i18n.ts defines the list of supported locales and returns a Next-Intl request configuration that dynamically imports the appropriate message bundle.

src/contexts/LanguageContext.tsx implements the core detection logic. It fetches /api/lang/config, detects the browser’s preferred language using navigator.language, and dynamically imports the matching JSON file from ../messages/${validLanguage}.json. The context exposes language, setLanguage, messages, and supportedLanguages to the entire component tree via the useLanguage hook.

How DeepWiki Detects and Loads Languages

When a user opens DeepWiki, the following workflow executes:

  1. Configuration Fetch: The LanguageProvider component requests /api/lang/config to retrieve supported languages and the default locale.
  2. Browser Detection: The detectBrowserLanguage() function extracts the two-letter language code from navigator.language. If the code exists in the supported locales list (imported from src/i18n.ts), it is selected; otherwise the default "en" is chosen.
  3. Bundle Loading: The provider dynamically imports ../messages/${validLanguage}.json and stores the translation object in React state.
  4. Context Availability: Components throughout the application access translations via the useLanguage hook, which reads from the LanguageContext.

When users manually switch languages via setLanguage, the process repeats steps 3-4 and also updates localStorage for persistence and the <html lang> attribute for accessibility.

Implementing Language Switching in React Components

Components can read and modify the current language using the useLanguage hook provided by src/contexts/LanguageContext.tsx.

Creating a Language Selector

import { useLanguage } from '@/contexts/LanguageContext';

export default function LanguageSwitcher() {
  const { language, setLanguage, supportedLanguages } = useLanguage();

  return (
    <select
      value={language}
      onChange={e => setLanguage(e.target.value)}
    >
      {Object.entries(supportedLanguages).map(([code, name]) => (
        <option key={code} value={code}>
          {name}
        </option>
      ))}
    </select>
  );
}

Accessing Translated Strings

import { useLanguage } from '@/contexts/LanguageContext';

export default function Header() {
  const { messages } = useLanguage();
  
  return (
    <h1>{messages['app.title'] ?? 'Deep Wiki'}</h1>
  );
}

The messages object contains the entire JSON translation bundle loaded dynamically from src/messages/, allowing components to reference keys safely using the nullish coalescing operator for fallbacks.

Adding a New Language to DeepWiki

DeepWiki’s data-driven architecture allows adding new languages without modifying core logic. To add German (de), for example:

  1. Register the locale in src/i18n.ts:
export const locales = [
  'en', 'ja', 'zh', 'es', 'kr', 'vi', 'pt-br', 'de'
];
  1. Update the server configuration in config/lang.json:
{
  "supported_languages": {
    "en": "English",
    "ja": "日本語 (Japanese)",
    "de": "Deutsch (German)"
  },
  "default": "en"
}
  1. Create the translation file at src/messages/de.json:
{
  "app.title": "Deep Wiki",
  "app.description": "Erstelle automatisch eine Wiki für jedes GitHub‑Repository."
}

No further code modifications are needed; the application automatically lists "Deutsch (German)" in the language selector and loads de.json when selected.

Summary

  • DeepWiki provides complete DeepWiki internationalization support through a three-layer architecture separating static JSON assets, server-side configuration, and client-side React context.
  • Translation files reside in src/messages/*.json, while src/i18n.ts and src/contexts/LanguageContext.tsx handle dynamic loading and browser detection.
  • The backend exposes supported languages via the /lang/config endpoint defined in api/api.py (lines 49-51), driven by config/lang.json.
  • Components access translations through the useLanguage hook, which provides messages, language, and setLanguage.
  • Adding new languages requires only three data files—no code changes—making DeepWiki’s i18n system fully extensible.

Frequently Asked Questions

Does DeepWiki support right-to-left (RTL) languages?

DeepWiki’s i18n infrastructure supports any language defined in the configuration files, but RTL layout handling depends on CSS implementation in the React components. The LanguageContext updates the <html lang> attribute, which can be used with CSS logical properties or libraries like rtl-css-js to handle text direction. However, the core message loading system in src/contexts/LanguageContext.tsx treats RTL and LTR languages identically.

How does DeepWiki handle fallback languages when a translation key is missing?

When a translation key is not found in the loaded messages object, DeepWiki relies on the consuming component to provide fallback behavior. The typical pattern uses the nullish coalescing operator (??) to provide default text, as shown in messages['app.title'] ?? 'Deep Wiki'. The system does not automatically cascade to a default language file; instead, it loads only the active locale’s JSON bundle from src/messages/ and expects complete key coverage within that file.

Can I use DeepWiki’s i18n system with Next.js App Router?

The current implementation uses a custom LanguageProvider context in src/contexts/LanguageContext.tsx that fetches configuration from /api/lang/config and manages state via React hooks. While this works with Next.js Pages Router, adapting it for the App Router would require moving the detection logic to a Server Component or using the next-intl library’s App Router configuration in src/i18n.ts. The static JSON files in src/messages/ remain compatible with both routing strategies.

What is the performance impact of dynamic message loading in DeepWiki?

DeepWiki uses dynamic imports to load only the active language bundle, keeping the initial JavaScript payload small. The LanguageContext caches the loaded messages in React state, preventing redundant fetches when components re-render. The /api/lang/config endpoint returns a small JSON object, and the system stores the user’s preference in localStorage to avoid re-detection on subsequent visits. This architecture ensures that adding new languages to src/messages/ does not increase the bundle size for users who do not select those languages.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →