Skip to content

fix: localize remaining hardcoded user-facing strings (#18)#27

Merged
dannym-arx merged 2 commits into
masterfrom
pip/darkmatter-linux-18
Jun 18, 2026
Merged

fix: localize remaining hardcoded user-facing strings (#18)#27
dannym-arx merged 2 commits into
masterfrom
pip/darkmatter-linux-18

Conversation

@agent-p1p

@agent-p1p agent-p1p commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Routes the last few visible strings that bypassed translation through the i18n layer. Fixes the English fragments that leaked into otherwise-translated login and profile screens for it/de/ja users.

Wrapped in @tr("…") (Slint):

  • ui/login/login-screen.slint — NSEC field label
  • ui/profile/profile-page.slint — picture-field placeholder https://… or upload a file →
  • ui/profile/profile-page.slint — both NIP-05 labels (edit FieldRow + display InfoRow)

File-dialog title (the one subtlety)

The issue suggested routing the rfd file-picker title "Choose a profile picture" through "the same s() helper already used for other Rust-side status strings." That doesn't actually translate anything: s() (main.rs:223) is just v.into() — a &strSharedString conversion. The project also deliberately keeps all i18n in the Slint @tr catalogs and does not wire gettext-rs on the Rust side (see the notification_body comment at main.rs:8020).

To honor that architecture, this exposes the title as an @tr property on a new NativeDialogStrings Slint global and reads it on the UI thread before spawning the blocking dialog task. Same pattern as the existing EmojiSheet/ProfileSink globals.

Catalogs

Regenerated lang/dm-ui.pot and merged into the it/de/ja .po catalogs via the mandated scripts/update-translations.sh. The 5 new strings land untranslated (empty msgstr), matching the existing translation backlog (~120 untranslated entries per locale).

Note on catalog diff size: the .po diffs are large because msgmerge refreshes #: source-location comments (line numbers shifted by these edits) and demotes 3 pre-existing fuzzy entries. That churn reproduces identically when running update-translations.sh on pristine master — it is pre-existing catalog drift, not introduced by this change. Content changes are limited to the 5 added msgids.

Verification

  • cargo check — clean
  • cargo clippy — clean (only the pre-existing optional libmpv pkg-config probe warning)

Closes #18


Open in Stage

Summary by CodeRabbit

  • New Features

    • Expanded theme picker with new color and theme options including Synthwave and Chalkboard.
    • Profile picture upload dialog now displays localized titles.
  • Documentation

    • Updated German, Italian, and Japanese language translations with new UI strings (NSEC, NIP-05, theme options, and profile picture prompts).

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e607d4d2-f348-486c-bea9-c1c4a3509c07

📥 Commits

Reviewing files that changed from the base of the PR and between 212511a and d6e699a.

📒 Files selected for processing (9)
  • lang/de/LC_MESSAGES/dm-ui.po
  • lang/dm-ui.pot
  • lang/it/LC_MESSAGES/dm-ui.po
  • lang/ja/LC_MESSAGES/dm-ui.po
  • src/main.rs
  • ui/dark-matter-linux.slint
  • ui/login/login-screen.slint
  • ui/profile/profile-page.slint
  • ui/tokens.slint

Walkthrough

Wraps previously hardcoded "NSEC", "NIP-05", and PictureField placeholder strings in @tr() calls across the login and profile UI. Adds a new NativeDialogStrings global in tokens.slint, exports it from the main Slint entry point, and updates src/main.rs to read the localized file-dialog title from that global before opening the rfd picker. The .pot template and all three locale catalogs (de, it, ja) are regenerated to reflect new and shifted strings.

Changes

Localize UI strings and native file-dialog title

Layer / File(s) Summary
NativeDialogStrings global and @tr() wraps in UI components
ui/tokens.slint, ui/dark-matter-linux.slint, ui/login/login-screen.slint, ui/profile/profile-page.slint
Defines and exports NativeDialogStrings with a localized choose-profile-picture property in tokens.slint, re-exports it from dark-matter-linux.slint, and wraps the NSEC label, PictureField URL placeholder, and both NIP-05 labels in @tr() calls.
Rust file-dialog title read from NativeDialogStrings
src/main.rs
Reads get_choose_profile_picture() from NativeDialogStrings on the UI thread and passes the localized string to rfd::FileDialog via .set_title().
.pot template regeneration with new msgids
lang/dm-ui.pot
Regenerates the master template with updated source line references and adds new msgid entries for NSEC, PictureField hint, NIP-05, Synthwave, Chalkboard, and NativeDialogStrings "Choose a profile picture".
German (de) catalog update
lang/de/LC_MESSAGES/dm-ui.po
Refreshes source line anchors, adds NSEC and NIP-05 entries with empty msgstr, adds the PictureField hint, new theme names, and maps NativeDialogStrings to "Profilbild auswählen"; rewraps several existing msgstr blocks.
Italian (it) and Japanese (ja) catalog updates
lang/it/LC_MESSAGES/dm-ui.po, lang/ja/LC_MESSAGES/dm-ui.po
Both catalogs receive the same new entries (NSEC, NIP-05 empty, PictureField hint, expanded theme picker, ErrorCopy re-anchoring, NativeDialogStrings); Italian and Japanese translations are provided where available and left empty for newly added strings.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pip/darkmatter-linux-18

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@stage-review

stage-review Bot commented Jun 16, 2026

Copy link
Copy Markdown

Ready to review this PR? Stage has broken it down into 3 individual chapters for you:

Title
1 Localize hardcoded strings in Slint UI
2 Expose localized dialog titles to Rust
3 Update translation catalogs and source locations
Open in Stage

Chapters generated by Stage for commit d6e699a on Jun 18, 2026 12:50pm UTC.

@agent-p1p

Copy link
Copy Markdown
Contributor Author

Verification + CI status

Local checks (the exact commands CI runs) all pass on this branch:

  • cargo fmt --all -- --check → exit 0
  • cargo clippy --locked --all-targets -- -D warnings → exit 0
  • cargo check → clean

CI is red for an environmental reason unrelated to this PR. Every build matrix job fails in 2–3s with empty steps, and the fmt + clippy job fails at the webfactory/ssh-agent@v0.9.0 step (the Check formatting and Clippy steps are skipped, never run). Root cause: the DARKMATTER_DEPLOY_KEY secret — required to fetch the private marmot-protocol/darkmatter ssh dependency — is unavailable to these runs.

This is not introduced by this change: the identical failure pattern is present on the latest master push (run 27626370659) and on sibling PR #20 (run 27639097077). It blocks all real verification in CI across the whole repo.

CodeRabbit: ✅ pass. No sensitive paths touched.

cc @ Jeff — needs the deploy-key secret restored on CI before the build/lint jobs can go green; the code itself is verified locally.

@dannym-arx

Copy link
Copy Markdown
Collaborator

@agent-p1p please rebase on top of master to fix the CI

@agent-p1p agent-p1p force-pushed the pip/darkmatter-linux-18 branch from 9393610 to b896549 Compare June 18, 2026 03:16
@agent-p1p

Copy link
Copy Markdown
Contributor Author

@dannym-arx done — rebased pip/darkmatter-linux-18 onto current master (now sits one commit on top of f00b739) and force-pushed.

That fixed the CI failure you were hitting: every build job had been insta-failing in ~2s because the old branch predated the master switch from the private ssh DARKMATTER_DEPLOY_KEY dep to the public https marmot dep. After the rebase:

  • ✅ build (x86_64-unknown-linux-gnu) — 8m38s
  • ✅ build (aarch64-unknown-linux-gnu) — 9m13s
  • ✅ build (aarch64-apple-darwin) — 16m5s
  • ✅ clippy — 4m8s
  • ✅ CodeRabbit
  • fmt — see below

The one remaining red check, fmt, is not from this PR. It's a pre-existing formatting break already red on master itself (HEAD f00b739, run 27726916757 shows fmt: failure), introduced by master commit 0adfb27 "fixes #0afd5344 offline queue". The unformatted lines are in the offline-queue flush block (src/main.rs ~6051–6132); this PR's only diff is at line 5819 (the i18n @tr wiring), nowhere near it.

I'm deliberately not folding a cargo fmt of master's offline-queue code into this localization PR — that'd be unrelated scope on a green-on-its-own change. The fix is a one-liner that belongs on master (or its own PR): run cargo fmt --all and commit. Once that lands and this rebases again, fmt goes green here too.

cc @ Jeff for the call on the master fmt fix.

@dannym-arx

Copy link
Copy Markdown
Collaborator

@agent-p1p rebase on top of master, and I'm telling you for certain that the fmt issues will be fixed, also you have conflicts that need to be fixed

@agent-p1p agent-p1p force-pushed the pip/darkmatter-linux-18 branch from b896549 to 63f03b2 Compare June 18, 2026 06:03
@agent-p1p

Copy link
Copy Markdown
Contributor Author

@dannym-arx done. Rebased pip/darkmatter-linux-18 onto current master (now sits one commit on top of d6239f6) and force-pushed.

You were right on both counts:

  • Conflicts resolved. The branch predated fix: add pointer cursor to clickable rows and chips (#20) #26 (pointer-cursor) landing on master. Conflicts were in ui/dark-matter-linux.slint (the tokens import line — master added ErrorCopy, this PR added NativeDialogStrings; merged both) and the four lang/ catalogs. I reset the catalogs to master's clean state and re-ran scripts/update-translations.sh so the new @tr strings (e.g. "Choose a profile picture") re-extract cleanly on top of the post-fix: add pointer cursor to clickable rows and chips (#20) #26 base instead of hand-merging conflict markers.
  • fmt is green. The master fmt fix has landed, so the offline-queue formatting break I called out last time is gone. cargo fmt --all -- --check, cargo check, and cargo clippy --locked --all-targets -- -D warnings all pass locally, and CI is fully green: fmt, clippy, all three build targets, CodeRabbit.

No sensitive paths touched (UI strings + translation catalogs only).

@agent-p1p agent-p1p marked this pull request as ready for review June 18, 2026 06:22
@dannym-arx

Copy link
Copy Markdown
Collaborator

@agent-p1p a few things are missing translations in the i18n... nsec is fine... but the rest....

@dannym-arx dannym-arx marked this pull request as draft June 18, 2026 07:08
agent-p1p added a commit that referenced this pull request Jun 18, 2026
Fill the it/de/ja catalog entries for the two user-facing strings added
in this PR that landed untranslated:
- "Choose a profile picture" (NativeDialogStrings)
- "https://… or upload a file →" (PictureField)

NSEC and NIP-05 are Nostr protocol identifiers and are intentionally
left as passthrough (empty msgstr → falls back to the identifier),
matching the existing convention.

Addresses @dannym-arx review feedback on #27.
@agent-p1p

Copy link
Copy Markdown
Contributor Author

@dannym-arx good catch — the new @tr strings were wired up but landed with empty msgstr, so it/de/ja users were still seeing English. Fixed in 1ec7be4:

msgid it de ja
Choose a profile picture Scegli un'immagine del profilo Profilbild auswählen プロフィール画像を選択
https://… or upload a file → https://… o carica un file → https://… oder Datei hochladen → https://… またはファイルをアップロード →

Left untranslated (passthrough, empty msgstr falls back to the identifier):

  • NSEC — you said this is fine.
  • NIP-05 — same class: it's a Nostr protocol identifier (the spec name), not a phrase. It renders identically in every locale, matching how the rest of the app treats protocol terms.

If you'd actually prefer NIP-05 localized too (or a different phrasing on any of the above), say the word and I'll adjust. All three catalogs parse cleanly.

dannym-arx
dannym-arx previously approved these changes Jun 18, 2026
@dannym-arx

Copy link
Copy Markdown
Collaborator

@agent-p1p rebase on top and it should be fine to merge

Wrap the strings that bypassed translation in @tr():
- login NSEC field label (login-screen.slint)
- profile picture-field placeholder (profile-page.slint)
- both NIP-05 labels, edit + display (profile-page.slint)

The native file-picker title "Choose a profile picture" is set on the
Rust side via rfd. The s() helper is only a SharedString conversion, not
a translator, and the project deliberately keeps i18n in the Slint @tr
catalogs (see notification_body comment in main.rs). So expose the title
as an @tr property on a new NativeDialogStrings Slint global and read it
on the UI thread before spawning the blocking dialog task.

Regenerated lang/dm-ui.pot and merged into the it/de/ja catalogs via
scripts/update-translations.sh; the new strings land untranslated,
matching the existing translation backlog.

Closes #18
Fill the it/de/ja catalog entries for the two user-facing strings added
in this PR that landed untranslated:
- "Choose a profile picture" (NativeDialogStrings)
- "https://… or upload a file →" (PictureField)

NSEC and NIP-05 are Nostr protocol identifiers and are intentionally
left as passthrough (empty msgstr → falls back to the identifier),
matching the existing convention.

Addresses @dannym-arx review feedback on #27.
@agent-p1p

Copy link
Copy Markdown
Contributor Author

@dannym-arx done — rebased pip/darkmatter-linux-18 onto current master (212511a), now 2 commits on top with no merge conflicts (mergeable: MERGEABLE).

The only conflicts were in the gettext catalogs (lang/dm-ui.pot + the it/de/ja .po files) — pure source-line-reference and POT-timestamp drift from master's UI line-number shifts. Resolved by regenerating the .pot from the rebased UI tree with slint-tr-extractor and msgmerge-ing each catalog against it; the new translations from 1ec7be4 (file-dialog title + picture-field placeholder for it/de/ja) are preserved.

Local checks green: cargo fmt --all -- --check, cargo clippy --locked --all-targets -- -D warnings, and the debug build all pass. CI re-triggered on d6e699a (fmt already green).

@dannym-arx dannym-arx marked this pull request as ready for review June 18, 2026 13:16
@dannym-arx dannym-arx merged commit b8a95f0 into master Jun 18, 2026
5 of 6 checks passed
@dannym-arx dannym-arx deleted the pip/darkmatter-linux-18 branch June 18, 2026 13:17
@agent-p1p

Copy link
Copy Markdown
Contributor Author

Pip adversarial review

Verdict: no blocking findings for PR #27.

I reviewed the merged diff against #18's listed locations:

  • ui/login/login-screen.slint wraps the NSEC field label in @tr(...).
  • ui/profile/profile-page.slint wraps the picture placeholder and both NIP-05 labels in @tr(...).
  • ui/tokens.slint exposes NativeDialogStrings.choose-profile-picture as @tr("Choose a profile picture"); src/main.rs reads it on the UI thread before opening the blocking rfd picker.
  • lang/dm-ui.pot and the it/de/ja .po catalogs contain the new msgids.
  • The profile-picture placeholder and native dialog title have it/de/ja translations. NSEC and NIP-05 are protocol identifiers and correctly fall back to the original text when the locale entry is intentionally empty.

Verification:

  • GitHub checks are green: fmt, clippy, all build targets, CodeRabbit.
  • Local cargo fmt --all -- --check passes.
  • Local cargo check could not complete in this worker image because system pkg-config deps are missing (fontconfig.pc, then alsa.pc); I did not treat that as a PR failure because the same commit has green GitHub CI.

Sensitive paths touched: none of the repo-sensitive paths (src/vault.rs, src/blossom.rs, src/backend.rs, src/media_cache.rs, src/settings.rs, ui/keys/**) were changed.

Out-of-scope follow-up filed: #71 tracks two remaining hardcoded generated-key readout labels on the login screen (PUBLIC KEY (NPUB), SECRET KEY (NSEC)). They were not among #18's listed locations, so they do not block this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants