> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/pfrankov/obsidian-local-gpt/llms.txt
> Use this file to discover all available pages before exploring further.

# Localization & Internationalization

> Multi-language support and translation system in Local GPT

# Localization & Internationalization

Local GPT supports 11 languages out of the box, with automatic language detection and a community-driven translation system.

## Supported Languages

The plugin includes complete translations for:

<CardGroup cols={3}>
  <Card title="English" icon="flag-usa">
    `en` - Default language
  </Card>

  <Card title="German" icon="flag">
    `de` - Deutsch
  </Card>

  <Card title="Spanish" icon="flag">
    `es` - Español
  </Card>

  <Card title="French" icon="flag">
    `fr` - Français
  </Card>

  <Card title="Italian" icon="flag">
    `it` - Italiano
  </Card>

  <Card title="Japanese" icon="flag">
    `ja` - 日本語
  </Card>

  <Card title="Korean" icon="flag">
    `ko` - 한국어
  </Card>

  <Card title="Dutch" icon="flag">
    `nl` - Nederlands
  </Card>

  <Card title="Portuguese" icon="flag">
    `pt` - Português
  </Card>

  <Card title="Russian" icon="flag">
    `ru` - Русский
  </Card>

  <Card title="Chinese" icon="flag">
    `zh` - 中文
  </Card>
</CardGroup>

## Language Detection

Local GPT uses Obsidian's language setting automatically. The active language is determined by:

```typescript theme={null}
const locale = window.localStorage.getItem("language") || "en";
```

No manual configuration is needed - the plugin adapts to your Obsidian interface language.

## How Language Detection Works

For advanced use cases like detecting the language of user content, Local GPT includes a sophisticated language detection system in `src/languageDetection.ts`.

### Script-Based Detection

The system first checks for distinctive writing systems:

<AccordionGroup>
  <Accordion title="Japanese (Hiragana, Katakana)">
    Detects Unicode ranges:

    * `U+3040 - U+309F`: Hiragana
    * `U+30A0 - U+30FF`: Katakana
    * `U+31F0 - U+31FF`: Katakana Phonetic Extensions
    * `U+FF65 - U+FF9F`: Halfwidth Katakana
  </Accordion>

  <Accordion title="Chinese (Han Characters)">
    Detects Unicode ranges:

    * `U+3400 - U+4DBF`: CJK Unified Ideographs Extension A
    * `U+4E00 - U+9FFF`: CJK Unified Ideographs

    <Note>
      When Japanese text contains Han characters (Kanji), they are counted as Japanese if Hiragana/Katakana is also present.
    </Note>
  </Accordion>

  <Accordion title="Korean (Hangul)">
    Detects Unicode ranges:

    * `U+1100 - U+11FF`: Hangul Jamo
    * `U+3130 - U+318F`: Hangul Compatibility Jamo
    * `U+AC00 - U+D7AF`: Hangul Syllables
  </Accordion>

  <Accordion title="Russian/Cyrillic">
    Detects Unicode ranges:

    * `U+0400 - U+04FF`: Cyrillic
    * `U+0500 - U+052F`: Cyrillic Supplement
    * `U+2DE0 - U+2DFF`: Cyrillic Extended-A
    * `U+A640 - U+A69F`: Cyrillic Extended-B

    <Info>
      The `ru` code represents Cyrillic script used by Russian, Ukrainian, Bulgarian, Serbian, and other languages. The detector identifies the script, not the specific language.
    </Info>
  </Accordion>

  <Accordion title="Other Scripts">
    Also supports:

    * **Arabic** (`ar`): `U+0600 - U+06FF`, `U+0750 - U+077F`, `U+08A0 - U+08FF`
    * **Hebrew** (`he`): `U+0590 - U+05FF`
    * **Greek** (`el`): `U+0370 - U+03FF`, `U+1F00 - U+1FFF`
    * **Hindi/Devanagari** (`hi`): `U+0900 - U+097F`
  </Accordion>
</AccordionGroup>

### Latin-Script Detection

For Latin-based languages (English, Spanish, French, etc.), the system uses:

**Character-based scoring:**

* Distinctive diacritics (ñ, ü, ç, õ, etc.)
* Weight: 3 points per character

**Word-based scoring:**

* Common words ("the", "der", "le", "el", etc.)
* Weight: 2 points per occurrence

**Example detection logic:**

```typescript theme={null}
// French detection
chars: ["œ", "æ", "ç", "é", "è", "ê", "ë", ...]
words: ["le", "la", "les", "est", "pour", "que", ...]

// Spanish detection  
chars: ["ñ", "á", "é", "í", "ó", "ú", "¿", "¡"]
words: ["el", "la", "que", "para", "con", "muy", ...]
```

### Performance Optimization

```typescript theme={null}
const MAX_ANALYSIS_LENGTH = 1000;
const MIN_LATIN_LETTERS_THRESHOLD = 10;
```

* Only the first **1,000 characters** are analyzed
* Latin language detection requires at least **10 letters** to avoid false positives on short text

## Translation System

The i18n system is implemented in `src/i18n/index.ts`:

```typescript theme={null}
export class I18n {
  static t(key: string, params?: { [key: string]: string }): string {
    const locale = window.localStorage.getItem("language") || "en";
    const keys = key.split(".");
    let translations = locales[locale] || locales["en"];
    
    // Traverse nested keys
    for (const k of keys) {
      if (translations?.[k] === undefined) {
        // Fall back to English
        translations = locales["en"];
      }
      translations = translations[k];
    }
    
    // String interpolation
    if (params) {
      Object.entries(params).forEach(([key, value]) => {
        result = result.replace(`{{${key}}}`, value);
      });
    }
    
    return result;
  }
}
```

### Translation File Structure

Translations are stored in `src/i18n/*.json` files:

```json theme={null}
{
  "commands": {
    "showContextMenu": "Show context menu",
    "actionPalette": {
      "name": "Action Palette",
      "placeholder": "Your prompt... | Enter: send, Esc: cancel"
    }
  },
  "notices": {
    "errorGenerating": "Error while generating text: {{message}}"
  },
  "settings": {
    "creativity": "Creativity",
    "creativityLow": "💡 Low"
  }
}
```

### Using Translations

In the code, translations are accessed via dot notation:

```typescript theme={null}
import { I18n } from "./i18n";

// Simple translation
I18n.t("commands.showContextMenu")
// → "Show context menu"

// With parameters
I18n.t("notices.errorGenerating", { message: "Connection failed" })
// → "Error while generating text: Connection failed"
```

## Contributing Translations

We welcome community contributions to improve translations or add new languages!

<Steps>
  <Step title="Fork the Repository">
    Visit [github.com/pfrankov/obsidian-local-gpt](https://github.com/pfrankov/obsidian-local-gpt) and fork it.
  </Step>

  <Step title="Choose a Language">
    To improve an existing translation, edit `src/i18n/[code].json`.

    To add a new language:

    1. Copy `src/i18n/en.json` to `src/i18n/[code].json`
    2. Add the import in `src/i18n/index.ts`:

    ```typescript theme={null}
    import [code] from "./[code].json";
    ```

    3. Add to the locales object:

    ```typescript theme={null}
    const locales: { [key: string]: any } = {
      // ...
      [code],
    };
    ```
  </Step>

  <Step title="Translate Strings">
    Translate all string values in the JSON file. Keep:

    * JSON structure identical
    * Placeholder variables like `{{message}}` unchanged
    * Emoji prefixes (💡, 🎨, 🚀) if they add meaning
  </Step>

  <Step title="Test Your Translation">
    1. Build the plugin: `npm run build`
    2. Change Obsidian's language to your locale
    3. Verify all UI strings appear correctly
  </Step>

  <Step title="Submit a Pull Request">
    Create a PR with:

    * Clear title: "Add \[Language] translation" or "Improve \[Language] translation"
    * Description of what was changed
    * Mention if you're a native speaker
  </Step>
</Steps>

<Tip>
  When translating, prioritize:

  * **Accuracy**: Match the original meaning
  * **Brevity**: UI space is limited
  * **Natural phrasing**: Use how native speakers would say it
  * **Consistency**: Use the same terms throughout
</Tip>

## Translation Guidelines

<AccordionGroup>
  <Accordion title="Keep Placeholders Intact">
    Placeholders like `{{message}}`, `{{name}}`, `{{percent}}` must remain unchanged:

    ✅ **Correct:**

    ```json theme={null}
    "errorGenerating": "Fehler beim Generieren: {{message}}"
    ```

    ❌ **Incorrect:**

    ```json theme={null}
    "errorGenerating": "Fehler beim Generieren: {{nachricht}}"
    ```
  </Accordion>

  <Accordion title="Preserve JSON Structure">
    Do not change key names, only values:

    ✅ **Correct:**

    ```json theme={null}
    {
      "commands": {
        "showContextMenu": "Menú contextual"
      }
    }
    ```

    ❌ **Incorrect:**

    ```json theme={null}
    {
      "comandos": {
        "mostrarMenuContextual": "Menú contextual"
      }
    }
    ```
  </Accordion>

  <Accordion title="Handle Emojis Thoughtfully">
    Emojis can be kept, adapted, or removed based on cultural appropriateness:

    **Option 1 - Keep:**

    ```json theme={null}
    "creativityLow": "💡 Niedrig"
    ```

    **Option 2 - Adapt:**

    ```json theme={null}
    "creativityLow": "🔆 Niedrig"
    ```

    **Option 3 - Remove:**

    ```json theme={null}
    "creativityLow": "Niedrig"
    ```
  </Accordion>

  <Accordion title="Test Edge Cases">
    Verify your translations work in:

    * **Long text**: Does it fit in the UI?
    * **Short text**: Is it still clear?
    * **With placeholders**: Does the sentence flow naturally?

    Example:

    ```json theme={null}
    "actionRewritten": "Rewritten \"{{name}}\" action"
    ```

    Should work with both short names ("Fix") and long names ("Summarize this document in detail").
  </Accordion>
</AccordionGroup>

## Fallback Behavior

If a translation key is missing:

1. The system logs a warning: `Translation missing: [key]`
2. Falls back to English (`en`)
3. If English is also missing, returns the raw key

```typescript theme={null}
if (translations?.[k] === undefined) {
  logger.warn(`Translation missing: ${key}`);
  translations = locales["en"];
  // ... attempt to load from English
}
```

<Warning>
  Missing translations won't crash the plugin, but users will see English text instead.
</Warning>

## Community Actions Localization

Community actions can be filtered by language in the settings:

* **Setting**: `settings.communityActionsLanguage`
* **Default**: Matches Obsidian's active language
* **Purpose**: Shows community-contributed actions in your language

This allows users to discover actions written in their preferred language for better prompt clarity.

## Source Code References

<CardGroup cols={2}>
  <Card title="i18n System" icon="language">
    `src/i18n/index.ts` - Translation loader and interpolation
  </Card>

  <Card title="Language Detection" icon="magnifying-glass">
    `src/languageDetection.ts` - Content language detection
  </Card>

  <Card title="Translation Files" icon="folder">
    `src/i18n/*.json` - All language files
  </Card>

  <Card title="English (Reference)" icon="file">
    `src/i18n/en.json` - Base translation file
  </Card>
</CardGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Contributing Guide" icon="code-pull-request" href="https://github.com/pfrankov/obsidian-local-gpt/blob/master/CONTRIBUTING.md">
    Learn how to contribute to the project
  </Card>

  <Card title="Troubleshooting" icon="wrench" href="/advanced/troubleshooting">
    Debug language detection and display issues
  </Card>
</CardGroup>
