Skip to content

chore(ui): fill 411 missing strings + 15 plural entries across all 42 languages - #945

Merged
QuantumExplorer merged 43 commits into
developfrom
claude/fill-missing-localizations
Aug 9, 2026
Merged

chore(ui): fill 411 missing strings + 15 plural entries across all 42 languages#945
QuantumExplorer merged 43 commits into
developfrom
claude/fill-missing-localizations

Conversation

@QuantumExplorer

@QuantumExplorer QuantumExplorer commented Aug 8, 2026

Copy link
Copy Markdown
Member

What

Fills the 411 missing Localizable.strings keys and the 15 missing Localizable.stringsdict plural entries in all 42 non-en localizations. These are the whole SwiftDashSDK-migration era of new UI — the DashPay intro/FAQ/Enable flow, identity public keys, shielded/internal transfer history, Platform balance copy, masternode keys, username voting and the raw-transaction inspector.

Every language goes from 1294 → 1705 keys and 5 → 20 plural entries.

84 files changed, 59214 insertions(+), 0 deletions(-)

One commit per language so a single bad language can be reverted on its own.

⚠️ These translations are machine-generated

They have not been reviewed by a human translator. I raised the Transifex conflict before starting and the owner chose to land them in-repo as a stopgap.

Two consequences worth being explicit about:

  1. A tx pull -a will overwrite this. .tx/config maps DashWallet/<lang>.lproj/Localizable.strings to o:dash:p:dash-mobile-wallets:r:app-localizable-strings. To keep this work, push the en source up (tx push -s) so translators see the 411 new keys, and treat these strings as a placeholder that real translations supersede.
  2. They compete with human translators. Anything here that a translator later corrects should win.

tx is not installed on this machine, so I could not push the source myself.

Terminology decisions

The three balance names had no existing precedent in any of the 42 files, so I had to establish them. Everything else reuses the terminology already in each file (checked per language before writing).

en choice rationale
Platform, DashPay, Dash, CoinJoin, InstantSend, Orchard, Tenderdash, duffs, TESTNET, Evonode left untranslated product / brand names
Shielded translated per language (de abgeschirmt, es blindado, ru экранированный, ja シールド, zh 屏蔽 …) descriptive English word, not a coined brand; follows each language's established Zcash-ecosystem term
Transparent translated per language cognate almost everywhere

masternode / evonode / identity / contact request / credits follow each file's existing usage — e.g. tr uses Anadüğüm, ru мастернода, zh 主节点, fil keeps English technical loanwords as that file already does.

Reviewers who disagree with the Shielded/Transparent rendering for their language should change it — it is the one call that was genuinely mine and is applied consistently within each file, so it is cheap to sed.

Verification

Per language, all 42:

  • plutil -lint clean on both Localizable.strings and Localizable.stringsdict
  • exactly 1705 string keys / 20 plural entries; no duplicates
  • format specifiers match en exactly (multiset-compared, %1$@ normalised against %@); the 53 format-bearing strings use positional specifiers wherever word order moves
  • sort order preserved (stable, case-insensitive — what bartycrouch normalize produces)
  • insert-only diffs: 0 deletions across all 84 files; every pre-existing line is byte-identical
  • stringsdict category sets match each locale's CLDR rules — other-only for CJK/SEA, one/other for most European, one/few/other for hr/sr/ro, one/few/many/other for ru/uk/pl/cs/sk, one/two/few/other for sl, zero/one/two/few/many/other for ar

Build:

xcodebuild -workspace DashWallet.xcworkspace -scheme dashpay -sdk iphonesimulator \
  -destination 'generic/platform=iOS Simulator' ARCHS=arm64 build
** BUILD SUCCEEDED **

The build's bartycrouch run-script phase left every file untouched, which independently confirms the formatting and sort order are what the tool expects.

Runtime spot-check against the built bundle (de, ru, ja, pl) — the longest FAQ string resolves, and format specifiers render correctly:

de 2-arg: Der gemeinsame Privatsphäre-Pool wächst noch (3 von 10 Einzahlungen). …
ja 2-arg: 共有プライバシープールはまだ拡大中です(3 / 10 件の入金)。…
de fee  : ~0.0012 DASH (≈ €0.04)

I could not drive the FAQ screen itself in the simulator — the test device sits behind a PIN I don't have — so the FAQ check is bundle-level (string resolves, correct length, correct text) rather than a screenshot.

Pre-existing issues found along the way (not fixed here)

These are all pre-existing and none are introduced by this PR, but they affect how much of this work reaches users:

  1. 21 of the 43 .lproj dirs are not in the Xcode target. knownRegions lists only 22 languages + Base. These do not ship in the app today: ar ca da eo et fa fi fil hr hu mk ms nb ro sl sl_SI sq sr sv zh zh_TW. They are still tracked by Transifex, so filling them is not wasted — but adding them to the target is a separate, deliberate decision (it changes the App Store language list).
  2. Localizable.stringsdict ships for only 4 localizationsen, cs, sk, uk. The other 38 stringsdict files are not in the target, so their plural entries never load. Worth fixing separately.
  3. zh-Hans / zh-Hant-TW are near-empty stubs that shadow the real files. zh (909 translated) and zh_TW (908) are the well-translated ones, but only zh-Hans and zh-Hant-TW are in knownRegions — and each had just 43 of 1294 entries translated. So Chinese users have effectively been getting English. I filled all four, so the new strings land correctly either way, and I backfilled the 3 baseline plural entries the two stubs were missing. The pre-existing 1251 untranslated entries in those stubs are still untranslated — worth a follow-up to either populate them from zh/zh_TW or switch knownRegions.
  4. sl (52/1294) and sl_SI (28/1294) are similarly near-empty; neither ships today.

Not done

  • No human review of any string.
  • The 3 stale keys each language carries that no longer exist in en were left in place (Platform sync is not running…, Shielded transfer, Shielded transfer (pending)) — harmless, and removing them is bartycrouch's job.
  • Nothing pushed to Transifex.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Localization
    • Expanded wallet translations across numerous languages, covering DashPay, usernames, invitations, identities, voting, nodes, balances, transactions, CoinJoin, synchronization, and wallet status.
    • Added localized plural forms for vote counts, node counts, selections, contests, requests, merchants, and transactions.
    • Improved language-specific handling of singular, plural, and multi-count messages.
    • Added broader coverage for guidance, privacy explanations, diagnostics, confirmations, errors, and FAQ content.
    • Preserved numeric formatting and translated count-based messages consistently across supported languages.

QuantumExplorer and others added 30 commits August 9, 2026 02:48
Machine-generated German translations for the DashPay intro/FAQ/Enable
flow, identity public keys, shielded/internal transfers, Platform balance
copy, masternode keys, username voting, raw transaction inspector and SPV
diagnostics strings.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Simplified Chinese. zh-Hans is currently a near-empty stub (43 of 1294
existing entries translated) that shadows zh on iOS locale resolution;
the new keys are filled in both with the same Simplified text.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Traditional Chinese. zh-Hant-TW is currently a near-empty stub (43 of
1294 existing entries translated); the new keys are filled in both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
RTL. Directional arrows in the balance-transfer labels use the RTL
left-arrow so they read source-to-destination in Arabic.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
RTL. Strings that begin with a Latin token carry a leading RLM so the
line lays out right-to-left.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Latin script, matching the existing file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
sl_SI is a near-empty stub (28 of 1294 existing entries translated); the
new keys are filled in both with the same Slovenian text.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
QuantumExplorer and others added 10 commits August 9, 2026 04:21
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…2 languages

The username-voting UI added 15 pluralised strings that only existed in
en. Each language gets the CLDR plural categories its locale actually
uses — other-only for CJK/SEA, one/other for most European languages,
one/few/other for hr/sr/ro, one/few/many/other for the Slavic four-form
locales, one/two/few/other for sl, and zero/one/two/few/many/other for ar.

zh-Hans and zh-Hant-TW were also missing 3 of the 5 pre-existing plural
entries; those are backfilled from zh and zh_TW.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@QuantumExplorer, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 36 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b1c3f8e3-04a0-4a81-a555-309f5177268d

📥 Commits

Reviewing files that changed from the base of the PR and between d458f20 and 07e00b0.

📒 Files selected for processing (48)
  • DashWallet/ar.lproj/Localizable.strings
  • DashWallet/bg.lproj/Localizable.strings
  • DashWallet/ca.lproj/Localizable.strings
  • DashWallet/cs.lproj/Localizable.strings
  • DashWallet/da.lproj/Localizable.strings
  • DashWallet/de.lproj/Localizable.strings
  • DashWallet/el.lproj/Localizable.strings
  • DashWallet/el.lproj/Localizable.stringsdict
  • DashWallet/eo.lproj/Localizable.strings
  • DashWallet/es.lproj/Localizable.strings
  • DashWallet/et.lproj/Localizable.strings
  • DashWallet/fa.lproj/Localizable.strings
  • DashWallet/fi.lproj/Localizable.strings
  • DashWallet/fil.lproj/Localizable.strings
  • DashWallet/fr.lproj/Localizable.strings
  • DashWallet/hr.lproj/Localizable.strings
  • DashWallet/hr.lproj/Localizable.stringsdict
  • DashWallet/hu.lproj/Localizable.strings
  • DashWallet/id.lproj/Localizable.strings
  • DashWallet/it.lproj/Localizable.strings
  • DashWallet/ja.lproj/Localizable.strings
  • DashWallet/ja.lproj/Localizable.stringsdict
  • DashWallet/ko.lproj/Localizable.strings
  • DashWallet/mk.lproj/Localizable.strings
  • DashWallet/ms.lproj/Localizable.strings
  • DashWallet/nb.lproj/Localizable.strings
  • DashWallet/nl.lproj/Localizable.strings
  • DashWallet/pl.lproj/Localizable.strings
  • DashWallet/pt.lproj/Localizable.strings
  • DashWallet/ro.lproj/Localizable.strings
  • DashWallet/sk.lproj/Localizable.strings
  • DashWallet/sl.lproj/Localizable.strings
  • DashWallet/sl_SI.lproj/Localizable.strings
  • DashWallet/sq.lproj/Localizable.strings
  • DashWallet/sr.lproj/Localizable.strings
  • DashWallet/sr.lproj/Localizable.stringsdict
  • DashWallet/sv.lproj/Localizable.strings
  • DashWallet/th.lproj/Localizable.strings
  • DashWallet/tr.lproj/Localizable.strings
  • DashWallet/vi.lproj/Localizable.strings
  • DashWallet/zh-Hans.lproj/Localizable.strings
  • DashWallet/zh-Hans.lproj/Localizable.stringsdict
  • DashWallet/zh-Hant-TW.lproj/Localizable.strings
  • DashWallet/zh-Hant-TW.lproj/Localizable.stringsdict
  • DashWallet/zh.lproj/Localizable.strings
  • DashWallet/zh.lproj/Localizable.stringsdict
  • DashWallet/zh_TW.lproj/Localizable.strings
  • DashWallet/zh_TW.lproj/Localizable.stringsdict
📝 Walkthrough

Walkthrough

The pull request expands wallet localization coverage in Catalan, Danish, Esperanto, Estonian, Finnish, and Croatian catalogs. It also adds locale-specific pluralized strings for voting, node, username, selection, contest, merchant, transaction, and request counts.

Changes

Wallet localization

Layer / File(s) Summary
Expanded translated catalogs
DashWallet/ca.lproj/Localizable.strings, DashWallet/da.lproj/Localizable.strings, DashWallet/eo.lproj/Localizable.strings, DashWallet/et.lproj/Localizable.strings, DashWallet/fi.lproj/Localizable.strings, DashWallet/hr.lproj/Localizable.strings
Added translations for DashPay, identities, usernames, voting, masternodes, Platform transfers, balances, CoinJoin, diagnostics, transactions, invitations, wallet states, and FAQ content.
Pluralized voting and request strings
DashWallet/*/Localizable.stringsdict
Added locale-specific plural forms for vote counts, node counts, username voting, selections, contest weighting, vote multipliers, merchant counts, transaction counts, and requests. Format arguments and numeric types were preserved.
Locale-specific plural rules
DashWallet/ar.lproj/Localizable.stringsdict, DashWallet/ru.lproj/Localizable.stringsdict, DashWallet/sl.lproj/Localizable.stringsdict, DashWallet/sl_SI.lproj/Localizable.stringsdict, DashWallet/zh-Hans.lproj/Localizable.stringsdict, DashWallet/zh-Hant-TW.lproj/Localizable.stringsdict
Added language-specific plural categories such as zero, one, two, few, many, and other where required.

Estimated code review effort: 2 (Simple) | ~15 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the addition of 411 missing strings and 15 plural entries across 42 language localizations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/fill-missing-localizations

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

@QuantumExplorer QuantumExplorer changed the title i18n: fill 411 missing strings + 15 plural entries across all 42 languages chore(ui): fill 411 missing strings + 15 plural entries across all 42 languages Aug 8, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
DashWallet/et.lproj/Localizable.strings (2)

49-49: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Remove the unintended leading space.

The translation starts with a literal space before %@, although the key does not. This adds unwanted whitespace before the subject in the UI.

Proposed fix
- "%@ is not allowed to access the camera" = " %@ pole kaamerale ligipääsu";
+ "%@ is not allowed to access the camera" = "%@ pole kaamerale ligipääsu";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/et.lproj/Localizable.strings` at line 49, Remove the unintended
leading space from the Estonian translation value for "%@ is not allowed to
access the camera", keeping the placeholder and remaining wording unchanged.

517-517: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use a noun for “block”, not an imperative verb.

blokeeri means “block” as a command. This string labels a block number, so use the reviewed Estonian noun for “block” and preserve both format arguments.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/et.lproj/Localizable.strings` at line 517, Update the Estonian
translation for the “block #%d of %d” label to use the reviewed noun meaning
“block” instead of the imperative “blokeeri,” while preserving both positional
format arguments.
DashWallet/hr.lproj/Localizable.strings (1)

1-5067: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Convert the catalog to UTF-16LE and correct the Croatian translations.

  • Store DashWallet/hr.lproj/Localizable.strings as UTF-16LE with BOM.
  • Change od kandidata to za kandidata on line 286.
  • Change bez staja na nečiju stranu to bez zauzimanja strane on line 3072.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/hr.lproj/Localizable.strings` around lines 1 - 5067, Convert the
Localizable.strings catalog to UTF-16LE with a BOM, preserving all existing keys
and values. In the translation for “All of your masternodes have voted on this
username...”, replace “od kandidata” with “za kandidata”; in the translation
containing “bez staja na nečiju stranu”, replace it with “bez zauzimanja
strane”.

Sources: Coding guidelines, Learnings

🟡 Minor comments (24)
DashWallet/ca.lproj/Localizable.strings-337-337 (1)

337-337: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Resolve the name, not the address.

Line [337] uses qualsevol la pot resoldre; la refers to aquesta adreça. This changes the privacy explanation to say that anyone can resolve the address. Refer to the name instead.

Suggested wording
- de manera que qualsevol la pot resoldre
+ de manera que qualsevol pot resoldre el nom
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/ca.lproj/Localizable.strings` at line 337, Update the Catalan
translation value for the Ethereum account explanation so the resolvable subject
is the name, not “aquesta adreça”; revise the phrase around “qualsevol la pot
resoldre” accordingly while preserving the rest of the translation and meaning.
DashWallet/ca.lproj/Localizable.strings-3170-3170 (1)

3170-3170: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use a non-imperative, plural Catalan section heading. Demana aquest nom can read as “Request this name” and is singular, but this key labels a section containing multiple contenders. Use Sol·licitants d'aquest nom or another equivalent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/ca.lproj/Localizable.strings` at line 3170, Update the Catalan
translation for the “Requesting this name” key to use a non-imperative plural
section heading, such as “Sol·licitants d'aquest nom”, while preserving the key
itself.
DashWallet/da.lproj/Localizable.strings-2467-2467 (1)

2467-2467: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve the meaning of “fallback” in the translation.

reserveregistrering reads as “reserve registration”. It does not clearly describe an alternative path used when no Platform address is available. Use a term such as alternativ skærmet registrering, subject to the localization glossary.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/da.lproj/Localizable.strings` at line 2467, Update the Danish
translation value for the shielded registration fallback message so “fallback”
clearly conveys an alternative registration path, using the localization
glossary’s equivalent of “alternativ skærmet registrering” instead of “skærmede
reserveregistrering.”
DashWallet/eo.lproj/Localizable.strings-543-543 (1)

543-543: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use an action form for this instruction.

Line [543] translates the source command as "Kolektas...", which is a third-person form. Use an imperative or the repository’s standard infinitive form, such as "Kolektu...", so the text reads as a user instruction.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/eo.lproj/Localizable.strings` at line 543, Update the translation
value for “Bundle recent diagnostic logs into a zip to AirDrop, mail, or save to
Files” from the third-person “Kolektas” form to the repository’s standard
imperative/action form, such as “Kolektu,” while preserving the rest of the
translation.
DashWallet/eo.lproj/Localizable.strings-2436-2438 (1)

2436-2438: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the translator context comments.

The /* local currency empty state */ comment is attached to "No masternodes yet". The /* Location Service Status */ comment is attached to the restored-wallet explanation. These comments can cause future translators to use the wrong meaning.

  • DashWallet/eo.lproj/Localizable.strings#L2436-L2438: replace or remove the local-currency comment and keep masternode empty-state context.
  • DashWallet/eo.lproj/Localizable.strings#L3199-L3200: replace the location-status comment with wallet-restoration context.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/eo.lproj/Localizable.strings` around lines 2436 - 2438, Update the
translator context comments in DashWallet/eo.lproj/Localizable.strings at lines
2436-2438 and 3199-3200: replace or remove the local-currency comment so “No
masternodes yet” retains masternode empty-state context, and replace the
location-status comment with wallet-restoration context for the restored-wallet
explanation.
DashWallet/eo.lproj/Localizable.strings-2937-2937 (1)

2937-2937: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Remove or parameterize the dated roadmap promise.

The source string in ContactsScreen.swift is hard-coded and copied into the localized entries. Use undated copy or a centrally maintained, release-controlled date to prevent stale roadmap text after October 2026.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/eo.lproj/Localizable.strings` at line 2937, Update the localized
entry for the private contact request message and its source in
ContactsScreen.swift to remove the hard-coded September–October 2026 roadmap
promise, or replace it with the centrally maintained release-controlled date
mechanism. Ensure all localized keys remain aligned with the revised source
string.
DashWallet/fi.lproj/Localizable.strings-3956-3957 (1)

3956-3957: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Correct the payment direction in the Finnish translation.

Use Tästä %@-saldosta ei voi maksaa tähän osoitteeseen.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/fi.lproj/Localizable.strings` around lines 3956 - 3957, Update the
Finnish translation for the “Send sheet source/destination mismatch” key to use
the requested payment direction: “Tästä %@-saldosta ei voi maksaa tähän
osoitteeseen”.
DashWallet/fi.lproj/Localizable.strings-1017-1017 (1)

1017-1017: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use a complete Finnish connection phrase.

Replace Dash Platformiin ei ole vielä yhdistetty with Yhteyttä Dash Platformiin ei ole vielä muodostettu.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/fi.lproj/Localizable.strings` at line 1017, Update the Finnish
localization value for the Dash Platform connection message to use “Yhteyttä
Dash Platformiin ei ole vielä muodostettu” while preserving the existing syncing
and retry text.
DashWallet/fi.lproj/Localizable.strings-471-472 (1)

471-472: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use a natural Finnish label for “Balance after”.

This label describes the balance after a Platform payment. Replace Saldo jälkeenpäin with Saldo maksun jälkeen.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/fi.lproj/Localizable.strings` around lines 471 - 472, Update the
Finnish “Balance after” localization in the CrowdNode section to use the natural
label “Saldo maksun jälkeen” instead of “Saldo jälkeenpäin”.
DashWallet/fi.lproj/Localizable.strings-1108-1110 (1)

1108-1110: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use Johdannaispolku for Derivation path.

Johtamispolku refers to a management path. Johdatuspolku is not the established cryptographic term.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/fi.lproj/Localizable.strings` around lines 1108 - 1110, Update the
Finnish localization value for the "Derivation path" key to use the established
cryptographic term "Johdannaispolku" instead of "Johtamispolku".
DashWallet/fi.lproj/Localizable.strings-4414-4415 (1)

4414-4415: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fix the Finnish grammar for the fee description.

Replace Erittäin tehokas ja matalat maksut with Erittäin tehokas, ja maksut ovat matalat.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/fi.lproj/Localizable.strings` around lines 4414 - 4415, Update the
Finnish translation for "Very efficient with low fees" in the balance info sheet
by replacing the existing value with "Erittäin tehokas, ja maksut ovat matalat".
DashWallet/hr.lproj/Localizable.strings-286-286 (1)

286-286: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use za kandidata in the vote guidance.

glasajte ponovno od kandidata means voting “from the contender”. The intended action is voting “for the contender”. Replace od with za.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/hr.lproj/Localizable.strings` at line 286, Update the Croatian
translation value for the masternode username voting guidance so the phrase uses
“glasajte ponovno za kandidata” instead of “glasajte ponovno od kandidata,”
while preserving the rest of the localized string.
DashWallet/hr.lproj/Localizable.strings-3072-3072 (1)

3072-3072: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fix the Croatian wording for abstaining.

bez staja na nečiju stranu contains the incorrect word staja in this sentence. Use bez stajanja na nečiju stranu or bez zauzimanja strane.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/hr.lproj/Localizable.strings` at line 3072, Update the Croatian
translation for the masternode voting string to replace the incorrect “bez staja
na nečiju stranu” wording with “bez stajanja na nečiju stranu” or “bez
zauzimanja strane,” preserving the original meaning.
DashWallet/hr.lproj/Localizable.stringsdict-103-120 (1)

103-120: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use the correct Croatian case for one username.

The one branch renders Glasano o 1 od 1 korisničko ime. After o, this singular phrase requires korisničkom imenu. Adjust the branch or reword the full sentence.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/hr.lproj/Localizable.stringsdict` around lines 103 - 120, Update
the Croatian singular “one” branch for the localized key %d of %d usernames
voted on so it uses the dative form “korisničkom imenu” after “o”; preserve the
existing “few” and “other” plural branches.
DashWallet/hr.lproj/Localizable.stringsdict-85-100 (1)

85-100: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Move count-dependent wording into the plural branches.

The fixed text contains adjectives or verbs that depend on the count. Singular values therefore render ungrammatical messages.

  • DashWallet/hr.lproj/Localizable.stringsdict#L85-L100: Reword %#@votes@ izbrojeno za ... so each Croatian plural branch supplies correct agreement.
  • DashWallet/eo.lproj/Localizable.stringsdict#L85-L99: Reword %#@votes@ kalkulitaj por ... so the singular branch uses singular agreement.
  • DashWallet/es.lproj/Localizable.stringsdict#L95-L108: Move contados into count-specific wording or use a neutral template.
  • DashWallet/es.lproj/Localizable.stringsdict#L143-L157: Replace fixed han votado with wording that remains correct when the count is one.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/hr.lproj/Localizable.stringsdict` around lines 85 - 100, The
pluralized vote-count strings use fixed count-dependent wording that becomes
grammatically incorrect for singular values. Update the entries in
DashWallet/hr.lproj/Localizable.stringsdict lines 85-100,
DashWallet/eo.lproj/Localizable.stringsdict lines 85-99, and
DashWallet/es.lproj/Localizable.stringsdict lines 95-108 and 143-157 so
agreement-dependent adjectives or verbs are supplied within the appropriate
plural branches, or replaced with neutral wording; preserve the existing
placeholders and correct singular/plural meaning.
DashWallet/et.lproj/Localizable.stringsdict-85-100 (1)

85-100: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use natural Estonian vote terminology.

Replace loetud kirje with a vote-result construction, such as %#@votes@ anti „%2$@“ kasuks. Have an Estonian reviewer confirm the final phrasing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/et.lproj/Localizable.stringsdict` around lines 85 - 100, Update
the localized format string under “%u votes counted for “%@”” to replace “loetud
kirje” with natural Estonian vote-result terminology, such as expressing that
the votes were cast for the quoted option. Preserve the existing pluralized
votes substitution and placeholder ordering, then have an Estonian reviewer
confirm the final phrasing.
DashWallet/hu.lproj/Localizable.stringsdict-85-100 (1)

85-100: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use idiomatic Hungarian for the vote-count message.

The current format renders 1 szavazat számolva ehhez: „Alice”, which does not clearly express votes counted for the contender. Use a native-speaker-approved construction and keep the complete count-dependent wording in the one and other variants.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/hu.lproj/Localizable.stringsdict` around lines 85 - 100, Update
the localized "%u votes counted for “%@”" entry in the votes plural dictionary
to use the approved idiomatic Hungarian construction. Move the complete
count-dependent wording, including the contender reference, into both the one
and other variants, preserving the correct vote count placeholder and plural
behavior.
DashWallet/eo.lproj/Localizable.stringsdict-101-115 (1)

101-115: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use a finite-verb status sentence.

Voĉdonite pri ... is clearer with an auxiliary, such as estis voĉdonite pri .... For this standalone status, use Oni voĉdonis pri %1$d el %#@names@ or another native-speaker-approved equivalent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/eo.lproj/Localizable.stringsdict` around lines 101 - 115, Update
the NSStringLocalizedFormatKey value in the %d of %d usernames voted on
localization to use a finite-verb Esperanto status sentence, such as the
approved Oni voĉdonis pri phrasing, while preserving the existing %1$d and
%#@names@ placeholders and plural entries.
DashWallet/ar.lproj/Localizable.stringsdict-349-371 (1)

349-371: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use Arabic dual and plural username forms.

The two branch needs a dual form. The few branch needs a plural form for values where n % 100 is 3–10. Have an Arabic reviewer validate the final wording.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/ar.lproj/Localizable.stringsdict` around lines 349 - 371, Update
the plural branches under the “Vote on %d usernames” localization entry: change
the two form to the Arabic dual “اسمَي مستخدم” and the few form to the Arabic
plural “أسماء مستخدمين,” while leaving the other branches unchanged. Have an
Arabic reviewer validate the final wording.
DashWallet/de.lproj/Localizable.stringsdict-133-163 (1)

133-163: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Move the finite verb into the plural forms.

The second argument selects the nested plural form. With a count of one, the current entries still use a plural verb. Put the complete sentence in the one and other forms:

  • German: hat abgestimmt / haben abgestimmt.
  • Bulgarian: гласува / гласуваха.
  • Catalan: ha votat / han votat.
  • Greek usernames: singular Ψηφίστηκε / plural Ψηφίστηκαν.
  • Greek nodes: ψήφισε / ψήφισαν.
  • Persian: رأی داد / رأی دادند.
  • Macedonian: гласаше / гласаа.
  • Dutch: heeft gestemd / hebben gestemd.

Apply these changes to the listed entries and to both node keys where present.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/de.lproj/Localizable.stringsdict` around lines 133 - 163, Update
the plural-form entries in DashWallet/de.lproj/Localizable.stringsdict:133-163,
bg.lproj/Localizable.stringsdict:133-163,
ca.lproj/Localizable.stringsdict:133-163,
el.lproj/Localizable.stringsdict:101-116 and :133-163,
fa.lproj/Localizable.stringsdict:133-163,
mk.lproj/Localizable.stringsdict:133-163, and
nl.lproj/Localizable.stringsdict:133-163. For each applicable voting entry and
both node keys where present, move the complete sentence into the nested one and
other forms so the singular/plural finite verbs are respectively German “hat
abgestimmt”/“haben abgestimmt”, Bulgarian “гласува”/“гласуваха”, Catalan “ha
votat”/“han votat”, Greek usernames “Ψηφίστηκε”/“Ψηφίστηκαν”, Greek nodes
“ψήφισε”/“ψήφισαν”, Persian “رأی داد”/“رأی دادند”, Macedonian
“гласаше”/“гласаа”, and Dutch “heeft gestemd”/“hebben gestemd”; retain the
correct count substitution in each form.
DashWallet/ca.lproj/Localizable.stringsdict-85-99 (1)

85-99: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep agreement-sensitive text inside the plural branches.

The fixed forms after %#@votes@ can disagree with the selected noun form. Move the complete sentence into each branch for:

  • DashWallet/ca.lproj/Localizable.stringsdict
  • DashWallet/ar.lproj/Localizable.stringsdict
  • DashWallet/bg.lproj/Localizable.stringsdict
  • DashWallet/el.lproj/Localizable.stringsdict
  • DashWallet/mk.lproj/Localizable.stringsdict

Alternatively, use number-neutral wording.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/ca.lproj/Localizable.stringsdict` around lines 85 - 99, The
pluralized “%u votes counted for “%@”” entries must keep the entire
agreement-sensitive sentence inside each plural branch rather than placing fixed
wording after %#@votes@. Apply this change in
DashWallet/ca.lproj/Localizable.stringsdict lines 85-99,
DashWallet/ar.lproj/Localizable.stringsdict lines 85-107,
DashWallet/bg.lproj/Localizable.stringsdict lines 85-99,
DashWallet/el.lproj/Localizable.stringsdict lines 85-99, and
DashWallet/mk.lproj/Localizable.stringsdict lines 85-99; alternatively replace
the fixed wording with number-neutral text.
DashWallet/ja.lproj/Localizable.stringsdict-89-100 (1)

89-100: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep the Japanese counted-noun phrase intact.

%2$d ユーザー名 is inserted directly before , producing 2 ユーザー名中. Use %2$d 件のユーザー名.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/ja.lproj/Localizable.stringsdict` around lines 89 - 100, Update
the “%d of %d usernames voted on” localization entry’s names.other value to use
the counted-noun phrase “%2$d 件のユーザー名”, preserving the surrounding Japanese
format string and placeholders.
DashWallet/zh-Hans.lproj/Localizable.stringsdict-49-60 (1)

49-60: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Label the voted count as usernames.

BulkResultView passes the voted count as %1$d. In all four Chinese entries, the text labels %1$d as votes. Replace it with username-specific wording.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/zh-Hans.lproj/Localizable.stringsdict` around lines 49 - 60,
Update the localized “%d of %d usernames voted on” entries so the %1$d value is
labeled as usernames rather than votes. Apply the same wording correction in
DashWallet/zh-Hans.lproj/Localizable.stringsdict (49-60),
DashWallet/zh-Hant-TW.lproj/Localizable.stringsdict (49-60),
DashWallet/zh.lproj/Localizable.stringsdict (89-100), and
DashWallet/zh_TW.lproj/Localizable.stringsdict (89-100), preserving the existing
pluralization structure.
DashWallet/fr.lproj/Localizable.stringsdict-95-108 (1)

95-108: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep count-dependent wording tied to the correct count.

  • In the French and Italian vote-count entries, place comptabilisée/comptabilisées and conteggiato/conteggiati in the plural variants.
  • In the French username entry, avoid the fixed plural votés, which conflicts with %2$d nom d'utilisateur.
  • In the French, Italian, and Ukrainian node entries, make the verb agree with %1$d, not %2$d.
  • In the Chinese username entries, label %1$d as usernames, not votes, in zh-Hans, zh-Hant-TW, zh, and zh_TW.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/fr.lproj/Localizable.stringsdict` around lines 95 - 108, Update
the plural variants in DashWallet/fr.lproj/Localizable.stringsdict lines 95-108
and 111-124 and DashWallet/it.lproj/Localizable.stringsdict lines 95-108 so
vote-count wording carries the appropriate singular/plural form; update the
French username entry at DashWallet/fr.lproj/Localizable.stringsdict lines
143-172 to avoid fixed plural “votés”. In
DashWallet/fr.lproj/Localizable.stringsdict lines 143-172,
DashWallet/it.lproj/Localizable.stringsdict lines 143-172, and
DashWallet/uk.lproj/Localizable.stringsdict lines 165-202, make node verbs agree
with %1$d rather than %2$d. Also correct the Chinese username entries in
zh-Hans, zh-Hant-TW, zh, and zh_TW Localizable.stringsdict files so %1$d is
labeled as usernames, not votes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@DashWallet/da.lproj/Localizable.strings`:
- Line 2937: Update the localized FAQ string identified by the private contact
request message to remove the fixed “September–October 2026” release window, and
apply the same date-free wording to every matching occurrence across the
localization catalogs. Preserve the existing explanation of public requests and
future privacy choices.

In `@DashWallet/pl.lproj/Localizable.stringsdict`:
- Around line 105-123: Pluralized localization sentences place count-dependent
grammar outside their plural branches; move the complete sentence into each
branch or use count-invariant wording. Update
DashWallet/pl.lproj/Localizable.stringsdict lines 105-123 (`policzonych` to
singular `policzony`), DashWallet/pt.lproj/Localizable.stringsdict lines 95-109
(`contabilizados` to `contabilizado`) and 143-174 (`votaram` to `votou`),
DashWallet/ro.lproj/Localizable.stringsdict lines 85-101 (`numărate` to
`numărat`) and 139-174 (`au votat` to `a votat`),
DashWallet/ru.lproj/Localizable.stringsdict lines 165-204 (use `проголосовал`
for nodes and `проголосовала` for masternodes in singular forms),
DashWallet/sk.lproj/Localizable.stringsdict lines 105-123 (`započítaných` to
`započítaný`), DashWallet/sl.lproj/Localizable.stringsdict lines 85-103 and
DashWallet/sl_SI.lproj/Localizable.stringsdict lines 85-103 (`preštetih` to
`preštet`), DashWallet/sq.lproj/Localizable.stringsdict lines 85-99 (`të
numëruara` to `e numëruar`) and 133-164 (`votuan` to `votoi`),
DashWallet/sr.lproj/Localizable.stringsdict lines 85-101 (`izbrojano` to
`izbrojan`), and DashWallet/sv.lproj/Localizable.stringsdict lines 85-99 (use
passive `räknades för` or count-specific participles). Validate every corrected
string with a native speaker.

---

Outside diff comments:
In `@DashWallet/et.lproj/Localizable.strings`:
- Line 49: Remove the unintended leading space from the Estonian translation
value for "%@ is not allowed to access the camera", keeping the placeholder and
remaining wording unchanged.
- Line 517: Update the Estonian translation for the “block #%d of %d” label to
use the reviewed noun meaning “block” instead of the imperative “blokeeri,”
while preserving both positional format arguments.

In `@DashWallet/hr.lproj/Localizable.strings`:
- Around line 1-5067: Convert the Localizable.strings catalog to UTF-16LE with a
BOM, preserving all existing keys and values. In the translation for “All of
your masternodes have voted on this username...”, replace “od kandidata” with
“za kandidata”; in the translation containing “bez staja na nečiju stranu”,
replace it with “bez zauzimanja strane”.

---

Minor comments:
In `@DashWallet/ar.lproj/Localizable.stringsdict`:
- Around line 349-371: Update the plural branches under the “Vote on %d
usernames” localization entry: change the two form to the Arabic dual “اسمَي
مستخدم” and the few form to the Arabic plural “أسماء مستخدمين,” while leaving
the other branches unchanged. Have an Arabic reviewer validate the final
wording.

In `@DashWallet/ca.lproj/Localizable.strings`:
- Line 337: Update the Catalan translation value for the Ethereum account
explanation so the resolvable subject is the name, not “aquesta adreça”; revise
the phrase around “qualsevol la pot resoldre” accordingly while preserving the
rest of the translation and meaning.
- Line 3170: Update the Catalan translation for the “Requesting this name” key
to use a non-imperative plural section heading, such as “Sol·licitants d'aquest
nom”, while preserving the key itself.

In `@DashWallet/ca.lproj/Localizable.stringsdict`:
- Around line 85-99: The pluralized “%u votes counted for “%@”” entries must
keep the entire agreement-sensitive sentence inside each plural branch rather
than placing fixed wording after %#@votes@. Apply this change in
DashWallet/ca.lproj/Localizable.stringsdict lines 85-99,
DashWallet/ar.lproj/Localizable.stringsdict lines 85-107,
DashWallet/bg.lproj/Localizable.stringsdict lines 85-99,
DashWallet/el.lproj/Localizable.stringsdict lines 85-99, and
DashWallet/mk.lproj/Localizable.stringsdict lines 85-99; alternatively replace
the fixed wording with number-neutral text.

In `@DashWallet/da.lproj/Localizable.strings`:
- Line 2467: Update the Danish translation value for the shielded registration
fallback message so “fallback” clearly conveys an alternative registration path,
using the localization glossary’s equivalent of “alternativ skærmet
registrering” instead of “skærmede reserveregistrering.”

In `@DashWallet/de.lproj/Localizable.stringsdict`:
- Around line 133-163: Update the plural-form entries in
DashWallet/de.lproj/Localizable.stringsdict:133-163,
bg.lproj/Localizable.stringsdict:133-163,
ca.lproj/Localizable.stringsdict:133-163,
el.lproj/Localizable.stringsdict:101-116 and :133-163,
fa.lproj/Localizable.stringsdict:133-163,
mk.lproj/Localizable.stringsdict:133-163, and
nl.lproj/Localizable.stringsdict:133-163. For each applicable voting entry and
both node keys where present, move the complete sentence into the nested one and
other forms so the singular/plural finite verbs are respectively German “hat
abgestimmt”/“haben abgestimmt”, Bulgarian “гласува”/“гласуваха”, Catalan “ha
votat”/“han votat”, Greek usernames “Ψηφίστηκε”/“Ψηφίστηκαν”, Greek nodes
“ψήφισε”/“ψήφισαν”, Persian “رأی داد”/“رأی دادند”, Macedonian
“гласаше”/“гласаа”, and Dutch “heeft gestemd”/“hebben gestemd”; retain the
correct count substitution in each form.

In `@DashWallet/eo.lproj/Localizable.strings`:
- Line 543: Update the translation value for “Bundle recent diagnostic logs into
a zip to AirDrop, mail, or save to Files” from the third-person “Kolektas” form
to the repository’s standard imperative/action form, such as “Kolektu,” while
preserving the rest of the translation.
- Around line 2436-2438: Update the translator context comments in
DashWallet/eo.lproj/Localizable.strings at lines 2436-2438 and 3199-3200:
replace or remove the local-currency comment so “No masternodes yet” retains
masternode empty-state context, and replace the location-status comment with
wallet-restoration context for the restored-wallet explanation.
- Line 2937: Update the localized entry for the private contact request message
and its source in ContactsScreen.swift to remove the hard-coded
September–October 2026 roadmap promise, or replace it with the centrally
maintained release-controlled date mechanism. Ensure all localized keys remain
aligned with the revised source string.

In `@DashWallet/eo.lproj/Localizable.stringsdict`:
- Around line 101-115: Update the NSStringLocalizedFormatKey value in the %d of
%d usernames voted on localization to use a finite-verb Esperanto status
sentence, such as the approved Oni voĉdonis pri phrasing, while preserving the
existing %1$d and %#@names@ placeholders and plural entries.

In `@DashWallet/et.lproj/Localizable.stringsdict`:
- Around line 85-100: Update the localized format string under “%u votes counted
for “%@”” to replace “loetud kirje” with natural Estonian vote-result
terminology, such as expressing that the votes were cast for the quoted option.
Preserve the existing pluralized votes substitution and placeholder ordering,
then have an Estonian reviewer confirm the final phrasing.

In `@DashWallet/fi.lproj/Localizable.strings`:
- Around line 3956-3957: Update the Finnish translation for the “Send sheet
source/destination mismatch” key to use the requested payment direction: “Tästä
%@-saldosta ei voi maksaa tähän osoitteeseen”.
- Line 1017: Update the Finnish localization value for the Dash Platform
connection message to use “Yhteyttä Dash Platformiin ei ole vielä muodostettu”
while preserving the existing syncing and retry text.
- Around line 471-472: Update the Finnish “Balance after” localization in the
CrowdNode section to use the natural label “Saldo maksun jälkeen” instead of
“Saldo jälkeenpäin”.
- Around line 1108-1110: Update the Finnish localization value for the
"Derivation path" key to use the established cryptographic term
"Johdannaispolku" instead of "Johtamispolku".
- Around line 4414-4415: Update the Finnish translation for "Very efficient with
low fees" in the balance info sheet by replacing the existing value with
"Erittäin tehokas, ja maksut ovat matalat".

In `@DashWallet/fr.lproj/Localizable.stringsdict`:
- Around line 95-108: Update the plural variants in
DashWallet/fr.lproj/Localizable.stringsdict lines 95-108 and 111-124 and
DashWallet/it.lproj/Localizable.stringsdict lines 95-108 so vote-count wording
carries the appropriate singular/plural form; update the French username entry
at DashWallet/fr.lproj/Localizable.stringsdict lines 143-172 to avoid fixed
plural “votés”. In DashWallet/fr.lproj/Localizable.stringsdict lines 143-172,
DashWallet/it.lproj/Localizable.stringsdict lines 143-172, and
DashWallet/uk.lproj/Localizable.stringsdict lines 165-202, make node verbs agree
with %1$d rather than %2$d. Also correct the Chinese username entries in
zh-Hans, zh-Hant-TW, zh, and zh_TW Localizable.stringsdict files so %1$d is
labeled as usernames, not votes.

In `@DashWallet/hr.lproj/Localizable.strings`:
- Line 286: Update the Croatian translation value for the masternode username
voting guidance so the phrase uses “glasajte ponovno za kandidata” instead of
“glasajte ponovno od kandidata,” while preserving the rest of the localized
string.
- Line 3072: Update the Croatian translation for the masternode voting string to
replace the incorrect “bez staja na nečiju stranu” wording with “bez stajanja na
nečiju stranu” or “bez zauzimanja strane,” preserving the original meaning.

In `@DashWallet/hr.lproj/Localizable.stringsdict`:
- Around line 103-120: Update the Croatian singular “one” branch for the
localized key %d of %d usernames voted on so it uses the dative form
“korisničkom imenu” after “o”; preserve the existing “few” and “other” plural
branches.
- Around line 85-100: The pluralized vote-count strings use fixed
count-dependent wording that becomes grammatically incorrect for singular
values. Update the entries in DashWallet/hr.lproj/Localizable.stringsdict lines
85-100, DashWallet/eo.lproj/Localizable.stringsdict lines 85-99, and
DashWallet/es.lproj/Localizable.stringsdict lines 95-108 and 143-157 so
agreement-dependent adjectives or verbs are supplied within the appropriate
plural branches, or replaced with neutral wording; preserve the existing
placeholders and correct singular/plural meaning.

In `@DashWallet/hu.lproj/Localizable.stringsdict`:
- Around line 85-100: Update the localized "%u votes counted for “%@”" entry in
the votes plural dictionary to use the approved idiomatic Hungarian
construction. Move the complete count-dependent wording, including the contender
reference, into both the one and other variants, preserving the correct vote
count placeholder and plural behavior.

In `@DashWallet/ja.lproj/Localizable.stringsdict`:
- Around line 89-100: Update the “%d of %d usernames voted on” localization
entry’s names.other value to use the counted-noun phrase “%2$d 件のユーザー名”,
preserving the surrounding Japanese format string and placeholders.

In `@DashWallet/zh-Hans.lproj/Localizable.stringsdict`:
- Around line 49-60: Update the localized “%d of %d usernames voted on” entries
so the %1$d value is labeled as usernames rather than votes. Apply the same
wording correction in DashWallet/zh-Hans.lproj/Localizable.stringsdict (49-60),
DashWallet/zh-Hant-TW.lproj/Localizable.stringsdict (49-60),
DashWallet/zh.lproj/Localizable.stringsdict (89-100), and
DashWallet/zh_TW.lproj/Localizable.stringsdict (89-100), preserving the existing
pluralization structure.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: dd8726f6-c4c7-4a79-9cc9-103faa94a80b

📥 Commits

Reviewing files that changed from the base of the PR and between b2ac658 and fc86625.

📒 Files selected for processing (84)
  • DashWallet/ar.lproj/Localizable.strings
  • DashWallet/ar.lproj/Localizable.stringsdict
  • DashWallet/bg.lproj/Localizable.strings
  • DashWallet/bg.lproj/Localizable.stringsdict
  • DashWallet/ca.lproj/Localizable.strings
  • DashWallet/ca.lproj/Localizable.stringsdict
  • DashWallet/cs.lproj/Localizable.strings
  • DashWallet/cs.lproj/Localizable.stringsdict
  • DashWallet/da.lproj/Localizable.strings
  • DashWallet/da.lproj/Localizable.stringsdict
  • DashWallet/de.lproj/Localizable.strings
  • DashWallet/de.lproj/Localizable.stringsdict
  • DashWallet/el.lproj/Localizable.strings
  • DashWallet/el.lproj/Localizable.stringsdict
  • DashWallet/eo.lproj/Localizable.strings
  • DashWallet/eo.lproj/Localizable.stringsdict
  • DashWallet/es.lproj/Localizable.strings
  • DashWallet/es.lproj/Localizable.stringsdict
  • DashWallet/et.lproj/Localizable.strings
  • DashWallet/et.lproj/Localizable.stringsdict
  • DashWallet/fa.lproj/Localizable.strings
  • DashWallet/fa.lproj/Localizable.stringsdict
  • DashWallet/fi.lproj/Localizable.strings
  • DashWallet/fi.lproj/Localizable.stringsdict
  • DashWallet/fil.lproj/Localizable.strings
  • DashWallet/fil.lproj/Localizable.stringsdict
  • DashWallet/fr.lproj/Localizable.strings
  • DashWallet/fr.lproj/Localizable.stringsdict
  • DashWallet/hr.lproj/Localizable.strings
  • DashWallet/hr.lproj/Localizable.stringsdict
  • DashWallet/hu.lproj/Localizable.strings
  • DashWallet/hu.lproj/Localizable.stringsdict
  • DashWallet/id.lproj/Localizable.strings
  • DashWallet/id.lproj/Localizable.stringsdict
  • DashWallet/it.lproj/Localizable.strings
  • DashWallet/it.lproj/Localizable.stringsdict
  • DashWallet/ja.lproj/Localizable.strings
  • DashWallet/ja.lproj/Localizable.stringsdict
  • DashWallet/ko.lproj/Localizable.strings
  • DashWallet/ko.lproj/Localizable.stringsdict
  • DashWallet/mk.lproj/Localizable.strings
  • DashWallet/mk.lproj/Localizable.stringsdict
  • DashWallet/ms.lproj/Localizable.strings
  • DashWallet/ms.lproj/Localizable.stringsdict
  • DashWallet/nb.lproj/Localizable.strings
  • DashWallet/nb.lproj/Localizable.stringsdict
  • DashWallet/nl.lproj/Localizable.strings
  • DashWallet/nl.lproj/Localizable.stringsdict
  • DashWallet/pl.lproj/Localizable.strings
  • DashWallet/pl.lproj/Localizable.stringsdict
  • DashWallet/pt.lproj/Localizable.strings
  • DashWallet/pt.lproj/Localizable.stringsdict
  • DashWallet/ro.lproj/Localizable.strings
  • DashWallet/ro.lproj/Localizable.stringsdict
  • DashWallet/ru.lproj/Localizable.strings
  • DashWallet/ru.lproj/Localizable.stringsdict
  • DashWallet/sk.lproj/Localizable.strings
  • DashWallet/sk.lproj/Localizable.stringsdict
  • DashWallet/sl.lproj/Localizable.strings
  • DashWallet/sl.lproj/Localizable.stringsdict
  • DashWallet/sl_SI.lproj/Localizable.strings
  • DashWallet/sl_SI.lproj/Localizable.stringsdict
  • DashWallet/sq.lproj/Localizable.strings
  • DashWallet/sq.lproj/Localizable.stringsdict
  • DashWallet/sr.lproj/Localizable.strings
  • DashWallet/sr.lproj/Localizable.stringsdict
  • DashWallet/sv.lproj/Localizable.strings
  • DashWallet/sv.lproj/Localizable.stringsdict
  • DashWallet/th.lproj/Localizable.strings
  • DashWallet/th.lproj/Localizable.stringsdict
  • DashWallet/tr.lproj/Localizable.strings
  • DashWallet/tr.lproj/Localizable.stringsdict
  • DashWallet/uk.lproj/Localizable.strings
  • DashWallet/uk.lproj/Localizable.stringsdict
  • DashWallet/vi.lproj/Localizable.strings
  • DashWallet/vi.lproj/Localizable.stringsdict
  • DashWallet/zh-Hans.lproj/Localizable.strings
  • DashWallet/zh-Hans.lproj/Localizable.stringsdict
  • DashWallet/zh-Hant-TW.lproj/Localizable.strings
  • DashWallet/zh-Hant-TW.lproj/Localizable.stringsdict
  • DashWallet/zh.lproj/Localizable.strings
  • DashWallet/zh.lproj/Localizable.stringsdict
  • DashWallet/zh_TW.lproj/Localizable.strings
  • DashWallet/zh_TW.lproj/Localizable.stringsdict

Comment thread DashWallet/da.lproj/Localizable.strings
Comment thread DashWallet/pl.lproj/Localizable.stringsdict
QuantumExplorer and others added 2 commits August 9, 2026 06:30
NSStringLocalizedFormatKey is invariant, so any word agreeing with the
count must live in the plural branches, not the frame. Two mistakes:

- '%u votes counted for X' put the participle in the frame, so it could
  not agree at count 1 (pl 'policzonych', pt 'contabilizados',
  sq 'të numëruara', sv active 'räknade', …). The participle moves into
  each branch and the frame keeps only the trailing 'for X'.
- The '%1$d of %2$d … voted' keys carried a verb agreeing with %1$d,
  which is not the plural driver and therefore can never agree. Those
  frames become count-invariant labels ('Abgestimmt:', 'Votado:',
  'Голосование:', …) so the branch handles the only inflected noun.

26 languages touched; non-inflecting locales (CJK/SEA, hu, tr, fil, da,
nb, et) were already correct and are untouched.

Reported by CodeRabbit on #945.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…w translations

- hr/sr: 'bez staja na nečiju stranu' is ungrammatical -> 'bez zauzimanja
  strane'; 'glasajte ponovno od kandidata' -> 'za kandidata' (you vote
  *for* a contender, not from one).
- hr/sr stringsdict: the 'one' branch of the '%1$d of %2$d …' keys sat in
  the nominative although the frame's 'od' governs the genitive
  ('1 od 1 korisničko ime' -> 'korisničkog imena'). sl/cs/sk/pl/ru/uk were
  already genitive and are untouched.
- el stringsdict: 'από' takes the accusative -> κόμβο / κόμβους.
- ja stringsdict: counted nouns need the 件の counter before 中.
- fi: 'maksaa osoitetta' is not idiomatic -> 'Tästä %@-saldosta ei voi
  maksaa tähän osoitteeseen'; Johtamispolku -> Johdannaispolku (derivation,
  not management); plus three phrasing fixes.
- ca: 'qualsevol la pot resoldre' pointed 'la' at the address rather than
  the name; 'Demana aquest nom' was imperative for a section label.

Reported by CodeRabbit on #945.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@QuantumExplorer

Copy link
Copy Markdown
Member Author

Second round from the review body (the outside-diff and minor findings, which have no inline threads) — pushed in d2ae850.

Fixed — genuine errors in strings this PR added:

Finding Fix
hr/sr bez staja na nečiju stranu ungrammatical → bez zauzimanja strane. I'd made the same error in both — sr was derived from hr
hr/sr glasajte ponovno **od** kandidata za kandidata; you vote for a contender, not from one
hr/sr stringsdict one branch the frame's od governs the genitive but the branch was nominative (1 od 1 korisničko imekorisničkog imena, masternodea, čvora)
el stringsdict %d of %d nodes voted από takes the accusative → κόμβο / κόμβους
ja stringsdict counted nouns need the counter before 中 → %2$d 件のユーザー名
fi Tätä osoitetta ei voi maksaa maksaa osoitetta isn't idiomatic → Tästä %@-saldosta ei voi maksaa tähän osoitteeseen
fi Johtamispolku management path → Johdannaispolku (derivation)
fi ×3 Saldo maksun jälkeen, Yhteyttä Dash Platformiin ei ole vielä muodostettu, Erittäin tehokas, ja maksut ovat matalat
ca qualsevol **la** pot resoldre la pointed at the address, not the name → qualsevol pot resoldre el nom
ca Demana aquest nom imperative for a section label → Sol·liciten aquest nom

I checked the same case-government issue in sl, sl_SI, cs, sk, pl, ru, uk — those one branches were already genitive, so they're untouched.

Not fixed, with reasons:

  • et.lproj:49 (leading space) and et.lproj:517 (blokeeri as imperative) — both pre-existing, introduced by a352923c7, not lines this PR touches. They're Transifex-owned and a tx pull would restore them; worth fixing upstream.
  • Convert hr.lproj/Localizable.strings to UTF-16LE with BOM — declining. That guideline is stale. Every catalog in the repo, en included, is UTF-8 with no BOM today (head -c 42f2a 204e, i.e. /* N). Converting hr alone would make it the only UTF-16 file and break the plain-text tooling the repo already relies on. CLAUDE.md's "localization files are UTF-16LE" note no longer matches reality and should be corrected separately.
  • eo translator-context comments (/* local currency empty state */ on "No masternodes yet") — those comments are harmonized from the en source by bartycrouch, where one key has two call sites. Not a translation defect and not editable per-locale.
  • Dated FAQ copy — as covered in the other thread: it's en source copy, and the key is the English text.
  • Remaining idiom suggestions (et/hu/eo stringsdict phrasing, da reserveregistrering, zh username labelling) — left for native review. These are exactly the judgement calls the PR description flags as needing a native speaker, and I'd rather not layer more machine guesses on top.

Re-verified after the changes: plutil -lint clean on all 84 files, all 42 languages still at 1705 keys / 20 plural entries, CLDR category sets unchanged, format specifiers still match en for all 15 new plural keys, and ** BUILD SUCCEEDED ** with bartycrouch leaving every file untouched.

🤖 Addressed by Claude Code

@QuantumExplorer QuantumExplorer left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed the current head (d2ae850) rather than the earlier snapshots. The catalog/key counts, plist parsing, common key set, and whitespace checks pass for the 84-file PR diff. I found two remaining semantic problems in the voting copy; both affect what the UI tells the user and should be corrected before merging.

Comment thread DashWallet/zh-Hans.lproj/Localizable.strings Outdated
Comment thread DashWallet/zh-Hans.lproj/Localizable.stringsdict Outdated
The 'To change a vote, vote again from the contender you now prefer'
guidance was rendered with a literal 'from' in 38 locales. On
ContestDetailScreen the contenders are rows with a vote button, so the
action is casting a vote *for* that contender; 'from' inverts the
relationship and reads as though the contender casts the vote.

Each locale now uses its own idiomatic 'vote for' construction rather
than a calque: de 'für den Bewerber', pl 'na kandydata', pt 'no
candidato', el 'υπέρ του διεκδικητή', ja '候補者に', ko '후보에게',
zh '再次为…投票', th 'โหวตให้…'.

ru and uk already used 'за' and are unchanged; hr and sr were fixed in
d2ae850.

Also: the Chinese stringsdict frames labelled %1$d as a vote count when
it is the number of usernames/nodes voted on. All four Chinese catalogs
now use the unit-neutral '已投票:%1$d / %#@NAMEs@'.

Reported by QuantumExplorer on #945.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@QuantumExplorer
QuantumExplorer merged commit 9b81b7b into develop Aug 9, 2026
2 checks passed
QuantumExplorer added a commit that referenced this pull request Aug 9, 2026
* docs: correct the stale UTF-16LE claim about localization files

CLAUDE.md said `*.lproj/Localizable.strings` files are UTF-16LE and told
readers to keep them that way. That is inverted for the main app: all 43
locales of `DashWallet/*.lproj/Localizable.strings` and
`Localizable.stringsdict` are UTF-8 with no BOM, and plain `grep` works on
them. The files that actually are UTF-16LE are
`WatchApp/*.lproj/Interface.strings` (40 of 43; en, zh-Hans and zh-Hant-TW
are UTF-8).

The old wording was actively harmful — acting on it means running iconv
over UTF-8 files or "restoring" them to UTF-16, which breaks bartycrouch,
plutil and reviewable diffs. It came up in review on #945, where a
reviewer cited the guideline to request exactly that conversion.

Also notes that `file` reports pure-ASCII UTF-8 as `us-ascii`, and every
example command is runnable as written.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(ci): scope the Transifex encoding-fixup script to the main-app catalogs

scripts/convert_strings_to_utf8.sh ran `find $(pwd) -name '*.strings'` and
rewrote every match as UTF-8 without a BOM. That swept in the 40 UTF-16LE
WatchApp/*.lproj/Interface.strings files — which are UTF-16LE by design —
and anything under Pods/. Following the documented post-pull workflow
therefore silently changed encodings it should not touch.

Now scoped to DashWallet/*.lproj/Localizable.strings and .stringsdict,
and it detects the BOM instead of unconditionally rewriting, so it is
idempotent: on a clean tree it reports 'checked 86, normalised 0' and
leaves every file byte-identical. Also drops the vim dependency.

Verified both directions: no-op on the current tree, and a file forced to
UTF-16LE converts back byte-identical to the original.

Reported by CodeRabbit on #948.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
QuantumExplorer added a commit that referenced this pull request Aug 27, 2026
…les (#1079)

The Localizable.stringsdict PBXVariantGroup had only four children — en, sk,
cs, uk — so `find <builtapp> -name '*.stringsdict'` returned 4 even though all
43 catalogs exist on disk and are actively maintained (#945 added 15 plurals,
#1076 added `%d words`). Every pluralised string therefore fell back to English
in the other locales.

`%d words` is the clearest case: it lives only in stringsdict and in no
`.strings` catalog, so the 12/24 recovery-phrase-length picker rendered
"12 words / 24 words" in English on a Russian device.

Add the 18 remaining locales the app actually ships (bg de el es fr id it ja ko
nl pl pt ru th tr vi zh-Hans zh-Hant-TW) as children of the variant group. Both
the dashwallet and dashpay targets already reference that one group via build
files 2ADC722923B5547000D9DD37 and C9D2C91C2A320AA000D15901, so no build-phase
change is needed.

Bundled stringsdict count: 4 -> 22, one for each shipping locale.

Note: 21 further locales (ar ca da eo et fa fi fil hr hu mk ms nb ro sl sl_SI
sq sr sv zh zh_TW) have complete translations on disk but are absent from
knownRegions and from the Localizable.strings group, so they ship nothing at
all today. Wiring those up adds 21 new advertised languages (including RTL) and
needs a product decision on the sl/sl_SI, zh/zh-Hans and zh_TW/zh-Hant-TW
duplicates — tracked separately, deliberately out of scope here.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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.

1 participant