Adding or Changing a Feature
Use this page when you want to add a new feature to Manga Translator — a new setting, a new translator/OCR/renderer option, a new page, or new UI copy — or modify an existing one. It describes the full path from configuration to UI to runtime consumption. It is not an architecture overview (see Architecture and code boundaries), and it does not expand on test methodology, packaging/release, or HTTP API details (see Tests and code quality, Packaging and release, and the pages under developer/http-api/).
Relevant code
- This guide focuses on how a code change takes effect: config model → settings-page mounting → i18n → persistence → backend consumption → tests and manual verification.
- The detailed module boundaries of the desktop UI, business logic, services, and backend pipeline live in Architecture and code boundaries; this page lists which files a new feature usually touches at each layer.
- Adding API credentials, slots, or rotation strategies is not described here (see the API-management pages); adding prompt files, batch schemes, or rich-text rules is covered by the corresponding feature pages.
- This page contains no real
.env, userconfig.json, API key, token, username, private absolute path, or private prompt; example defaults come only from tracked templates and code.
Development workflow
Adding or changing a feature usually follows the path below. Not every step requires a change: a pure copy change touches only i18n, and a pure backend algorithm change may skip the settings page; but every step below must be checked when adding a user-configurable parameter.
flowchart TD
A["Define the boundary\n(setting / new option / new page / new copy)"] --> B["Config model\ncore/config_models.py or manga_translator/config.py"]
B --> C["Release template\nconfig/config-example.json"]
C --> D["Settings mount\nsettings_tab_layout.json"]
D --> E["Display mapping\napp_logic.py get_display_mapping / get_options_for_key"]
E --> F["i18n copy\nlocales/en_US.json and zh_CN.json"]
F --> G["Persistence\nconfig_service.py deep merge + user-config sync"]
G --> H["Backend consumption\nMangaTranslator or module implementation"]
H --> I["Tests and verification\ntest/ scripts + language switch + import/export"]
- Define the boundary: decide which module the change belongs to —
desktop_qt_ui/(UI and business logic),manga_translator/(pipeline and algorithms),config/(release templates),locales/(copy). - Change the config model: add a field to the matching
AppSettingssubmodel indesktop_qt_ui/core/config_models.pyfor user-configurable desktop settings, and to the matchingConfigsubmodel inmanga_translator/config.pyfor backend runtime configuration. Field names, types, and defaults should stay in sync. - Update the release template: write the new field and its default into
config/config-example.json. The desktop startup priority is userconfig/config.json>config/config-example.json> Qt model defaults (seeconfig_service.py). - Mount the settings page: append the config key to the
itemslist of the matching tab indesktop_qt_ui/ui/main_page/settings_tab_layout.json; tab titles are themselves i18n keys. - Add display mapping: add a
key -> label_*mapping tolabelsindesktop_qt_ui/app_logic.py#get_display_mapping; for dropdowns, also provide options and display names inget_options_for_key/get_display_mapping. - Add i18n copy: add the
label_*label and thedesc_*description tolocales/en_US.jsonandlocales/zh_CN.json(next section).en_USusually uses the English copy itself as the value. - Confirm persistence:
config_service.pydeep-merges and validates each key againstAppSettings;_sync_user_configadds fields that are new in the release template to the user config, removes fields that no longer exist, and preserves user-modified values. - Wire the backend consumer: after
manga_translator/config.pyreads the new field,manga_translator/manga_translator.pyor the relevant module (detection/OCR/translation/inpainting/typesetting/upscaling/colorization) actually consumes it. - Test and verify: write a pytest-style regression script under
test/(first import_bootstrap) and run it withuv run pytest; then manually verify language switching and config import/export.
Adding i18n copy
UI copy goes through the JSON language packs under desktop_qt_ui/locales/. I18nManager.translate(key) returns the key itself when the current pack has no entry (see i18n_service.py), so a new key shows the key string instead of raising an error until it is translated.
Keys come in three common shapes:
- English sentence as key: menus, buttons, and hints use the English copy directly as the key, for example
SettingsorExport Config;en_US.jsonstores the same value as the key andzh_CN.jsonstores the Chinese. label_*: setting names, bound to config keys viaget_display_mapping('labels'), for examplelabel_context_size.desc_*: description-panel text in the formdesc_{full_key}(dots become underscores), for exampledesc_cli_context_size; when missing, the panel shows "No description available."
The language packs are zh_CN, zh_TW, en_US, ja_JP, ko_KR, and es_ES (six in total); the one-time script scripts/add_batch_edit_locale_keys.py demonstrates the batch pattern "add if missing, never touch existing, en_US uses the key itself".
On the wiki side, the i18n evidence catalog doc/wiki/data/i18n.generated.json is generated from the two language packs by doc/wiki/scripts/build-i18n-catalog.mjs (--check detects stale output), and the settings catalog doc/wiki/data/settings.generated.json is generated by doc/wiki/scripts/build-settings-catalog.py from app_logic.py#get_display_mapping, the release template, and the two packs. After editing a language pack, rerun both scripts; never hand-edit the generated JSON.
Constraints and notes
- When adding a user-configurable parameter, the field names/types in
config_models.pyandmanga_translator/config.pymust match, or the value saved by the desktop app may not line up with what the backend reads. - Setting labels come from
get_display_mapping('labels'); if the mapping is missing,dynamic_settings.pyfalls back to showing the raw field name (for examplemin_box_area_ratio) without an error, but the copy is missing. - A missing
desc_*key does not raise an error; the description panel shows "No description available." (Settings Desc No Description), so both languages should be filled in. - A missing i18n key makes
translate()return the key itself: this is invisible inen_US(key equals value) butzh_CNwill show the raw English key, so check after switching languages. - Editing
settings_tab_layout.jsonchanges the visible parameter set and grouping of the settings page; the baseline indoc/wiki/data/settings.generated.jsonis 109 visible fields, so regenerate and recheck after such a change. - Do not modify generated files outside
doc/wiki/data/anddoc/wiki/scripts/, and never read or commit real.env, userconfig.json, keys, tokens, or private absolute paths.
Developer Guide
Option matrix
The following copy is directly relevant to this workflow (key → actual en_US value → actual zh_CN value):
| UI call key | English actual value | Simplified Chinese actual value |
|---|---|---|
Settings | Settings | 设置 |
Settings Page Title | Settings | 参数设置 |
Settings Page Subtitle | Adjust translation pipeline parameters. Changes are saved automatically. | 调整翻译流程的各项参数。修改后将自动保存。 |
Settings Desc Header | Parameter Description | 参数说明 |
Settings Desc Key | Parameter Key: | 参数键: |
Settings Desc No Description | No description available. | 暂无说明。 |
Settings Desc Placeholder | Click any setting on the left to view details | 点击左侧任意设置项查看详细说明 |
Export Config | Export Config | 导出配置 |
Import Config | Import Config | 导入配置 |
General | General | 通用 |
OCR | OCR | 文字识别 |
Detection | Detection | 检测 |
Translation | Translation | 翻译 |
Inpainting | Inpainting | 修复 |
Typesetting | Typesetting | 排版 |
Mode Specific | Mode Specific | 模式相关 |
&Language | &Language | &语言 |
Language: | Language: | 语言: |
Apply | Apply | 应用 |
Save | Save | 保存 |
Cancel | Cancel | 取消 |
OK | OK | 确定 |
label_translator | Translator | 翻译器 |
label_context_size | Context Pages | 上下文页数 |
desc_cli_context_size | Translation context page count for multi-page joint translation. Larger values improve quality but consume more tokens. | 翻译上下文页面数,用于多页联合翻译。值越大翻译质量越好,但 token 消耗越多。 |
label_batch_concurrent | Concurrent Batch Processing | 并发批量处理 |
Code locations
| Layer | File | What was checked |
|---|---|---|
| Config models | desktop_qt_ui/core/config_models.py, manga_translator/config.py | AppSettings / Config submodels and defaults |
| Release template | config/config-example.json | Release defaults and get_default_config_path usage |
| Settings UI | desktop_qt_ui/ui/main_page/settings_tab_layout.json, dynamic_settings.py, pages/settings_page.py | Tab grouping, parameter rows, description panel, language refresh |
| Display mapping | desktop_qt_ui/app_logic.py | get_display_mapping, get_options_for_key, _t |
| i18n | desktop_qt_ui/services/i18n_service.py, locales/en_US.json, zh_CN.json | Six-locale loading, missing-key fallback, key/actual-value triples |
| Persistence | desktop_qt_ui/services/config_service.py | Priority loading, per-key validation, user-config sync |
| Backend consumption | manga_translator/manga_translator.py, manga_translator/translators/__init__.py | Parameters entering the pipeline, translator registration |
| Test conventions | test/README.md, pyproject.toml | import _bootstrap, pytest testpaths / pythonpath |
| Wiki tooling | doc/wiki/scripts/build-i18n-catalog.mjs, build-settings-catalog.py | i18n and settings catalog generation/checks |
