Website: unitygametranslator.asymptomatikgames.com
A universal translation mod for Unity games with local AI (Ollama) and online community translations.
- Runtime translation - text is translated as you encounter it in-game
- Local AI translation via Ollama (no internet required, no API costs)
- Instant cache hits - cached translations apply synchronously
- Number normalization - "Kill 5 enemies" and "Kill 10 enemies" share the same translation
- Auto language detection - detects system language as target
- Cross-platform - works on Windows, macOS, Linux
- Community translations - download translations from the community website
- Automatic game detection - detects game via Steam ID or product name
- Update notifications - get notified when translations are updated
- Mod update checker - get notified when a new mod version is available on GitHub
- Upload your work - share translations with the community
- 3-way merge - intelligently merge updates while keeping your local changes
- Device Flow login - secure authentication without entering passwords in-game
- Settings hotkey - press F10 (configurable) to open settings
- First-run wizard - guided setup on first launch
- Ollama configuration - test connection, select model, set game context
- Sync options - configure update checking and merge behavior
- Translation info - view current translation source and local changes
- Login/Upload - authenticate and upload translations without leaving the game
Note: Only text displayed during gameplay is translated. Play through the game to build the translation cache.
| Mod Loader | Unity Type | Download |
|---|---|---|
| BepInEx 5 | Mono | GitHub |
| BepInEx 6 | Mono or IL2CPP | Bleeding Edge |
| MelonLoader | Mono or IL2CPP | GitHub |
BepInEx 6 is in beta but supports both Mono and IL2CPP games. Use the version matching your game type.
Cross-platform: UnityGameTranslator DLLs are .NET assemblies that work on Windows, macOS, and Linux. The same release package works on all platforms. Install the mod loader version matching your OS and architecture, then use the same UnityGameTranslator plugin.
How to know your game type:
GameAssembly.dllin game folder → IL2CPP<Game>_Data/Managed/Assembly-CSharp.dll→ Mono
First run: Launch the game once with the mod loader installed, then quit. This creates the required folder structure for plugins.
Download the release matching your mod loader and extract to:
| Mod Loader | Extract to |
|---|---|
| BepInEx | <Game>/BepInEx/plugins/UnityGameTranslator/ |
| MelonLoader | <Game>/Mods/ |
The zip contains:
UnityGameTranslator.dll- main pluginUnityGameTranslator.Core.dll- translation engineUniverseLib.*.dll- UI framework (variant depends on mod loader)Newtonsoft.Json.dll- JSON library- (BepInEx 5 only)
System.Buffers.dll,System.Memory.dll, etc. - .NET Standard polyfills
On first launch, the mod displays a setup wizard:
- Welcome screen - introduction to the mod
- Online mode - choose to enable community features or stay offline
- Settings hotkey - pick a key to open settings (default: F10)
- Translation search - if online, search for existing translations
- Ollama setup - configure local AI translation (optional)
After setup, press the hotkey anytime to open settings.
By default, the plugin only uses cached/downloaded translations. To enable live AI translation:
- Install Ollama: https://ollama.ai
- Download a model:
ollama pull qwen3:8b - Open settings (F10) and enable Ollama, or edit
config.json:"enable_ollama": true
Recommended model:
qwen3:8bis the tested and optimized model (requires ~6-8 GB VRAM). It provides the best balance of speed, quality, and multilingual support. Other models may work but are experimental.
Config file location:
- BepInEx:
<Game>/BepInEx/plugins/UnityGameTranslator/config.json - MelonLoader:
<Game>/UserData/UnityGameTranslator/config.json
{
"ollama_url": "http://localhost:11434",
"model": "qwen3:8b",
"target_language": "auto",
"source_language": "auto",
"game_context": "",
"enable_ollama": false,
"normalize_numbers": true,
"preload_model": true,
"debug_ollama": false,
"settings_hotkey": "F10",
"first_run_completed": true,
"online_mode": true,
"api_token": null,
"api_user": null,
"sync": {
"check_update_on_start": true,
"auto_download": false,
"notify_updates": true,
"check_mod_updates": true,
"merge_strategy": "ask",
"ignored_uuids": []
}
}| Option | Description |
|---|---|
target_language |
Target language ("auto" = system language, or "French", "German", etc.) |
source_language |
Source language ("auto" = let AI detect) |
game_context |
Game description for better translations (e.g., "Medieval fantasy RPG") |
enable_ollama |
true to enable live AI translation |
model |
Ollama model (qwen3:8b recommended, other models are experimental) |
normalize_numbers |
true to replace numbers with placeholders for better cache reuse |
debug_ollama |
true to log detailed Ollama requests/responses |
| Option | Description |
|---|---|
settings_hotkey |
Key to open settings overlay (default: F10) |
first_run_completed |
true after completing the setup wizard |
online_mode |
true to enable community features (sync, upload) |
| Option | Description |
|---|---|
check_update_on_start |
Check for translation updates when game starts |
auto_download |
Automatically download updates (if no conflicts) |
notify_updates |
Show notification when updates are available |
check_mod_updates |
Check for new mod versions on GitHub at startup |
merge_strategy |
How to handle updates: "ask", "merge", or "replace" |
ignored_uuids |
List of translation UUIDs to ignore updates for |
| Option | Description |
|---|---|
api_token |
API token for authenticated actions (set via login flow) |
api_user |
Username of logged-in user |
- Press F10 to open settings
- Click "Search translations" or enable "Check updates on start"
- The mod searches for translations matching your game and language
- Select a translation to download
- Press F10 to open settings
- Click "Login" to authenticate via the website
- Enter the displayed code at the website
- Once logged in, click "Upload" to share your translation
UnityGameTranslator uses a Main/Branch model for collaborative translation:
| Term | Description |
|---|---|
| Main | The original translation. First uploader becomes the Main owner. |
| Branch | A contributor's version, linked to the Main. Each contributor has one Branch per UUID. |
| Fork | The action of copying a translation to create your own Branch. |
| Role | Description |
|---|---|
| Main owner | You created this translation. You can update it and merge contributions from Branches. |
| Branch contributor | You downloaded a translation, improved it, and uploaded your changes as a Branch. |
| None | You haven't uploaded yet. Your first upload will create a Main or Branch. |
- First upload → Your translation becomes the Main for that UUID
- Download + modify + upload → You fork the translation, creating your Branch
- Main owner can view all Branches on the website and merge contributions
- Languages are locked after first upload - source/target cannot be changed
| Situation | Result |
|---|---|
| UUID doesn't exist on server | Creates new Main translation |
| UUID exists, you're the Main owner | Updates your Main translation |
| UUID exists, owned by someone else | Forks it → creates your Branch |
- Your role is shown in the main panel: "Main translation" or "Branch of @username"
- Branch count is displayed if you're the Main owner
- Languages become read-only in Options after your first upload
When a translation you downloaded has updates:
- Merge - keeps your local changes + adds new entries from remote
- Replace - overwrites everything with the new version
- Ignore - keep your version, don't ask again for this translation
The mod uses 3-way merge logic to intelligently combine changes.
Each translation entry has a quality tag indicating how it was created:
| Tag | Name | Description | Score Weight |
|---|---|---|---|
| H | Human | Manually written by a human | 3 points |
| V | Validated | AI translation reviewed and approved by human | 2 points |
| A | AI | Automatically translated by Ollama | 1 point |
Note: Entries with tag
Hbut empty value are displayed as "C" (Capture) in stats and count as 0 points until translated.
Additional tags (excluded from quality score):
| Tag | Name | Description |
|---|---|---|
| S | Skip | Text intentionally not translated (e.g., alien language, Klingon, foreign text meant to stay foreign). AI decides when to skip. Experimental. |
| M | Mod | Mod UI translations (settings panel, buttons). Optional, internal use. |
The quality score is calculated from the H/V/A distribution:
Score = (H×3 + V×2 + A×1) / (H + V + A)
| Score | Label | Meaning |
|---|---|---|
| 2.5 - 3.0 | Excellent | Mostly human translations |
| 2.0 - 2.5 | Good | Mix of human and validated |
| 1.5 - 2.0 | Fair | Balanced mix |
| 1.0 - 1.5 | Basic | Mostly AI with some review |
| 0.0 - 1.0 | Raw AI | Unreviewed AI translations |
- Capture mode: Text saved with empty value, tag
H(shows asCin stats until translated) - AI translation: Ollama translates → tag
A - Manual edit: User edits a translation in-game or on website → tag
H - Validation: User approves AI translation on website → tag
V
For translators who want full control without AI:
- Open Settings (F10) → enable "Capture keys only"
- Play through the game - all text is captured but NOT translated
- Upload the captured file to the website
- Edit translations manually on the website → all entries become
H(Human) - Result: 100% human translation with Excellent quality score
This workflow is ideal for:
- Professional translators who don't want AI interference
- Languages not well supported by AI
- Games requiring specific terminology or style
Translation owners can edit their translations directly on the website:
- Edit any entry → changes tag to
H(Human) - Validate AI entries → changes tag to
V(Validated) - Changes sync back to the mod on next download/update check
- Translation list shows:
H:150 V:50 A:300 (Fair) - Status card shows visual H/V/A bar with colors
- Quality score displayed as
1.8/3 (Fair)
Translation caches are stored in translations.json in the plugin folder:
- BepInEx:
<Game>/BepInEx/plugins/UnityGameTranslator/translations.json - MelonLoader:
<Game>/UserData/UnityGameTranslator/translations.json
Each file contains metadata for tracking:
{
"_uuid": "unique-file-id",
"_game": { "name": "Game Name", "steam_id": "12345" },
"_source": { "site_id": 123, "uploader": "user", "hash": "sha256:..." },
"_local_changes": 42,
"Hello": "Bonjour",
"Play": "Jouer"
}- .NET SDK 6.0+
Create extlibs/ folder with required DLLs:
extlibs/
├── Unity/
│ ├── UnityEngine.dll
│ ├── UnityEngine.CoreModule.dll
│ ├── UnityEngine.UI.dll
│ ├── UnityEngine.IMGUIModule.dll
│ ├── UnityEngine.TextRenderingModule.dll
│ └── Unity.TextMeshPro.dll
├── UniverseLib/
│ └── UniverseLib.Mono.dll # Compile-time reference for Core
├── BepInEx5/
│ ├── BepInEx.dll
│ ├── 0Harmony.dll
│ └── UniverseLib.Mono.dll
├── BepInEx6-Mono/
│ ├── BepInEx.Core.dll
│ ├── BepInEx.Unity.Mono.dll
│ ├── 0Harmony.dll
│ └── UniverseLib.Mono.dll
├── BepInEx6-IL2CPP/
│ ├── BepInEx.Core.dll
│ ├── BepInEx.Unity.IL2CPP.dll
│ ├── Il2CppInterop.Runtime.dll
│ ├── 0Harmony.dll
│ └── UniverseLib.BIE.IL2CPP.Interop.dll
├── MelonLoader-Mono/
│ ├── MelonLoader.dll
│ ├── 0Harmony.dll
│ └── UniverseLib.Mono.dll
└── MelonLoader-IL2CPP/
├── MelonLoader.dll
├── 0Harmony.dll
├── Il2CppInterop.Runtime.dll
└── UniverseLib.ML.IL2CPP.Interop.dll
UniverseLib: Build from the
UniverseLib/submodule or download pre-built DLLs from the yukieiji fork releases.
Sources:
- BepInEx 5: Releases →
BepInEx/core/ - BepInEx 6: Bleeding Edge →
BepInEx/core/ - MelonLoader: Releases →
MelonLoader/net6/ - Unity: Any Unity game →
<Game>_Data/Managed/
./prepare-release.ps1This script builds all projects and creates release zips in releases/.
Or build individually:
dotnet build UnityGameTranslator-BepInEx5/UnityGameTranslator.BepInEx5.csproj -c Release
dotnet build UnityGameTranslator-BepInEx6-Mono/UnityGameTranslator.BepInEx6Mono.csproj -c Release
dotnet build UnityGameTranslator-BepInEx6-IL2CPP/UnityGameTranslator.BepInEx6IL2CPP.csproj -c Release
dotnet build UnityGameTranslator-MelonLoader-Mono/UnityGameTranslator.MelonLoaderMono.csproj -c Release
dotnet build UnityGameTranslator-MelonLoader-IL2CPP/UnityGameTranslator.MelonLoaderIL2CPP.csproj -c ReleaseOutput DLLs are in each project's bin/ folder.
Configuration is centralized in Directory.Build.props:
<PropertyGroup>
<Version>0.9.43</Version>
<!-- Change these URLs to use your own instance (AGPL compliance) -->
<ApiBaseUrl>https://unitygametranslator.asymptomatikgames.com/api/v1</ApiBaseUrl>
<WebsiteBaseUrl>https://unitygametranslator.asymptomatikgames.com</WebsiteBaseUrl>
</PropertyGroup>To self-host: Deploy your own website instance, then update ApiBaseUrl and WebsiteBaseUrl before building.
Runtime override (advanced): Users can also override URLs without recompiling by editing config.json:
{
"api_base_url": "https://my-server.com/api/v1",
"website_base_url": "https://my-server.com"
}
⚠️ Security note: Your API token will be sent to the configured server. Only use trusted instances.
UnityGameTranslator/
├── UnityGameTranslator.Core/ # Shared translation engine
│ ├── TranslatorCore.cs # Main logic, config, Ollama API
│ ├── TranslatorPatches.cs # Harmony patches for text
│ ├── TranslatorScanner.cs # Scene scanning for UI
│ ├── UI/ # UniverseLib uGUI overlay system
│ │ ├── TranslatorUIManager.cs # Panel manager, hotkey handling
│ │ ├── UIStyles.cs # Centralized styles and colors
│ │ └── Panels/ # UI panels
│ │ ├── WizardPanel.cs # First-run setup wizard
│ │ ├── MainPanel.cs # Main settings panel
│ │ ├── OptionsPanel.cs # Configuration options
│ │ ├── LoginPanel.cs # Device flow authentication
│ │ ├── UploadPanel.cs # Upload translations
│ │ ├── UploadSetupPanel.cs # Upload configuration (game, languages)
│ │ ├── MergePanel.cs # 3-way merge conflict resolution
│ │ ├── LanguagePanel.cs # Language selection
│ │ ├── ConfirmationPanel.cs # User confirmations
│ │ └── StatusOverlay.cs # Corner notifications (updates, sync)
│ ├── ApiClient.cs # HTTP client for website API
│ ├── GameDetector.cs # Game identification
│ ├── GitHubUpdateChecker.cs # GitHub releases update checker
│ ├── TranslationMerger.cs # 3-way merge logic
│ └── TokenProtection.cs # AES-256 token encryption
├── UniverseLib/ # Git submodule (yukieiji fork)
├── UnityGameTranslator-BepInEx5/ # BepInEx 5 adapter
├── UnityGameTranslator-BepInEx6-Mono/ # BepInEx 6 Mono adapter
├── UnityGameTranslator-BepInEx6-IL2CPP/# BepInEx 6 IL2CPP adapter
├── UnityGameTranslator-MelonLoader-Mono/ # MelonLoader Mono adapter
├── UnityGameTranslator-MelonLoader-IL2CPP/ # MelonLoader IL2CPP adapter
├── extlibs/ # External DLLs (Unity, BepInEx, UniverseLib)
├── releases/ # Build output
└── Directory.Build.props # Shared version + API URLs
UI System: The mod uses UniverseLib (yukieiji fork) for its overlay UI. This provides a unified uGUI-based interface that works on both Mono and IL2CPP Unity games, avoiding IMGUI crashes on IL2CPP.
UnityGameTranslator is built on the shoulders of amazing open-source projects:
- UniverseLib by sinai-dev & yukieiji - UI framework for Unity mods
- BepInEx - Unity plugin framework
- MelonLoader by LavaGang - Universal Unity mod loader
- Harmony by Andreas Pardeike - Runtime method patching
- Newtonsoft.Json by James Newton-King - JSON framework
- Ollama - Local AI inference engine
Special thanks to the Unity modding community for documentation, tutorials, and support.
See THIRD_PARTY_LICENSES.md for full license details.
This project is dual-licensed:
- Open Source: AGPL-3.0 - Free for open source use
- Commercial: Contact us for proprietary/commercial use
See LICENSING.md for details.