Repository navigation
i18n: make the GUI translatable and add a Simplified Chinese interface - #8
Conversation
d3086ab to
6f75f94
Compare
wleeaf
left a comment
There was a problem hiding this comment.
Thank you, this is careful and thorough work. I built it with Qt 6.4: the catalogue compiles, tools/check-translations.py passes, all 11 GUI smoke tests pass in English, and text that is read back as data (the string encoding combo, the comparisons by tr() text) is handled correctly. A few things before merging:
-
Restart order (
gui/settingsdialog.cpp,restartApplication). The new instance is started before this one closes.MainWindow::closeEventcan be cancelled (maybeSaveTable()offers Cancel) and it also runsreleaseTargetUsers(), which removes breakpoints and injected code from the attached process. So if the user cancels the save prompt, two instances run; and the restart should not skip that release step either. Please close the main window first and start the new process only once the close was accepted (for example fromQCoreApplication::aboutToQuit, or aftermainWindow->close()returned true). -
Catalogue lookup in a privileged binary (
gui/i18n.cpp). The.debgivescheatenginecap_sys_ptrace, so it runs as a secure-exec process (seecore/secure_exec.hpp). Loading a.qmfrom the current directory (and thetranslations/paths relative to it) lets whoever starts it replace every interface string, including confirmation dialogs. This predates your PR, but please skip the working-directory and user-writable lookups whence::secureExecution()is true and use the built-in catalogue then. -
Rebase.
mainmoved:CHANGELOG.md,docs/PROGRESS.mdandgui/mainwindow.cppnow conflict. Inmainwindow.cppthe scan-failure warning becamescanWriteErrorText(), which builds its text from parts; those strings will needtr()too.
Small note: gui_lifecycle_smoke with CE_LANG=zh_CN fails because it checks English status-bar text (First scan complete.) and opens windows by English action text. That is fine for screenshot runs, but please mention in docs/I18N.md that only the screenshot mode supports CE_LANG.
6f75f94 to
18b38f7
Compare
|
All three points and the small note are addressed in the new head (
Re-ran locally with Qt 6.4.2: Release build, |
|
The red run on
|
|
Thanks for confirming. The branch is already rebased onto current The |
|
Let me state the current status plainly, since the last two notes were mostly CI bookkeeping: 1. The code side of the review is done. Head 2. The only thing blocking CI is the workflow approval. As a first-time contributor my runs are held at 3. A clarification about the Wine job: rebasing fixes |
English remains the source language, so a build without a catalogue behaves as before. Every user-visible GUI string now goes through tr() in member functions, or QCoreApplication::translate() in free functions and classes without Q_OBJECT, with QT_TRANSLATE_NOOP for static display arrays: the menu bar and menus, dialogs, labels, buttons, table headers, tooltips, placeholders, file dialog filters and status texts are covered. gui/i18n.cpp loads the catalogue from the translations directory beside the executable or from the built-in resource. The interface language comes from the new Settings > Language page (ui/language: follow the system, English, Simplified Chinese) and falls back to the desktop locale; a change applies on the next start. translations/cheatengine_zh_CN.ts is compiled with lrelease and embedded through qt_add_translations when the Qt6 Linguist tools are available, so the .deb and the AppImage carry Chinese, and a .qm dropped next to the binary still overrides the built-in copy. Building without the Linguist tools keeps working, in English, with a status line. The desktop file and the AppStream metadata carry Chinese text. CI installs qt6-tools-dev and qt6-l10n-tools, and tests the catalogues with the new tools/check-translations.py, which fails on an unfinished message or a dropped %1/%n placeholder; tools/ci-check.sh runs the same check. docs/I18N.md documents the workflow for translators and how to add a language. The screenshot review renders another interface language with CE_LANG=zh_CN. Not translated on purpose: cescan terminal output, messages from the Qt-free cecore library, the tutorial games (their steps quote the code in the game), Lua and agent tool names, and text stored in cheat tables.
Every window builds its texts in its constructor, so a new language needs a new start. Instead of leaving that to the user, applying a different language in Settings now asks to restart, and relaunches the same command line (the AppImage file itself when running from a bundled build). Choosing Later keeps the behaviour of applying the change on the next manual start.
- Close the main window before starting the replacement instance. The Settings dialog now only emits restartRequested; MainWindow closes itself through the normal closeEvent path (save prompt, releaseTargetUsers) and calls launchRestart() only when that close was accepted, so a cancelled save prompt cannot leave two instances behind and the release step is never skipped. - A binary holding a file capability runs as a secure-exec process: gui/i18n.cpp now loads only the built-in catalogue then, so a .qm beside the executable or in the working directory can no longer replace the interface strings of its confirmation dialogs. The startup log line says when this applies. - Rebase onto main. The new scanWriteErrorText() strings and the scan-warning title are translatable too, the CHANGELOG entry is folded into the existing Unreleased list, and the PROGRESS log entry keeps its date. - Document that CE_LANG is a screenshot-mode hook and that a privileged install ignores .qm overrides.
18b38f7 to
337d099
Compare
|
Rebased onto
Head is |
wleeaf
left a comment
There was a problem hiding this comment.
Thanks, all three points are addressed: the restart now goes through the normal close (save prompt and target release) and starts the new instance only when the close was accepted, a secure-exec binary loads only the built-in catalogue, and the new scan-error strings are translated in the matching context. Verified on the rebased head: the translation check, a fresh Release build with translations enabled, the full regression suite, all 11 GUI smoke tests and the CI configuration check pass.
Summary
The GUI is now fully translatable and ships with a Simplified Chinese (zh_CN)
interface. English remains the source language, so a build without a catalogue
behaves exactly as before; with nothing chosen in Settings the interface follows
the desktop locale.
gui/goes throughtr()in member functions, orQCoreApplication::translate()in free functions and classes withoutQ_OBJECT, withQT_TRANSLATE_NOOPfor static display arrays. That covers themenu bar and menus, actions, windows and dialogs, labels, buttons, check
boxes, table headers, tooltips, placeholders, file dialog filters, message
boxes and the empty-state hints.
gui/i18n.cppfinds and installs the translators. The interface language comesfrom the new Settings > Language page (follow the system, English, 简体中文,
stored as
ui/language) and otherwise from the desktop locale (LANG). Whenthe language changes, Settings offers to restart Cheat Engine right away; the
main window closes through the normal path first (save prompt,
releaseTargetUsers), and only then is the replacement process started withthe same command line. Unsaved table state is the user's call.
translations/cheatengine_zh_CN.ts(1644 messages in 53 contexts) is compiledby
lreleaseand embedded in the binaries throughqt_add_translations, sothe
.deband the AppImage carry it. A.qmfile dropped beside theexecutable or under
translations/overrides the built-in copy, which lets atranslator try a catalogue without rebuilding; a privileged install (the
.debgivescap_sys_ptrace) is a secure-exec process and uses only thebuilt-in catalogue, so those strings cannot be replaced from a writable path.
docs/I18N.mddocuments the workflow for translators, how to add a language,the secure-exec caveat, and that
CE_LANGis a hook of the screenshot modeonly.
line). CI installs
qt6-tools-devandqt6-l10n-tools, and tests thecatalogues with the new
tools/check-translations.py, which fails on anunfinished message or a dropped
%1/%nplaceholder. The same check runsfrom
tools/ci-check.sh.gui_lifecycle_smoke --screenshotscan render another language withCE_LANG=zh_CN; the default English run is unchanged.Deliberately not translated:
cescanterminal output, messages produced by theQt-free
cecorelibrary, the tutorial games (their steps quote the exact codeand instructions in the game), Lua and agent tool names, and text stored in cheat
tables or scripts.
Verification
main; the newscanWriteErrorText()warning, its twocall sites and the "Scan results truncated" title are translatable as well.
cheatengine,gui_lifecycle_smokeand theGUI smoke targets compile.
build/gui_lifecycle_smokepasses every stage.python3 tools/check-translations.py: all 1644 messages finished, placeholderspreserved.
ui/languageset the interface followsLANG(
zh_CNshows Chinese,en_USEnglish);ui/language=zh_CNshows the Chineseinterface regardless of
LANG; a binary copied away from the generated.qmstill logs
catalogue: built-in.build/gui_lifecycle_smoke --screenshots DIRrenders about 200 screenshots inboth themes; the Chinese set was rendered with
CE_LANG=zh_CNand inspectedfor clipped or overlapping text.
tools/ci-check.sh --configcovers both the Qt and the no-GUI configuration.