feat: add project-wide i18n support - #209
Conversation
|
There were a lot of files changed, very hard to look at everything, but in general looks fine from my point of view. Don't forget to add docstrings and specify which files you said were incorrectly merged |
Remove EN/DE keys with no frontend or backend references to shrink catalogs and reduce unused-key noise.
Rename setting:/users: to settingLabel/usersLabel for scanner-friendly keys, and remove unused modalTitle props that BasicCoordinator no longer accepts.
Pass localized copy/download/send labels via tooltip so icon-only buttons do not render title as visible text over the skill name.
Replace plain Error("ns.key") with TranslatableError so socket/HTTP errors go through the typed i18n path instead of legacy message keys.
9a1f7fa to
c201eaf
Compare
| return result; | ||
| } | ||
|
|
||
| function loadTranslations() { |
There was a problem hiding this comment.
flattenObject, interpolate, and hasKey are already implemented in utils/modules/i18n/index.js, the shared module this PR adds. Use it directly instead: const { t, hasKey, messages } = require('../../utils/modules/i18n');.
There was a problem hiding this comment.
Agreed, the duplication is real.
This split came from TPSE: shared JSON catalogs, frontend via Vite/ESM (i18n-bundles.js), backend via fs in backend/utils/i18n.js. utils/modules/i18n/index.js looks like an intended shared entry, but Node can’t require it as is because en/index.js is ESM, so the backend helper stayed separate. I’m not sure whether that was intentional or leftover.
Unifying the helpers needs a small refactor. I’d keep this PR on finishing the i18n port and track that in #273, unless you want it in scope here.
| return; | ||
| } | ||
|
|
||
| const systemSetting = await Setting.findOne({ |
There was a problem hiding this comment.
i think this should use the MetaModel.getByKey instead of findOne directly.
|
|
||
| .. code-block:: javascript | ||
|
|
||
| const { TranslatableError } = require("../utils/TranslatableError"); |
There was a problem hiding this comment.
I think the brackets { TranslatableError } here will cause the import to be deconstructed which will cause the direct class export of TranslatableError.js:75 to be deconstructed which will return undefined and cause a TypeError when instantiated with new ...
As far as i can tell the import is done correctly in the actual code, but here in the docs the { } brackets are added.
Summary
Adds UI internationalization (English + German): shared locale JSON,
vue-i18non the frontend, i18n error keys on the backend, and per-user UI language stored in the DB.Also fixes #251 (users could override protected system settings via
appSettingSet) and implements #250 (optional restriction of language selection per role).Changes
utils/modules/i18n/— EN/DE catalogs;i18n-bundles.jsbundles namespaces forvue-i18n(renamed frommessages.js); backend uses catalogs for logs.$t/i18n-t,resolveApiMessage,translateMaybeKey,formatLocalized*for datesTranslatableError, structured{ key, params }in socket responsestranslateMaybeKeyinbackend/utils/i18n.jsapp.localeinsetting(default) +user_setting(per user); logged-in users read mergedappSettingsfrom server, withlocalStorage(locale) until settings load, fallbacken; auth pages use browser language and clear cache when logged out; save via Preferences →appSettingSet+ cache;App.vueapplies locale onappSettings; helpers inlocale.js+utils.jsdocs/source/for_developers/i18n.rstwith developer patterns anddocs/source/for_researchers/interface_language.rstfor researchersOut of scope
Not fully done in this branch:
SetupWizard,components/wizard/*)RoleManagementModal, …)utils/modules/i18n/index.jsandbackend/utils/i18n.js— works as-is, duplication only in helper code#250 — Restrict language selection
New right:
frontend.preferences.disableLanguageSelection(default on Guest).app.localeviaappSettingSet(non-admin)#251 — Security: system settings override
Users could write any key to
user_settingand shadow systemsettingvalues.setting.allowUserOverride(defaultfalse;trueonly for allowed keys likeapp.locale,projects.default, …)user_settingbeforeCreate / beforeUpdate hooks reject protected keysbypassSystemSettingCheckwhen setting prefs for users