Existing accounts inherited the company language at creation time and there was no way to change UI language per user. Add a 'Default (Company Language)' entry to the language selector in UserGeneralView, persist the choice through userStore.updateUserSettings and reload the i18n bundle via window.loadLanguage. The 'default' sentinel keeps the user opted in to the company-wide setting.
Bootstrap (global.store) now syncs userForm from current_user data and resolves the active UI language as user > company > 'en'. RegisterController, InvitationRegistrationController and MemberService seed new users with language=default instead of copying the current company setting, so promoting/inviting members no longer leaks the inviter's frozen language.
fetchBasicMailConfig() was calling the wrong endpoint (company-config
instead of default config). Also, the response has no .data wrapper so
from_mail was never extracted. Fixed in all three send modals.
Estimate and payment preview blob construction now falls back to the
raw response when .data is undefined, matching the invoice modal.
Rewrite all 7 global stores from JS options API to TypeScript
composition API. 8 files, 1005 lines, zero any types.
- auth.store.ts: login/logout with authService
- global.store.ts: bootstrap, menus, sidebar, config fetching
- company.store.ts: company selection, admin mode, settings
- user.store.ts: current user, abilities, settings
- notification.store.ts: typed toast notifications
- dialog.store.ts: confirm dialog returning Promise<boolean>
- modal.store.ts: modal state with isEdit getter
All use async/await, typed API services, localStore utility,
and explicit ref<T> generics.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>