Skip to content

Fix: use locale plural rules and whole messages in translations - #463

Merged
SandObserver merged 2 commits into
mainfrom
fix/i18n-plurals-and-language-tags
Oct 16, 2026
Merged

SandObserver merged 2 commits into
mainfrom
fix/i18n-plurals-and-language-tags

Conversation

@SandObserver

Copy link
Copy Markdown
Owner

Summary

  • Replace singular/plural choices made with === 1 by counted catalog messages: home.resultCount, status.pending, Connections ui.peerCount/ui.peerRatio/ui.peersOnline, Disk Health ui.baysFailed.
  • Add wtCount() (counted widget messages via Intl.PluralRules), a vars argument to wt(), relativeTime() and a re-exported formatList() to the widget toolbox; loadStrings() now also awaits the shared widget strings.
  • Add formatList() to format-number.js (Intl.ListFormat in the interface language) and use it in the listbox summary, withheld-secret toast, Disk Health, GitHub filters, Connections map and Backup labels.
  • Turn accessible names glued from fragments into single templates: Now Playing, Books, Weather, Backup, the Connections map key and the add-new type buttons.
  • Backup: relative times come from Intl.RelativeTimeFormat instead of hand-written English, the card reads "Last {when}" / "Next {when}" as one message, and job states are translated in the label.
  • Translate Docker container states in badge reasons when the daemon sends no status text.
  • Mark each language picker option, and the button showing it, with lang (WCAG 2.2 SC 3.1.2).
  • Translate data.js options that carry labelKey on /api/widget-options through the widget catalog; System Summary's "All interfaces" uses it.
  • Canonicalise the clock's language tag so a malformed tag falls back instead of throwing.
  • Split Connections ui.online so the map status and the peer count no longer share one string.

Testing
All green, Docker build and e2e included. Added tests for widget plurals, list and relative-time formatting, option labels, the language picker, and a guard against === 1 plurals and glued translated text.

Changelog

Fixed

  • Counts in search, badges and widgets follow the plural rules of the selected language.
  • Backup, Now Playing, Books, Weather and Connections read their labels in the selected language's word order.
  • Backup shows run times in the selected language.
  • Lists use the selected language's separators.
  • The language picker marks each language name with its language for screen readers.
  • System Summary translates "All interfaces" and badges translate container states.

Checklist

  • Stays within the project constraints: one container, no runtime dependencies, no build step (see CONTRIBUTING.md).
  • Tests added or updated for new logic, and the full suite, lint, and typechecks pass.
  • Docs updated if behavior or configuration changed.

Counted strings take the language's CLDR plural category, sentences built
from translated fragments become single catalog messages, lists use
Intl.ListFormat, Backup ages use Intl.RelativeTimeFormat, and the language
picker marks each name with its language.
@SandObserver SandObserver added the bug Something isn't working label Oct 15, 2026
@SandObserver
SandObserver merged commit 3449a36 into main Oct 16, 2026
6 checks passed
@SandObserver
SandObserver deleted the fix/i18n-plurals-and-language-tags branch October 16, 2026 01:38
stackyard-release Bot pushed a commit that referenced this pull request Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant