Repository navigation
Translate the window into Omarchy's languages - #57
Conversation
Hype takes the shared Translator every Omarchy app carries, marks every string the window shows for translation, lists them in src/i18n/en.json beside 49 empty catalogs, and gets folio's translation sync, by way of signed's, to fill them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex found three messages still glued in English, parse errors cached by source alone so they kept the old language, and an untitled title that QML's retranslation never re-reads. The parse caches and slide render ids now carry a translation generation, Deck::retranslate redoes the deck's error, title and banners on a switch, and the starter headline of a new presentation is translated too. Co-Authored-By: Codex XHigh <noreply@openai.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…alone A slide edited within known boundaries may begin with --- that only those boundaries explain, so reparsing the whole document on a language switch turned "Unclosed code fence" into "Front matter needs a closing ---". The deck now remembers which check produced its error and repeats that one. It no longer re-sets the status on a switch: the status line is a flash of a few seconds, and setting it again would show an error that had already gone. The test now reaches the per-slide cache through slide editing and undo, and the thumbnail's render id. Co-Authored-By: Codex XHigh <noreply@openai.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
[Medium impact] The changes affect Hype’s window and the workflow that updates its language catalogs. The PR still needs the previously reported slide-direction fix before merging. Findings
SummaryHype adds live window translations, compiled language catalogs, and an automated translation sync.
Reviews (2) · Last reviewed commit: "Translate the close dialog's buttons and..." · Reviewed by Greptile |
| // too, and right-to-left languages mirror the window. | ||
| const QLocale locale = formatLocale(language); | ||
| QLocale::setDefault(locale); | ||
| QGuiApplication::setLayoutDirection(locale.textDirection()); |
There was a problem hiding this comment.
Slides follow the desktop direction
Translator::reload() now changes the application's layout direction, but sizeSlideText() creates a QTextOption without setting its text direction. That option inherits the application's direction. On Arabic, Hebrew, Persian, or Urdu desktops, slide lists and tables can therefore draw differently from the same presentation on an English desktop.
Set an explicit direction for slide text that does not depend on the desktop. The new slidesRenderTheSameRightToLeft test covers this path.
There was a problem hiding this comment.
Checked, and this does not happen: in Qt 6 a QTextOption defaults to Qt::LayoutDirectionAuto, and a QPainter on a slide image starts at LayoutDirectionAuto too, whatever QGuiApplication::layoutDirection() is, so each paragraph takes its direction from its own text. slidesRenderTheSameRightToLeft renders a headline, a list, a table, code, a quote and a placed image with the application set left to right and then right to left and requires identical pixels; it passes, and it fails if sizeSlideText is changed to option.setTextDirection(QGuiApplication::layoutDirection()), which is the case described here. No change. Checked by Opus 5.5; not reviewed by a second model.
The close dialog took Qt's standard Discard and Cancel, whose text Qt sets once from its own catalogs: about twenty of Omarchy's languages have none, and a live switch left the old words behind. The dialog now has its own buttons, translated like the rest of the window. Qt's right-click menu on the text fields asks for Cut, Copy, Paste and Select All through qsTr, so they are listed for the catalogs too, as folio does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hype was the one Omarchy app whose window stayed in English whatever language was picked under Setup > Language: it had no Translator, no string was marked for translation, and there was no catalog for anything to fill. This gives it the same setup folio and signed have.
src/translator.{h,cpp}is the copy every Omarchy app carries, byte for byte, from the omarchy-app skill's templates.main.cppinstalls it for the window, and for the--export-snapshotworker the window starts, so an export's progress and errors arrive in the window's language. The commands (hype check,render,export,new, ...) and command-line exports (hype file.md --pdf x.pdf) never install it: their output is read by scripts and agents, so it stays English, andhype_commandspasses unchanged.qsTr()ortr(): the toolbar, menus, dialogs, the shortcut overlay, the presenter view, and the status line's messages fromDeck, recovery, the file chooser, export and the renderer's slide problems. Sentences that were glued together ("Slide " + n + " of " + count,"Cannot " + operation + ": " + ..., the export progress stages) became whole sentences with%1placeholders, so a translation can reorder them; "N slides selected" is a counted string. The Place menu, which built its labels from position ids, names them from a table. The close dialog has its own Discard and Cancel buttons rather than Qt's standard ones, whose text Qt sets once from its own catalogs: about twenty of Omarchy's languages have none, and a live switch would leave the old words behind. Qt's right-click menu on the text fields asks for Cut, Copy, Paste and Select All throughqsTr, so those are listed for the catalogs too, as folio does. A new presentation's starter headline is translated too, since it becomes the author's text. Key names, the app name,images/andvideos/stay as they are. English reads as before, except that export progress now says "Converting the video on slide 2 of 5" where the old gluing produced "Converting video on slide 2 of 5".qsTr()bindings when the language changes, but text C++ makes and keeps would stay in the old language: parse errors are cached by slide source, the untitled name is read only when the deck changes, and thumbnails are cached by render id. The caches and render ids now carry a translation generation that a switch advances, andDeck::retranslatemakes the deck's error, title and banners again, repeating whichever check found the error, since a slide edited within known boundaries may begin with---that only those boundaries explain. A status message already on screen at the moment of a switch finishes its few seconds in the old language rather than being flashed again.src/i18n/en.jsonlists the 250 strings, and the 49 language catalogs exist empty, all compiled in throughresources.qrc. They exist up front because the sync may only modify catalogs that are already here. Until a catalog fills, its strings show in English.scripts/i18n-sync.pyand.github/workflows/i18n-sync.ymlare signed's, from Translate the window into Omarchy's languages automatically signed#18, withmasterfor the branch, Hype's brief for Muse, and Hype's Arch packages for the catalog tests, listed in the workflow rather than read from omarchy-pkgs. Like folio's and signed's, its land job merges its own "Update translations" pull request after checking that the patch only modifies existing catalogs, neveren.json.omacom/hypealready has theMUSE_API_KEYandI18N_SYNC_TOKENorganization secrets, so the first run after this merges fills the catalogs.englishCatalogMatchesTheSourcesfails when a translated string is missing fromen.jsonor a stale one is left in it, and the catalog tests check placeholders, plural forms, language codes and that every catalog is compiled in. The translator tests put back the default locale and layout direction they change, since Hype's tests share one process.windowFollowsTheLanguageloads the window in Danish, checks the close dialog's buttons through a live switch to Vietnamese and that Discard still closes the window, then switches back to English, andcachedTextFollowsTheLanguageswitches a deck with a cached parse error and an untitled name to Danish.slidesRenderTheSameRightToLeftdraws headlines, lists, a table, code, a quote and a placed image under both layout directions and requires identical pixels: the Translator turns the whole application right to left for Arabic, Hebrew, Persian and Urdu, and a slide is the author's, so it must not move. It does fail when the renderer's text follows the application's direction.docs/i18n.mddescribes the setup, and the README mentions it.Not in this pull request: for the right-to-left languages the window's layout isn't mirrored yet. Controls that follow the locale flip on their own while the layouts around them don't, as in signed today. Mirroring Hype's editor has to keep the slide stage and its placed media unmirrored, so it comes separately and is checked on a worker. The
.desktopfile'sName[…]andComment[…]live in omarchy-pkgs and aren't generated from the catalogs.Reviewed by Codex XHigh as a second opinion, once over the whole change and once over the caching it led to; its independence isn't guaranteed, since the reviewer can read this session's files. It contributed the missed glued messages, the stale caches and title, and the boundary case above, all fixed and covered by
cachedTextFollowsTheLanguage, which fails if the generation is dropped from either cache or the render id, or if the deck always reparses the whole document. The fix for that boundary case, and the close dialog's buttons (which Greptile pointed out), were checked by the tests named here rather than by another codex review. It found nothing wrong with the command line, exports, locale handling, the workflow's jobs and trust boundaries, or test isolation. The workflow's validation step was run as written in a fresh Arch container. Nothing here was looked at on a desktop: English draws as before apart from the one progress message above, and no other language has text until the first sync.🤖 Generated by Opus 5.5 in Claude Code. Reviewed by Codex XHigh.