Skip to content

feat(i18n): add Russian locale - #226

Merged
stefan-ernst merged 10 commits into
Windshiftapp:mainfrom
oshuej198:feat/russian-locale
Aug 31, 2026
Merged

feat(i18n): add Russian locale#226
stefan-ernst merged 10 commits into
Windshiftapp:mainfrom
oshuej198:feat/russian-locale

Conversation

@oshuej198

@oshuej198 oshuej198 commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

A quick note on the scope: this PR ended up doing a little more than simply adding Russian translation files.

In addition to the Russian locale with 100% key coverage, it also:

  • adds Russian to the initial setup and profile language selectors;
  • persists the selected language for the administrator created during setup;
  • applies language changes immediately after saving profile settings;
  • localizes pre-auth loading and onboarding screens;
  • localizes built-in seeded values such as the default workflow, screen, configuration, statuses, priorities, item types, and themes without modifying the stored data;
  • improves navigation and tab layouts for longer translated labels;
  • adds automated checks for locale key parity, placeholder parity, untranslated carryovers, and hardcoded English copy on migrated screens.

The Russian translation has been reviewed manually by a native speaker, including terminology and UI fit.

Validation completed successfully:

  • npm run check
  • npm run typecheck
  • npm run build

@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@oshuej198

Copy link
Copy Markdown
Contributor Author

I have read the CLA Document and I hereby sign the CLA

github-actions Bot added a commit that referenced this pull request Aug 28, 2026
@oshuej198 oshuej198 changed the title feat(i18n): add Russian locale WIP: feat(i18n): add Russian locale Aug 28, 2026
@stefan-ernst

Copy link
Copy Markdown
Contributor

Hi @oshuej198 - wow big change!
It looks good mainly but a couple of issues have arrived with the large change surface:

  1. ConfigurationSetManager.svelte:497 - the generic warning at line 497 hides the specific warnings that were previously returned (should be an easy fix)
  2. The setup assistant language selector is mentioned but not implemented. I would suggest having a new welcome screen with a simple language selector before showing the admin data input. If you want, we can scope this out of this PR
  3. App.svelte:306 - this will not work as the translations are lazy loaded, so the commons key will be displayed instead of loading
  4. UserProfile.svelte:222 - again, backend errors get shadowed, just like in ConfigurationSetManager.svelte
  5. This is one is the most important one: There are several system defaults (fields etc) now duplicated in the frontend in order to provide a stable key for translation. This can easily drift and also bloats the frontend code. In order to implement this properly, we should change the system fields tables with an immutable system_key/builtin_key column.

@github-actions

Copy link
Copy Markdown

This PR has merge conflicts that need to be resolved before it can be merged. Please rebase on the latest main branch.

@oshuej198 oshuej198 changed the title WIP: feat(i18n): add Russian locale feat(i18n): add Russian locale Aug 29, 2026
…/russian-locale

# Conflicts:
#	frontend/src/lib/jira-import/SystemImportPage.svelte
#	frontend/src/lib/layout/DashboardCustomizationSidebar.svelte
#	frontend/src/lib/locales/ar/index.js
#	frontend/src/lib/locales/de/index.js
#	frontend/src/lib/locales/en/index.js
#	frontend/src/lib/locales/es/index.js
#	frontend/src/lib/locales/pt-BR/index.js
#	frontend/src/lib/locales/zh-CN/index.js
#	frontend/src/lib/pages/Homepage.svelte
#	frontend/src/lib/services/dashboardWidgetRegistry.js
#	frontend/src/lib/stores/homepageStore.svelte.js
#	frontend/src/lib/stores/i18n-utils.spec.js
#	frontend/src/lib/widgets/dashboard/AssignedToMeWidget.svelte
#	frontend/src/lib/widgets/dashboard/DailyBriefingWidget.svelte
#	frontend/src/lib/widgets/dashboard/DashboardItemRow.svelte
#	frontend/src/lib/widgets/dashboard/PersonalTasksWidget.svelte
#	frontend/src/lib/widgets/dashboard/QuickAccessWidget.svelte
#	frontend/src/lib/widgets/dashboard/RecentWorkspacesWidget.svelte
#	frontend/src/lib/widgets/dashboard/UpcomingMilestonesWidget.svelte
#	frontend/src/lib/widgets/dashboard/WatchedItemsWidget.svelte
#	frontend/src/lib/widgets/dashboard/WhatsNewWidget.svelte
#	frontend/src/lib/widgets/dashboard/YourActivityWidget.svelte
@github-actions

Copy link
Copy Markdown

Merge conflicts have been resolved.

@github-actions github-actions Bot removed the conflict label Aug 29, 2026
@oshuej198

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review — I’ve addressed all five points in 2e27c17 and then merged the latest main in 5bd4f41.

  1. ConfigurationSetManager.svelte: the import flow now surfaces each specific warning returned by the backend instead of replacing them with a generic localized warning.

  2. Setup assistant: added a dedicated language-selection screen before the administrator details. The selected language is applied to the UI immediately, included in the setup payload, and persisted for the newly created administrator.

  3. App.svelte: the startup loader no longer attempts to resolve translation keys before the lazy locale bundle is ready. It uses a neutral loading label until i18n.init() completes and switches to translated labels afterwards.

  4. UserProfile.svelte: agent creation now preserves the backend-provided error message. The localized generic error is used only as a fallback when the backend does not provide a specific reason.

  5. System defaults: removed the frontend mappings based on duplicated names and descriptions. The relevant built-in tables now have backend-owned stable builtin_key columns for both SQLite and PostgreSQL. Existing installations are backfilled by a migration, new databases receive the keys from their seed data, and partial unique indexes protect their identity. The APIs expose these keys, while the frontend translates built-in records by key and falls back to the stored name for custom records.

The builtin_key values are populated by schema seeds/migrations and are not changed through the user-facing CRUD flows.

I also merged the latest main and resolved the conflict. Validation after the merge is green locally:

  • npm run typecheck
  • npm run check
  • npm run build
  • npm run test:run — 33 tests passed
  • go test ./...

The remaining GitHub Actions workflows are currently waiting for maintainer approval.

Thanks again for identifying these issues. Please let me know if you would prefer any part of the backend identifier migration to be split into a separate PR.

@stefan-ernst

stefan-ernst commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Thanks, the original five concerns are mostly addressed, especially the backend-owned builtin_key work and the setup language step. I re-reviewed the current head and found two remaining blockers:

  1. The App.svelte lazy-i18n issue is only partially fixed. i18nReady now gates the loader labels, but the startup catch path and startup error markup still call t(). If i18n.init() itself times out or the locale chunk cannot load, there is no catalog available, so the recovery screen renders literal keys such as errors.failedToLoad, errors.TIMEOUT, errors.NETWORK_ERROR, and common.retry. The full App startup tests reproduce both the offline and stalled-locale cases. All UI reachable before i18nReady, including the recovery path and skip link, needs an eager/static fallback.

  2. ItemTypeManager now drops the backend error detail (this is similar to the two ones we already fixed)

@oshuej198

Copy link
Copy Markdown
Contributor Author

Thank you again for the careful re-review and the precise reproduction cases — they were very helpful.
I’ve addressed both remaining blockers:

  1. The startup and recovery UI no longer depends on lazy-loaded locale catalogs before i18nReady. The loading states, slow-loading message, skip link, error title/details, and retry button now have an eager static fallback. Once i18n is ready, they use the active locale as usual.
  2. ItemTypeManager now preserves backend error details for load, save, and delete operations, using localized generic messages only as fallbacks.
    I also added regression coverage verifying that the translator is not called before i18n is ready.
    Validation completed:
  • 35 unit tests
  • Svelte typecheck
  • Biome and i18n checks
  • Production build
    Please take another look when convenient. Thanks!

@stefan-ernst

Copy link
Copy Markdown
Contributor

Hey @oshuej198 thanks again! I will merged this as is

However while analysing, I found that the local translation for built-in fields is not enough as they can be renamed. I will add a separate translation feature to account for user renaming them, that makes it also possible to localize them individually at the same time. This is a bit too big to incorporate in this PR, so I will add it separately before the 0.8.8 release

Thanks again for all the work

@stefan-ernst
stefan-ernst merged commit b59efcd into Windshiftapp:main Aug 31, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants