spacr.qt.i18n¶
Runtime localization for the spaCR Qt application.
The application historically embedded English text directly in its widgets. Replacing every call site at once would make localization brittle, so this module provides two complementary layers:
tr()translates text at construction time and always falls back to the original English source string.retranslate_widget_tree()safely updates already-created static Qt labels, buttons, menus, tabs, combo-box choices and accessibility text. Original English strings are retained as dynamic Qt properties, allowing a window to switch from Swedish to Korean (for example) without translating a translation. Editable values and user-entered paths are never touched.
Ten languages ship without optional dependencies or network access: English, Swedish, German, Spanish, Simplified Chinese (Mandarin), Portuguese, Hindi, Korean, Icelandic and French. Catalog entries cover application navigation, every registered module, Preferences, common actions and common settings terminology. Uncatalogued scientific or third-party terms remain in English rather than being guessed.
Classes¶
One selectable UI language. |
Functions¶
|
Return |
|
Return the active persisted language without creating an import cycle. |
|
Return whether |
|
Translate transient Qt dialogs when they are shown. |
|
Load Qt's own translations for |
|
Return |
|
Return a supported language code, falling back to English. |
|
Retranslate static text in |
|
Fill a dropdown with translated captions over untranslatable values. |
|
Set dynamic UI text while retaining its canonical template and values. |
|
Translate one English UI string. |
Module Contents¶
- class spacr.qt.i18n.Language[source]¶
One selectable UI language.
- Parameters:
code – stable persisted language code.
native_name – language name written in that language.
english_name – language name written in English.
- spacr.qt.i18n.catalog_coverage(sources: Iterable[str], language: str | None = None) tuple[int, int][source]¶
Return
(translated, total)for an iterable of source strings.
- spacr.qt.i18n.current_language() str[source]¶
Return the active persisted language without creating an import cycle.
- spacr.qt.i18n.has_translation(text: object, language: str | None = None) bool[source]¶
Return whether
texthas an exact or conservative term translation.
- spacr.qt.i18n.install_dialog_translation(app) None[source]¶
Translate transient Qt dialogs when they are shown.
File pickers, message boxes, input prompts and progress dialogs are often constructed and executed in one expression, so they do not exist during the main-window language pass. An application event filter catches only top-level
QDialogshow events and applies the same conservative exact catalog translation to their title, labels, buttons and accessible text. Dynamic paths, table data and user text remain outside that traversal.
- spacr.qt.i18n.install_qt_translations(app, language: str | None = None) bool[source]¶
Load Qt’s own translations for
language. True if one loaded.Idempotent: a translator installed by an earlier call is removed first, so switching language twice does not leave the first one underneath answering for strings the second does not carry.
- spacr.qt.i18n.language_choices() tuple[tuple[str, str], ...][source]¶
Return
(display label, code)choices for Preferences.
- spacr.qt.i18n.normalize_language(code: object) str[source]¶
Return a supported language code, falling back to English.
Locale-shaped values such as
pt_BRandzh-CNresolve to their bundled base/catalog variants. This also makes a manually editedQSettingsfile harmless.
- spacr.qt.i18n.retranslate_widget_tree(root, language: str | None = None, *, only_new: bool = False) None[source]¶
Retranslate static text in
rootand all existing descendants.The function is intentionally best-effort and idempotent. It never edits line-edit contents, text editors, table cells, model data, filenames or console output.
Qt’s OWN text follows too – see
_follow_qt_own_catalogs()– so a language chosen after launch reaches the right-click menu of every text field, not only the captions spaCR wrote.only_newskips widgets this pass would translate to exactly what they already say. Every visited widget is stamped with the language it was translated into and the catalog generation that was current; a later pass asked foronly_newskips the ones whose stamp still matches. A language change changes the stamp, and so does a catalog gaining a row, so neither can be missed.IT IS OFF BY DEFAULT AND THAT IS DELIBERATE. A caller that has just replaced a caption itself wants the full pass –
_translate_qt_textdetects an outside setter by comparing the rendered value, and a skipped widget is not compared. The one caller that asks for it is_LateCaptionTranslator, where three near-root passes an event turn apart re-walk the same tree while a module screen is being assembled.
- spacr.qt.i18n.set_translatable_items(combo, sources: Iterable[str], values: Iterable[object] | None = None, language: str | None = None) None[source]¶
Fill a dropdown with translated captions over untranslatable values.
A combo box whose entries a handler reads back with
currentText()cannot be translated: the caption moves and every comparison misses. That is why the live preview’s dropdowns were marked untranslatable outright, and why the ones that were not marked went wrong quietly – the segmentation object box handedcellento a worker that only knowscell, and the threshold method wrotemedelvärdeinto a settings key that only acceptsmean.Each entry here carries what the code matches on in its item DATA, so
currentData()answers the same English value whatever the caption reads. The English sources are recorded on the widget, so the ordinary language pass re-renders the captions on every later change instead of freezing the language the dropdown happened to be built in.The selected entry is kept by its value, never by its caption, and signals stay blocked while the entries are replaced.
- Parameters:
combo – the dropdown to fill; its existing entries are replaced.
sources – the English captions, in order.
values – what each entry means to the code, in the same order; defaults to
sourcesitself.language – language to render in; the current one by default.
- Raises:
ValueError – if
valuesis not one value per caption.
- spacr.qt.i18n.set_translatable_text(widget, source: str, language: str | None = None, **values: object) None[source]¶
Set dynamic UI text while retaining its canonical template and values.
This is for application chrome such as
Connecting to {provider}…. User text, AI replies, worker output and scientific results must not use this helper because they intentionally remain untouched by localization.