feat(i18n): add Spanish locale with full EN/ES translations#9635
feat(i18n): add Spanish locale with full EN/ES translations#9635dfliess wants to merge 12 commits into
Conversation
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.
AdityaHegde
left a comment
There was a problem hiding this comment.
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.
…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
|
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. |
AdityaHegde
left a comment
There was a problem hiding this comment.
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.
| Allow existing and new Rill users with a <b>@{$userDomain.data}</b> | ||
| email address to join this project as a <b>Viewer</b>. | ||
| {@html m.common_allow_domain_join_project({ | ||
| domain: `<b>@${$userDomain.data}</b>`, |
There was a problem hiding this comment.
Missing htmlEscape similar to other places.
There was a problem hiding this comment.
Done, added escapeHtml here (and to the role param and the few remaining interpolations inside {@html} params across the PR, for consistency).
| Allow existing and new Rill users with a <b>@{$userDomain.data}</b> | ||
| email address to join this org as a <b>Viewer</b>. | ||
| {@html m.settings_allow_domain_description({ | ||
| domain: `<b>@${$userDomain.data}</b>`, |
There was a problem hiding this comment.
Another instance of missing html escape.
…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
|
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. |
Adds Spanish (ES) as a second locale to Rill, building on the Paraglide scaffolding from #9570.
What's included
es.jsonwith ~1,740 keys, full parity withen.jsondocument-locale,luxon-locale,normalize-locale,escape-html, catalog integrity testpreferred_localecolumn, migration 0096, proto field, API handler); on next login the saved locale is applied automaticallyHow it works
localStorage→preferredLanguage→baseLocale(web-admin);preferredLanguage→baseLocale(web-local)UpdateUserPreferencesto save the choice+layout.tsreadspreferredLocalefromGetCurrentUserand applies it viasetLocale@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