Skip to content

feat(i18n): add Spanish locale with full EN/ES translations#9635

Merged
AdityaHegde merged 15 commits into
rilldata:mainfrom
dfliess:i18n-es-locale
Jul 9, 2026
Merged

feat(i18n): add Spanish locale with full EN/ES translations#9635
AdityaHegde merged 15 commits into
rilldata:mainfrom
dfliess:i18n-es-locale

Conversation

@dfliess

@dfliess dfliess commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Adds Spanish (ES) as a second locale to Rill, building on the Paraglide scaffolding from #9570.

What's included

  1. Spanish message cataloges.json with ~1,740 keys, full parity with en.json
  2. Localized web-common — all user-facing strings in shared components (~216 files)
  3. Localized web-admin — all user-facing strings in cloud admin (~231 files)
  4. LanguageSwitcher component — dropdown in the avatar menu to switch EN/ES, with spec and fixtures
  5. Locale utilitiesdocument-locale, luxon-locale, normalize-locale, escape-html, catalog integrity test
  6. User preferred locale — persists the user's language choice server-side (preferred_locale column, migration 0096, proto field, API handler); on next login the saved locale is applied automatically

How it works

  • Locale detection: localStoragepreferredLanguagebaseLocale (web-admin); preferredLanguagebaseLocale (web-local)
  • LanguageSwitcher calls UpdateUserPreferences to save the choice
  • +layout.ts reads preferredLocale from GetCurrentUser and applies it via setLocale
  • All imports use @rilldata/web-common/lib/i18n/gen/messages (matching feat: localization support #9570's structure)

Relation to #9621

This PR supersedes #9621. Rebased on current main (which includes #9570), dropped the framework scaffold (now upstream), kept only translations + language addition as requested in the review.

Test plan

  • go build ./... passes
  • Catalog integrity tests pass (key parity, no empties, parameter match, no duplicates)
  • Manual: switch locale via LanguageSwitcher in avatar menu, verify Spanish renders

Comment thread admin/database/postgres/migrations/0096.sql Outdated
Comment thread web-common/src/components/i18n/LanguageSwitcher.svelte Outdated
Comment thread web-common/src/lib/i18n/locale-utils.ts
Comment thread web-common/src/lib/i18n/__tests__/catalog-integrity.spec.ts Outdated
@dfliess dfliess requested a review from AdityaHegde July 2, 2026 09:44

@AdityaHegde AdityaHegde left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the quick set of changes. This is a massive PR so it will take time for me to fully review. Here are a few more changes needed.

Comment thread web-common/src/lib/i18n/messages/en.json Outdated
Comment thread web-common/src/lib/i18n/messages/en.json Outdated
Comment thread web-admin/src/features/projects/ProjectPage.svelte Outdated
Comment thread web-common/src/lib/i18n/messages/en.json
Comment thread web-admin/src/features/projects/settings/ProjectVisibilitySettings.svelte Outdated
Comment thread web-admin/src/features/billing/plans/dialog/CancelPlanDialog.svelte Outdated
Comment thread web-admin/src/routes/[organization]/[project]/+page.svelte Outdated
Comment thread web-common/src/features/dashboards/time-series/MetricsTimeSeriesCharts.svelte Outdated
Comment thread web-common/src/lib/time/config.ts Outdated
@nishantmonu51 nishantmonu51 added Type:Feature New feature request Size:XL Very large change: 2,000+ lines labels Jul 2, 2026
@dfliess

dfliess commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Thanks a lot for the thorough review, really appreciate the time given the size of this PR.

All comments are addressed in 66de2da. Since most of them were fidelity regressions (lost ellipses/markup/aria-labels, altered texts, flattened plurals), we also swept the entire diff for the same classes of issues and fixed ~35 more occurrences of the same patterns (shared keys flattening distinct source texts, typographic apostrophes, a couple of inline components left dangling outside their sentence, etc., grouped in the commit message). We also did a native-speaker pass over the Spanish catalog.

Happy to adjust anything or split changes out if it makes reviewing easier, glad to collaborate however works best for you.

@dfliess dfliess requested a review from AdityaHegde July 2, 2026 21:37

@AdityaHegde AdityaHegde left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks I did miss some. Splitting PRs will cause more disruptions for other PRs, so a single one is better IMO.

Also please run npm run quality:ci and fix any issues as well.

Comment thread web-admin/src/routes/[organization]/[project]/-/invite/+page.svelte Outdated
Comment thread web-admin/src/features/organizations/settings/OrgDomainAllowListSettings.svelte Outdated
@dfliess

dfliess commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Ran npm run quality:ci and fixed the two issues it caught (an unused helper left behind by the extraction and an unused import). It now passes clean, including the TypeScript whitelist check. Changes in ad97ee5.

@dfliess dfliess requested a review from AdityaHegde July 3, 2026 07:10
@dfliess

dfliess commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Small follow-up in fe6f7b4: while testing in Spanish we caught a few more hardcoded strings (the guarded delete-confirmation dialog and a couple of empty states) and localized them. The typed confirmation token (delete ) stays untranslated, same as the overwrite dialog.

@AdityaHegde

Copy link
Copy Markdown
Collaborator

Thanks @dfliess . Can you merge main and update the new components? I will merge this in a couple of days so there shouldnt be more such changes.

@dfliess

dfliess commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

Done, merged main and localized the new components (usage page + nav entry). Thanks for the heads up!

@AdityaHegde

Copy link
Copy Markdown
Collaborator

Sorry @dfliess more PRs might land in the next day. Maybe hold off for 24hrs?

dfliess added 14 commits July 8, 2026 20:19
Add es.json with full Spanish translations for all 1,733 user-facing
strings. Update inlang settings to include "es" in the locales array.
Merge Rill's existing organizations_overview_page_title key into both
catalogs.
Replace ~1,700 hard-coded English strings across shared viewer
components, features, and layout with m.key() calls backed by the
EN/ES message catalogs.
Replace hard-coded English strings across web-admin features
(projects, alerts, reports, branches, organizations, etc.) with
m.key() calls backed by the EN/ES message catalogs.
Add LanguageSwitcher dropdown component, locale utility modules
(document-locale, luxon-locale, normalize-locale, escape-html),
i18n init barrel, and catalog integrity test suite.
Add preferred_locale column (migration 0096), proto field, Go
handlers, and frontend plumbing so users can persist their language
choice via the API. On page load the +layout.ts resolver applies
the stored preference before rendering.

Proto generated files regenerated against current main.
Add canvas_tab_group, canvas_add_widget_to_tab,
canvas_add_widget_below_tabs, and edit_publish_merge_deploy_failed
to both EN and ES catalogs. These strings were introduced on main
after the original i18n branch diverged.
Address review: keep the language choice in localStorage only (paraglide
localStorage strategy) instead of persisting it on the user record. Reverts
the preferred_locale column, proto field and admin handlers, and removes the
persistLocale plumbing from LanguageSwitcher/AvatarButton and the initial
locale resolver from the web-admin layout. The manual switcher is now
cloud-only: Rill Developer keeps upstream's browser-language detection and
no longer renders LanguageSwitcher.
Address review: collapse document-locale, escape-html, luxon-locale and
normalize-locale into a single locale-utils module re-exported from the
i18n index. normalize-locale is dropped entirely: its only consumer was
the removed backend preference resolver.
Address review: move the catalog checks from a vitest spec into
scripts/i18n-guard.js and generalize them to every file under messages/:
union of keys across locales with per-file missing-key reporting, per-key
parameter superset validation, duplicate top-level keys, and empty texts.
Messages can be plain strings or variant arrays and variants are checked
for internal consistency (selectors, match branches and placeholders must
resolve to declared inputs/locals). Catalog errors are exact and now fail
the quality pipeline; the hardcoded-string heuristic stays warning-level
until --strict.
…ches

Address review: replace singular/plural key pairs and inline count
conditionals with paraglide variant messages (declarations/selectors/match,
backed by Intl.PluralRules). Converted: dimension filter chips, chat
thinking durations, project status (parse errors, tables/views, compute
units), relative time, user management counts (users, groups, members,
projects, invite/added notifications including a two-selector variant),
env var key errors, canvas color palette, pivot drag labels and pivot
error counts. This also fixes Spanish forms that were grammatically wrong
for count=1 and restores upstream singular forms the extraction had
flattened.

Also repair issues surfaced while verifying: message keys referenced but
missing from the catalogs (github connect pages, workspace onboarding,
dashboards empty state), parameter-name mismatches (billing plan renewal,
invite error notifications, logs connection error), the welcome-message
fragment, the missing second time grain, All time casing, and two
pre-existing type errors caught by tsc-with-whitelist.
…sh Spanish catalog

Review feedback:
- Convert remaining count-based messages to plural variants
  (status_levels_selected, users_already_member, users_failed_invite,
  users_failed_add_groups, users_failed_invite_users, groups_total_count)
- Restore texts changed during extraction (Enter a search term,
  Successfully invited..., lowercase user/users descriptions)
- Restore lost ellipses, aria-labels, grain capitalization and inline
  markup, injecting escaped params via {@html} where markup wraps data
- Type kindTitleMap as Record<ProjectPageKindParam, () => string>, reuse
  translateV1TimeGrain, key TIME_COMPARISON by TimeComparisonOption, and
  use alert_edit for the Edit alert trigger

Fidelity sweep over the full diff:
- Split shared keys that flattened distinct source texts (custom range,
  download PNG, search placeholders, no-results, alert/report created-by
  metadata, branch/subpath labels, learn more, loading tables, delete org
  label, filters-only switch)
- Restore typographic apostrophes, Unicode ellipsis, exact wording, and
  the interleaved GitHub user/repo inline components in retry-auth
- Localize hardcoded Viewer role params; fix duplicated Copy in
  copy-to-clipboard tooltips

Spanish catalog:
- Fix gender/number agreement and impersonal se-constructions; align
  tu/usted with each section's dominant register
- Unify terminology: dashboard (was tablero/panel), Visualizador,
  ranking, minigrafico
- Fix mistranslations and gender-dependent billing messages
…locals

- escapeHtml on the domain/role params of the domain-allowlist labels
  (review feedback), and on the remaining interpolations inside {@html}
  message params (plan name, docs links) for consistency
- remove leftover getMode helper and an unused import flagged by
  npm run quality:ci, which now passes clean
- alert-dialog-guarded-confirmation: instruction line (typed token stays
  untranslated, matching the overwrite dialog), confirmation input label,
  Cancel and default Continue button
- ProjectCards empty state and the personal canvas delete dialog
  (title, description, Delete button)
Cover the strings introduced by the upstream merge: the PDF export tab in
the share popover, the changed-files list/dialog with its status badges,
and the chat file-diff block. Promote edit_no_changes_detected to
common_no_changes_detected now that chat shares the text, and add the new
areas to the i18n-guard scan.
Localize the components added by the upstream usage page: the Usage nav
entry and page heading (reusing billing_usage_title) and the billing
portal iframe title. Drop the two keys orphaned by the removal of the
placeholder usage page.
@AdityaHegde AdityaHegde merged commit 8ca11f9 into rilldata:main Jul 9, 2026
@dfliess dfliess deleted the i18n-es-locale branch July 9, 2026 06:19
@dfliess

dfliess commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @AdityaHegde for the thorough review. Do you have a public roadmap ? I've been working on things like webhooks #9643 and would like to help with other areas.

@nishantmonu51

Copy link
Copy Markdown
Collaborator

@dfliess We don’t have a public roadmap available right now, but I’d be happy to set up a quick call to learn more about the areas you’re interested in contributing to and discuss how we can best collaborate. My email is nishant@rilldata.com, feel free to email few time slots that would work for you.

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

Labels

Size:XL Very large change: 2,000+ lines Type:Feature New feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants