Supervertaler - AI Agent Documentation
This is the single source of truth for AI coding assistants working on this project. Last Updated: February 1, 2026 | Version: v1.9.191
⚡ QUICK START FOR AI AGENTS
IMPORTANT: If you're continuing from a previous session or ran out of context:
- Skip to the end of this file - The most recent development context is in the "🔄 Recent Development History" section (search for the latest date)
- Current version: v1.9.191 - UI improvements (status icons, button padding, font sizes)
- Read only what you need - The Project Overview and Architecture sections are reference material; the dated history entries contain the actual working context
Quick Navigation:
- Latest context: See CHANGELOG.md for v1.9.191 UI improvements (near end of file)
- Module list: Search for
## 🔌 Complete Module List - Architecture: Search for
## 🏗️ Architecture Patterns - Common pitfalls: Search for
## ⚠️ Common Pitfalls
🎯 Project Overview
Supervertaler is a professional desktop translation application built with Python and PyQt6. It serves as a companion tool for translators, integrating AI-powered translation with traditional CAT (Computer-Assisted Translation) tool workflows.
| Property | Value |
|---|---|
| Name | Supervertaler |
| Version | v1.9.191 (February 2026) |
| Framework | PyQt6 (Qt for Python) |
| Language | Python 3.10+ |
| Platform | Windows (primary), Linux compatible |
| Repository | https://github.com/michaelbeijer/Supervertaler |
| Website | https://supervertaler.com |
| Main File | Supervertaler.py (~38,000+ lines) |
| Modules | 60+ specialized modules in modules/ directory |
Key Capabilities
- Multi-LLM AI Translation: OpenAI GPT-4, Anthropic Claude, Google Gemini, Local Ollama
- CAT Tool Integration: Trados SDLPPX/SDLRPX, memoQ XLIFF, Phrase/Memsource DOCX, CafeTran DOCX, Déjà Vu X3 RTF
- Translation Memory: Fuzzy matching TM with TMX import/export + Supermemory (ChromaDB vector search)
- Terminology Management: SQLite-based termbases with priority highlighting and automatic extraction
- Document Handling: DOCX, bilingual DOCX, PDF (via OCR), simple TXT, Markdown (MD), Multi-file folder import
- Quality Assurance: Spellcheck, tag validation, consistency checking
- Superlookup: Unified concordance hub with TM, Termbase, Supermemory, MT, and Web Resources
- Batteries Included: Default install includes all major features and dependencies, except heavy optional components (Supermemory + offline Local Whisper)
📦 Installation (Simplified)
Supervertaler uses a batteries-included core install: pip install supervertaler pulls in everything needed for the major features, while keeping heavy optional components out of the default install.
Note: Offline dictation via Local Whisper is optional because it pulls in very large dependencies (PyTorch). The default/recommended voice path uses the OpenAI Whisper API.
Legacy note: older “extras” (e.g. supervertaler[all]) are still accepted for backward compatibility, but they no longer change what gets installed.
Installation Options
| Command | Notes |
|---|---|
pip install supervertaler |
Recommended core install (excludes heavy optional Local Whisper) |
pip install supervertaler[local-whisper] |
Adds offline Local Whisper (heavy; pulls PyTorch) |
pip install supervertaler[all] |
Legacy alias (no-op; kept for compatibility) |
Feature Modules
| Module | Included by default | Size | Description |
|---|---|---|---|
| Supervoice | ✅ | ~150 MB | Voice dictation & commands (OpenAI Whisper API recommended) |
| Web Browser | ✅ | ~100 MB | Built-in browser for Superlookup |
| PDF Rescue | ✅ | ~30 MB | PDF text extraction/OCR |
| MT Providers | ✅ | ~30 MB | DeepL, Amazon Translate |
| Hunspell | ✅ | ~20 MB | Advanced spellcheck |
| AutoFingers | ✅ (Windows) | ~10 MB | Windows automation |
Settings → Features Tab
Users can enable/disable features in Settings → 📦 Features.
Feature Manager Module
The modules/feature_manager.py provides:
FeatureManagerclass for checking feature availabilityFEATURE_MODULESdict defining all optional featureslazy_import_*()functions for conditional importscheck_feature(id)quick availability check
🪟 Windows EXE Releases (CORE + FULL)
Supervertaler Windows releases are published as two separate ZIP assets on the same GitHub Release:
- CORE (recommended for most users)
- Smaller download
- Does not bundle the heavy ML stack (Supermemory + offline Local Whisper)
- FULL ("batteries included")
- Larger download
- Bundles Supermemory + offline Local Whisper (PyTorch / sentence-transformers / ChromaDB)
Key Rule (PyInstaller one-folder builds)
The EXE must be run from the extracted distribution folder. Do not separate Supervertaler.exe from _internal/.
If users see an error like missing python312.dll, they are almost always:
- running the wrong EXE (from an intermediate build folder), or
- moving the EXE away from
_internal/.
How to Build (recommended)
Use the automated build script:
# Build BOTH core + full and create both ZIP assets
powershell -NoProfile -ExecutionPolicy Bypass -File .\build_windows_release.ps1
# Build only core
powershell -NoProfile -ExecutionPolicy Bypass -File .\build_windows_release.ps1 -CoreOnly
# Build only full
powershell -NoProfile -ExecutionPolicy Bypass -File .\build_windows_release.ps1 -FullOnly
# Clean build venvs + rebuild (keeps dist/ so multi-flavor builds can coexist)
powershell -NoProfile -ExecutionPolicy Bypass -File .\build_windows_release.ps1 -Clean
What it does:
- Uses two isolated build environments:
.venv-build-coreand.venv-build-full - Runs PyInstaller with the corresponding spec:
Supervertaler.core.spec→dist\Supervertaler-core\...Supervertaler.full.spec→dist\Supervertaler-full\...
- Zips each output using
create_release_zip.pyand writes aREADME_FIRST.txtinto each dist folder.
Output Files
After a successful run, you should have:
dist\Supervertaler-v<version>-Windows-CORE.zipdist\Supervertaler-v<version>-Windows-FULL.zip
GitHub Release Posting
Attach both ZIP files to the same GitHub Release tag.
VS Code Tasks
There are build tasks wired up in .vscode/tasks.json:
- "Build Windows EXE (core)"
- "Build Windows EXE (full)"
- "Build Windows EXE (core + full)"
📁 Project Structure
Supervertaler/
├── Supervertaler.py # Main application (~38,000+ lines)
├── modules/ # 60+ specialized modules
│ ├── feature_manager.py # Modular feature management (NEW)
│ ├── llm_clients.py # OpenAI, Anthropic, Google Gemini, Ollama
│ ├── translation_memory.py # TM matching and storage
│ ├── termbase_manager.py # Terminology management
│ ├── docx_handler.py # DOCX import/export
│ ├── sdlppx_handler.py # Trados Studio packages
│ ├── phrase_docx_handler.py# Phrase/Memsource bilingual
│ ├── cafetran_docx_handler.py # CafeTran bilingual
│ ├── supermemory.py # Vector-indexed semantic TM (ChromaDB)
│ ├── spellcheck_manager.py # Spellcheck with pyspellchecker/Hunspell
│ ├── prompt_library.py # AI prompt management
│ └── ... # See module list below
├── user_data/ # User content (gitignored)
│ ├── prompts/ # .svprompt files
│ ├── termbases/ # .db termbase files
│ ├── translation_memories/ # .db TM files
│ ├── dictionaries/ # Custom spellcheck words
│ └── supermemory/ # ChromaDB vector database
├── assets/ # Icons, images
├── docs/ # Documentation site
├── beijerterm/ # 🔗 GIT SUBMODULE - Beijerterm glossary website
├── tests/ # Test files
└── legacy_versions/ # Historical Tkinter version
🔗 Beijerterm Website Submodule (IMPORTANT FOR AI AGENTS)
The beijerterm/ folder is a Git submodule - a separate repository embedded inside Supervertaler.
What is a Submodule?
- It's a pointer to a specific commit in another repository
- Regular
git clonedoes NOT download submodule contents (saves ~15 MB) - The submodule has its own
.gitand tracksmichaelbeijer/beijertermseparately
Two Separate Projects
| Project | Location | Purpose |
|---|---|---|
| Supervertaler | Root folder | PyQt6 translation app |
| Beijerterm | beijerterm/ subfolder |
Static glossary website (beijerterm.com) |
Note: The "Superlookup" name refers to the in-app lookup panel inside Supervertaler - don't confuse it with the Beijerterm website!
Working with the Submodule
To make changes to Beijerterm website:
cd beijerterm/
# Edit files...
git add .
git commit -m "your message"
git push origin main # Pushes to michaelbeijer/beijerterm
Then update the parent reference:
cd .. # Back to Supervertaler root
git add beijerterm # Stage the new submodule commit pointer
git commit -m "chore: Update beijerterm submodule"
git push origin main # Pushes to michaelbeijer/Supervertaler
⚠️ Common Pitfalls
Commits in submodule aren't automatically tracked - After committing inside
beijerterm/, you must also commit in the parent repo to update the pointer.Changelogs are separate - Beijerterm website changes go in
beijerterm/CHANGELOG.md, Supervertaler changes go inCHANGELOG.mdat root.Features in the wrong repo - The "Superlookup" panel inside Supervertaler.py is part of Supervertaler, not the Beijerterm website. Don't confuse them!
Building the website - Run
python scripts/build_site.pyfrom insidebeijerterm/, not from root.
🔧 Key Technical Details
Main Application (Supervertaler.py)
The main file is a large monolithic PyQt6 application. Key sections:
| Line Range | Purpose |
|---|---|
| 1-700 | Imports, constants, Project dataclass |
| 700-2000 | Custom widgets (grid editors, checkboxes) |
| 2000-4500 | MainWindow initialization, UI setup |
| 4500-8000 | Menu actions, file operations |
| 8000-12000 | Settings dialogs |
| 12000-18000 | Grid operations, navigation |
| 18000-25000 | Import/Export handlers |
| 25000-32000 | AI translation, batch operations |
Key Classes
@dataclass
class Project:
segments: List[Segment]
source_lang: str
target_lang: str
original_docx_path: Optional[str] = None
memoq_source_path: Optional[str] = None
sdlppx_source_path: Optional[str] = None
phrase_source_path: Optional[str] = None
original_txt_path: Optional[str] = None
# ... 20+ fields total
@dataclass
class Segment:
source: str
target: str = ""
status: str = "Not Started"
notes: str = ""
segment_type: str = "text"
# ... additional fields
File Extensions
| Extension | Purpose |
|---|---|
.svproj |
Supervertaler project files (JSON) |
.svprompt |
Prompt files (JSON) |
.svntl |
Non-translatables lists (JSON) |
🔌 Complete Module List
AI & LLM (modules/)
llm_clients.py- OpenAI, Anthropic Claude, Google Gemini, Ollama integrationmodel_version_checker.py- Auto-detect new LLM models from providersmodel_update_dialog.py- UI for selecting new modelsprompt_library.py- Prompt management and favoritesprompt_assistant.py- AI-powered prompt generationunified_prompt_library.py- Unified prompt systemunified_prompt_manager_qt.py- Prompt manager UIvoice_dictation.py- Whisper-based voice inputvoice_commands.py- Talon-style voice command system (NEW)ai_actions.py- AI action system for prompt libraryai_attachment_manager.py- File attachment persistenceai_file_viewer_dialog.py- File viewing dialog
Translation Memory & Terminology
translation_memory.py- Fuzzy matching TM systemsupermemory.py- ChromaDB vector semantic search (2100+ lines)termbase_manager.py- SQLite-based terminologyterm_extractor.py- Automatic term extractiontermbase_entry_editor.py- Term editing UItermbase_import_export.py- TMX/TBX import/exporttm_manager_qt.py- TM management UItm_metadata_manager.py- TM metadata handlingtm_editor_dialog.py- TM editing dialogtmx_editor.py/tmx_editor_qt.py- TMX file editingtmx_generator.py- TMX file generation
File Handlers
docx_handler.py- Standard DOCX import/exportsdlppx_handler.py- Trados Studio SDLPPX/SDLRPX packages (767+ lines)phrase_docx_handler.py- Phrase/Memsource bilingual DOCXcafetran_docx_handler.py- CafeTran bilingual DOCXtrados_docx_handler.py- Trados bilingual review DOCXdejavurtf_handler.py- Déjà Vu X3 bilingual RTF (NEW in v1.9.91)mqxliff_handler.py- memoQ XLIFF filessimple_segmenter.py- Text segmentation
Spellcheck & QA
spellcheck_manager.py- Dual-backend spellcheck (pyspellchecker + Hunspell)non_translatables_manager.py- Non-translatable term managementtag_cleaner.py- CAT tool tag removaltag_manager.py- Tag handling
UI Components
ribbon_widget.py- Ribbon-style toolbartranslation_results_panel.py- Match display paneltermview_widget.py- Inline term displaysuperlookup.py- Unified lookup windowsuperbrowser.py- Multi-chat AI browserquick_access_sidebar.py- Quick access panelkeyboard_shortcuts_widget.py- Shortcut managementproject_home_panel.py- Project home UI
Utilities
database_manager.py- SQLite database operationsdatabase_migrations.py- Database schema migrationsconfig_manager.py- Settings managementfile_dialog_helper.py- File dialog utilitiesfind_replace.py- Find and replace functionalityshortcut_manager.py- Keyboard shortcut handlingtheme_manager.py- UI theme managementstatuses.py- Segment status definitions
Specialized Tools
pdf_rescue_Qt.py- AI OCR for PDF extractionimage_extractor.py- Extract images from DOCXfigure_context_manager.py- Image context for AIdocument_analyzer.py- Document analysisencoding_repair.py/encoding_repair_Qt.py- Fix encoding issuesautofingers_engine.py- memoQ AutoFingers automationtracked_changes.py- Track changes analysissupercleaner.py/supercleaner_ui.py- Text cleaning
Benchmarking
llm_leaderboard.py- LLM quality benchmarkingsuperbench_ui.py- Benchmark UIlocal_llm_setup.py- Ollama setup wizard
🏗️ Architecture Patterns
UI Pattern
- PyQt6 with custom styled widgets
- Consistent styling:
- Checkboxes:
CheckmarkCheckBox(Standard),PinkCheckmarkCheckBox(Project),BlueCheckmarkCheckBox(Global) - Radio Buttons:
CheckmarkRadioButton(Standard Green)
- Checkboxes:
- Tag-based text formatting (
<b>,<i>,<u>,<li-o>,<li-b>) - Grid-based segment editor with source (read-only) and target (editable) columns
Data Flow
- Import file → Parse to segments → Display in grid
- User translates/edits → Status updates → Grid refreshes
- Export → Reconstruct original format with translations
Settings Storage
user_data/general_settings.json- App preferencesuser_data/ui_preferences.json- Window geometry, button states.svprojfiles - Per-project settings
📝 Development Guidelines
When Editing Supervertaler.py
- The file is large (~32K lines) - use line ranges when reading
- Search for method names with
grep_searchbefore editing - Follow existing patterns for new features
- Update
__version__at the top when making changes
When Adding New Modules
- Create in
modules/directory - Add import in main file where needed
- Follow existing module patterns (docstrings, type hints)
Documentation Updates
Always update these files after changes:
AGENTS.md- Add dated entry to development historyCHANGELOG.md- Add version entryREADME.md- Update version badge if needed
Commit Messages
Use semantic prefixes:
feat:- New featurefix:- Bug fixdocs:- Documentationrefactor:- Code restructuringstyle:- Formatting
⚠️ Common Pitfalls
ElementTree namespaces - Always use namespace dict when working with SDLXLIFF:
NAMESPACES = {'sdl': 'http://sdl.com/FileTypes/SdlXliff/1.0'} element.find('.//sdl:seg', NAMESPACES)Grid widget access - Use
table.cellWidget()for QTextEdit,table.item()for QTableWidgetItemFile paths - Store absolute paths, use
os.path.exists()before accessingStatus updates - Remember to update both internal data and grid display
Signal blocking - When setting text programmatically, use
blockSignals(True/False)to prevent cascading eventsQt event queue - Be aware that
setPlainText()queues events even when signals are blockedHidden widget styling - Qt may not apply stylesheets to hidden widgets. If theme colors aren't appearing, apply styles when the widget becomes visible, not just at creation time
Race conditions & timing - When debugging UI issues, consider whether the problem might be timing-related:
- Widgets created before theme manager is initialized
- Styles applied while widgets are hidden
- Signals firing before handlers are connected
- Use
QTimer.singleShot()for deferred initialization when needed
📋 Planned Features & Refactoring
🔧 Configuration File Consolidation (PRIORITY - Scheduled)
Identified: January 9, 2026
Status: Documented, not yet implemented
Complexity: Medium (30-40 file edits + migration script)
Current Problem: Configuration File Sprawl
Settings are currently scattered across multiple JSON files in user_data/:
general_settings.json- General application preferencesui_preferences.json- Window geometry, button states (DEPRECATED, migrated to general_settings.json)themes.json- Theme definitionsrecent_projects.json- Recent project listfeature_settings.json- Optional feature togglesfind_replace_history.json- Find & Replace historysuperlookup_history.json- Superlookup search historyvoice_commands.json- Voice command library- Plus module-specific configs...
Issues:
- Scattered settings - Hard to find where a setting is stored
- Code complexity - Multiple file read/write operations throughout codebase
- Inconsistent structure - Each file has different patterns (nested vs flat, etc.)
- Migration headaches - Changing structure requires updating multiple files
- User confusion - Manual editing requires knowing which file to look in
- Backup/restore complexity - Must backup multiple files to preserve all settings
Proposed Solution: Single config.json
Consolidate all settings into one well-structured file:
{
"config_version": "1.0.0",
"general": {
"restore_last_project": false,
"auto_propagate_exact_matches": true,
"auto_center_active_segment": true,
"auto_insert_100_percent_matches": true,
"auto_confirm_100_percent_matches": false,
"tm_save_mode": "latest",
"enable_smart_word_selection": true,
"enable_auto_backup": true,
"backup_interval_minutes": 5
},
"ui": {
"theme": "light",
"window_geometry": {
"x": 100,
"y": 100,
"width": 1200,
"height": 800
},
"fonts": {
"grid_family": "Segoe UI",
"grid_size": 11,
"results_match_size": 9,
"results_compare_size": 9,
"termview_family": "Segoe UI",
"termview_size": 10,
"termview_bold": false
},
"colors": {
"tag_color": "#7f0001",
"focus_border_color": "#2196F3",
"focus_border_thickness": 2,
"badge_text_color": "#333333",
"invisible_char_color": "#999999",
"even_row_color": "#FFFFFF",
"odd_row_color": "#F0F0F0"
},
"layout": {
"tabs_above_grid": false,
"enable_alternating_row_colors": true,
"show_invisibles": false
}
},
"features": {
"supermemory_enabled": true,
"supermemory_auto_init": false,
"voice_enabled": false,
"web_browser_enabled": true,
"pdf_rescue_enabled": true,
"autofingers_enabled": false
},
"match_limits": {
"LLM": 3,
"MT": 5,
"TM": 10,
"Termbases": 10
},
"termbase": {
"enable_grid_highlighting": true,
"highlight_style": "semibold",
"display_order": "appearance",
"hide_shorter_matches": false,
"dotted_color": "#808080"
},
"precision_scroll": {
"divisor": 3
},
"recent_projects": [
"/path/to/project1.svproj",
"/path/to/project2.svproj",
"/path/to/project3.svproj"
],
"custom_themes": [
{
"name": "Dark Blue",
"is_dark": true,
"colors": {
"background": "#1e1e1e",
"foreground": "#d4d4d4",
...
}
}
],
"history": {
"find_replace": [
{"find": "example", "replace": "sample"}
],
"superlookup_searches": [
"translation memory",
"terminology"
]
},
"voice_commands": {
"enabled": false,
"recognition_engine": "openai_whisper",
"custom_commands": [
{
"phrase": "next segment",
"aliases": ["go next", "move forward"],
"action_type": "internal",
"action": "next_segment"
}
]
},
"ollama": {
"keepwarm": false
},
"autohotkey": {
"path": "C:\\Program Files\\AutoHotkey\\v2\\AutoHotkey64.exe"
}
}
Benefits:
- ✅ Single source of truth - All settings in one place
- ✅ Clear hierarchy - Logical grouping by functionality
- ✅ Easy to read/edit - Clear structure for manual editing
- ✅ Atomic saves - All settings updated together (no partial updates)
- ✅ Simple backup/restore - One file to backup
- ✅ Version tracking -
config_versionfield for migrations - ✅ Better defaults - Easy to see all default values at once
Implementation Plan:
Create
modules/config_manager_v2.py(new unified config manager):ConfigManagerclass with section accessorsget(section, key, default)methodset(section, key, value)methodsave()method (atomic write)load()method with validation
Migration script (
scripts/migrate_config.py):- Read all existing JSON files
- Map to new structure
- Write
config.json - Backup old files to
user_data/config_backup/ - Run automatically on first startup after update
Update all load/save calls (~30-40 locations):
- Replace
_load_general_settings_from_file()→config_manager.get('general', key) - Replace
save_general_settings()→config_manager.set('general', key, value)+config_manager.save() - Update theme manager
- Update recent projects
- Update find/replace history
- Update voice command loader
- Replace
Backward compatibility:
- Keep old loaders as fallback for 1-2 versions
- Log migration warnings
- Auto-migrate on first run
Testing checklist:
- Fresh install (no config files)
- Migration from old files
- Settings persist correctly
- All features still work
- No performance regression
Files to modify:
Supervertaler.py- Replace all config load/save callsmodules/config_manager_v2.py- NEW unified config managermodules/theme_manager.py- Use new config managermodules/voice_commands.py- Use new config managermodules/find_replace_qt.py- Use new config managerscripts/migrate_config.py- NEW migration script
Estimated effort: 3-4 hours (careful testing needed)
Priority: High (improves maintainability significantly)
� Future Investigation: TMX Tag Export Format
Issue discovered December 22, 2025: Our TMX Editor stores formatting tags (like <b>, <i>) as escaped text (<b>) in the <seg> element. This is valid XML but may not be the optimal approach.
Three approaches exist:
| Approach | Example in TMX file | Pros | Cons |
|---|---|---|---|
| Escaped text | <seg><b>text</b></seg> |
Simple, valid XML | Tags treated as plain text, lost semantic meaning |
| TMX inline elements | <seg><bpt i="1" type="bold"><b></bpt>text<ept i="1"></b></ept></seg> |
TMX 1.4 compliant, preserves tag semantics | More complex to implement |
| Raw XML (invalid) | <seg><b>text</b></seg> |
Human readable | Invalid XML unless DTD defines <b> |
What other tools do:
- memoQ: Uses TMX inline elements (
<bpt>,<ept>) for proper tag preservation - Trados Studio: Similar, uses inline elements with type attributes
- OmegaT: Generally uses escaped text for simplicity
- Many web tools: Just escape everything
Recommendation for future: Consider implementing proper TMX inline elements (<bpt>, <ept>, <ph>) when exporting. This would:
- Maintain compatibility with professional CAT tools
- Preserve tag type information (bold, italic, etc.)
- Allow round-tripping without tag loss
Files to modify: modules/tmx_editor.py - TmxParser.save_file() method
�💡 Problem-Solving Tips for AI Agents
When stuck on a difficult bug, consider these approaches:
Think about timing: Is this a race condition? Are things happening in the wrong order?
- Widget creation vs. theme application timing
- Signal connections vs. signal emissions
- Hidden vs. visible widget state changes
Think outside the box: The obvious solution may not work
- If stylesheets aren't applying, try QPalette as an alternative
- If a method isn't being called, check if the widget is even visible
- If changes aren't reflected, check if there's caching involved
Add debug output: When behavior is mysterious, add logging to trace execution flow
- Print method entry/exit with timestamps
- Log parameter values and state
- Write to a debug file if console output is too fast
Question assumptions: What do you THINK is happening vs. what is ACTUALLY happening?
- The code might be running but not having the expected effect
- A different code path might be executing
- Something else might be overriding your changes
🧪 Testing
Running Tests
pytest tests/
Manual Testing Checklist
- Import DOCX, translate segment, export
- Save/load .svproj project
- TM matching works
- Termbase highlighting works
- AI translation (if API keys configured)
- Spellcheck toggles correctly
- SDLPPX import/export round-trip
🔑 API Keys
Unified Loading System with Persistent Storage:
API keys are stored in the persistent user data location (see Installation section).
User Data Locations (v1.9.148+):
| Platform | Default Data Folder | API Keys File |
|---|---|---|
| All Users (default) | ~/Supervertaler/ |
~/Supervertaler/api_keys.txt |
| Windows (default) | C:\Users\Username\Supervertaler\ |
...\Supervertaler\api_keys.txt |
| Development | user_data_private\ (git-ignored) |
user_data_private\api_keys.txt |
Note: Users can choose their own data folder location on first run or via Settings → General → Data Folder Location.
For Developers (running from source):
- Store keys in:
user_data_private/api_keys.txt - This location is fully gitignored and will never be uploaded to GitHub
- All features (translation, AI Assistant, tests) will find keys here
For End Users (pip install):
- On first run, choose where to store your data (default:
~/Supervertaler/) - Store API keys in:
[your-data-folder]/api_keys.txt - The app prints the exact path on startup:
[Data Paths] User data: ... - Keys persist across pip upgrades!
For Windows EXE Users:
- Same as pip users - choose your data folder on first run
- Default is visible in your home folder:
C:\Users\Username\Supervertaler\
Format:
openai=sk-...
claude=sk-ant-...
google=AI...
gemini=AI...
deepl=...
Note: google= and gemini= are aliases - both work identically (v1.9.146+).
Implementation Details:
Supervertaler.py:load_api_keys()method reads from user_data_path- Automatic normalization: if
googleis set,geminiis also populated (and vice versa) - All API key loading now unified through main app's method
🔄 Recent Development History
February 1, 2026 - Dark Mode Refinements & UI Improvements
✨ Feature Summary
Improved dark mode text visibility and fixed TM navigation arrows that were invisible or rendering incorrectly across light and dark themes.
Status: Implementation complete, version 1.9.184 released
Files Modified:
Supervertaler.py- Multiple UI improvements:- TermView source text color: Changed to #FFFFFF in dark mode for better contrast (lines 175, 456)
- HTML tag colors: Light pink (#FFB6C1) in dark mode for
<b>,</b>tags (lines 1403-1413, 2733-2743) - Navigation arrows: Implemented ClickableArrow class with Unicode symbols (◀ ▶) and theme-aware colors (lines 29674-29733)
- Table header font: Reduced from
font_size + 1tofont_sizefor better proportions (line 30834) - Theme refresh: Added arrow color updates in
refresh_theme_colors()(lines 43993-43999)
modules/unified_prompt_manager_qt.py- Fixed Issue #112:- Prompt edits now immediately reflected in Prompt Library and Preview Combined
- Cache refresh for both active primary and attached prompts (lines 2377-2384)
build_windows_release.ps1- Added Start Menu shortcut scripts to release packages (lines 111-116)create_release_zip.py- Added shortcut creation instructions to README (lines 28-31)
Key Code Locations:
ClickableArrow Class (Supervertaler.py:29684-29705):
class ClickableArrow(QLabel):
clicked = pyqtSignal()
def __init__(self, arrow_symbol, parent=None):
self.arrow_symbol = arrow_symbol
super().__init__("", parent)
self.setCursor(Qt.CursorShape.PointingHandCursor)
def set_color(self, color):
"""Update arrow color for current theme"""
self.setStyleSheet(f"""
QLabel {{
color: {color};
background: transparent;
border: none;
font-size: 11px;
font-weight: bold;
}}
""")
self.setText(self.arrow_symbol)
Theme Color Logic:
- Dark mode: White arrows (#FFFFFF), light pink tags (#FFB6C1)
- Light mode: Dark gray arrows (#333333), standard tag colors
Development Notes:
- Initially tried PNG arrow images but they rendered fuzzy
- Attempted Unicode angle brackets (❮ ❯) but font support was inconsistent
- Final solution: Unicode triangle symbols (◀ ▶) render crisply on all systems
- Arrow visibility issues were caused by arrows being created at startup before theme was applied
- Solution: ClickableArrow class with
set_color()method called during theme refresh
PowerShell Scripts Created:
create_start_menu_shortcut.ps1- For end users (Supervertaler.exe)create_dev_start_menu_shortcut.ps1- For developers (run.cmd)
Related Issues:
- Fixed #112: Prompt editing bug where saved prompts weren't updating in UI
January 30-31, 2026 - Total Recall Architecture & Build System Unification
✨ Feature Summary
Implemented CafeTran-inspired "Total Recall" architecture for instant grid navigation. Instead of querying giant TMs on every segment click, relevant segments are extracted into lightweight in-memory structures on project load.
Status: Implementation complete, ready for testing
Files Created:
modules/project_tm.py- In-memory TM for instant lookupsmodules/extract_tm.py- Persistent TM extraction to .svtm files
Files Modified:
Supervertaler.py(~938 lines changed)modules/database_manager.py- Reduced candidate limitbuild_windows_release.ps1- Unified build system
Implementation 1: In-Memory Termbase Index (Quick Win)
On project load, builds a Python dict mapping lowercase_word -> [term_info, ...] for O(1) termbase lookups.
Key code locations in Supervertaler.py:
self.termbase_indexinitialization: ~line 6243_build_termbase_index(): ~line 22502_search_termbase_index(): ~line 22645- Integration (called on project load): ~line 22265
Implementation 2: ProjectTM - In-Memory TM
File: modules/project_tm.py
On project load, extracts relevant TM segments (fuzzy matches ≥75%) into an in-memory SQLite database with FTS5 for fast fuzzy search.
Features:
ProjectTMclass with in-memory SQLite + FTS5extract_from_database()- extracts segments matching project contentsearch()- instant lookup (exact match first, then FTS5 fuzzy)- Thread-safe with locking
Integration in Supervertaler.py:
self.project_tminitialization: ~line 6250- Progress signal:
_project_tm_progress_signalat ~line 6128 - Background extraction:
_start_project_tm_extraction_background()at ~line 7553 - UI indicator in status bar:
self.project_tm_indicatorat ~line 7439
Implementation 3: ExtractTM - Persistent TM Extraction
File: modules/extract_tm.py
Extracts relevant segments from selected TMs into a .svtm file (SQLite) that persists across sessions.
Features:
ExtractTMclass with persistent SQLite storageextract_and_save()- extracts and saves to fileload()- loads existing extractionsearch()- fast lookup with FTS5export_to_tmx()- export to standard TMX format- File saved as
{ProjectName}_Extract.svtmnext to project
Integration in Supervertaler.py:
- Menu action: Bulk → Extract from TMs...
- Dialog:
show_extract_tm_dialog()at ~line 33840
Implementation 4: Database Manager Optimization
File: modules/database_manager.py
Reduced TM candidate limit from 500 to 100 (~line 1016):
# Before
candidate_limit = max(500, max_results * 50)
# After
candidate_limit = max(100, max_results * 10)
Implementation 5: Unified Build System
File: build_windows_release.ps1
Removed CORE/FULL split, now uses single unified Supervertaler.spec:
# New usage
.\build_windows_release.ps1 # Build release
.\build_windows_release.ps1 -Clean # Clean build
# Output
dist\Supervertaler-v{version}-Windows.zip
Expected Performance Improvements
| Metric | Before | After |
|---|---|---|
| Termbase lookup | 20-100ms | <1ms |
| TM lookup (grid) | 50-200ms | <5ms |
| Project load | Fast | Slightly slower (background extraction) |
Testing Checklist
- Open project with TMs - see ProjectTM extraction progress indicator
- Grid navigation feels faster after extraction
- Termbase matches appear instantly
- Bulk → Extract from TMs... dialog works
- .svtm file created next to project
- Build script:
.\build_windows_release.ps1
Bug Fix (January 31, 2026)
Fixed attribute name mismatch: segment classes use source_text, but ProjectTM/ExtractTM were looking for source. Changed to try both:
source = getattr(seg, 'source', None) or getattr(seg, 'source_text', None)
Git Status (Uncommitted)
M Supervertaler.py
M build_windows_release.ps1
M modules/database_manager.py
?? modules/extract_tm.py
?? modules/project_tm.py
Related Documentation
- Design doc:
CLAUDE_SESSION_HANDOFF.md- original architecture design
January 30, 2026 - Global UI Font Scale Feature (v1.9.180)
✨ Feature Summary
A user-configurable setting (50%-200%) that scales the entire application UI. Particularly useful for Linux/macOS users where Qt applications may render with smaller fonts, or for high-DPI displays.
Files Modified:
modules/theme_manager.pySupervertaler.pyCHANGELOG.mdFAQ.md
Implementation Details:
Step 1: ThemeManager (modules/theme_manager.py)
In __init__ method, added after self.custom_themes:
# Global UI font scale (50-200%, default 100%)
self.font_scale: int = 100
In apply_theme method, added at the beginning (after getting theme = self.current_theme):
# Calculate scaled font sizes based on font_scale (default 100%)
base_font_size = int(10 * self.font_scale / 100) # Base: 10pt at 100%
small_font_size = max(7, int(9 * self.font_scale / 100)) # Small text (status bar)
# Font scaling rules (only applied if scale != 100%)
font_rules = ""
if self.font_scale != 100:
font_rules = f"""
/* Global font scaling ({self.font_scale}%) */
QWidget {{ font-size: {base_font_size}pt; }}
QMenuBar {{ font-size: {base_font_size}pt; }}
# ... (all Qt widget types)
"""
Then prepended font_rules to the stylesheet: stylesheet = font_rules + f"""...
Step 2: Supervertaler.py
- Replaced "Settings Panel Font Size" UI (~line 17721) in
_create_view_settings_tab()with "Global UI Font Scale" - Changed SpinBox range from 80-200 to 50-200
- Updated setting key from
settings_ui_font_scaletoglobal_ui_font_scale - Replaced
_apply_settings_ui_font_scale()with_apply_global_ui_font_scale():def _apply_global_ui_font_scale(self, scale_percent: int): """Apply font scale to the entire application UI""" general_settings = self.load_general_settings() general_settings['global_ui_font_scale'] = scale_percent # Remove old key if present (migration) if 'settings_ui_font_scale' in general_settings: del general_settings['settings_ui_font_scale'] self.save_general_settings(general_settings) # Update ThemeManager and reapply theme if hasattr(self, 'theme_manager') and self.theme_manager is not None: self.theme_manager.font_scale = scale_percent self.theme_manager.apply_theme(QApplication.instance()) # Update status bar and main tabs fonts self._update_status_bar_fonts(scale_percent) self._update_main_tabs_fonts(scale_percent) self.log(f"✓ Global UI font scale set to {scale_percent}%") - Added helper methods:
_update_status_bar_fonts(),_update_main_tabs_fonts(),_get_global_ui_font_scale() - Applied font scale at startup after
self.theme_manager = ThemeManager(...):saved_font_scale = self._get_global_ui_font_scale() self.theme_manager.font_scale = saved_font_scale
Settings Storage:
- Key:
global_ui_font_scale(replacessettings_ui_font_scale) - File:
general_settings.json - Default: 100
- Range: 50-200
January 28, 2026 - Fresh Projects Start Clean (v1.9.172)
🐛 Bug Fix: TM/Glossary Deactivation on Project Load
Fixed bug where TMs and glossaries remained activated from previous sessions when loading or creating new projects. Users expected a clean slate but saw resources from previous work.
Root Cause:
In load_project(), TM deactivation only ran if the project had saved activated_tm_ids in its tm_settings. For older projects or newly created projects without tm_settings, deactivation was skipped entirely.
Fix: Now follows the same pattern as glossaries:
- Always deactivate all TMs for the project first (start clean)
- Then restore saved TM activations if they exist in the project file
- *Always
…(truncated)