-
Notifications
You must be signed in to change notification settings - Fork 13k
chore(i18n): Readapt build scripts #36960
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Looks like this PR is not ready to merge, because of the following issues:
Please fix the issues and try again If you have any trouble, please check the PR guidelines |
|
WalkthroughReplaces ts-node with tsx for Meteor Mocha runs and removes TS_NODE env injections; deletes several Meteor translation CLI scripts; removes allowJs across many tsconfigs; refactors packages/i18n (module type/exports, new scripts and shared helpers, typed normalization, CJS bridge, build changes); updates ESLint/Jest presets and many locale JSON files; adds small testunit scripts. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Dev
participant CLI as replace-sprintf.mts
participant Common as scripts/common.mts
participant FS as FileSystem
Dev->>CLI: node replace-sprintf.mts <translationKey>
CLI->>Common: getResourceLanguages()
Common-->>CLI: [languages]
CLI->>Common: readResource(baseLang)
Common-->>CLI: base JSON (validate key & tokenCount)
CLI->>Dev: Prompt for param names (if %s present)
loop For each language
CLI->>Common: readResource(lang)
Common-->>CLI: lang JSON
CLI->>FS: writeResource(lang, updated JSON with {{name}} substitutions)
end
CLI-->>Dev: Log completion or exit non-zero on error
sequenceDiagram
autonumber
actor Dev
participant Check as check.mts
participant Tasks as Task Registry
participant Common as scripts/common.mts
participant FS as FileSystem
Dev->>Check: node check.mts [--fix] [--task ...]
Check->>Tasks: resolve selected tasks
loop For each task
Check->>Common: getResourceLanguages()
Common-->>Check: [languages]
loop For each language
Check->>Common: readResource(lang)
Common-->>Check: resource JSON
alt --fix
Check->>FS: writeResource(lang, fixed JSON)
else lint-only
Check-->>Dev: emit lint findings
end
end
end
Check-->>Dev: exit success or non-zero with aggregated error count
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
84a67aa to
97490c5
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #36960 +/- ##
===========================================
+ Coverage 67.38% 67.40% +0.01%
===========================================
Files 3328 3334 +6
Lines 113342 113509 +167
Branches 20562 20612 +50
===========================================
+ Hits 76375 76507 +132
+ Misses 34363 34322 -41
- Partials 2604 2680 +76
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
0bceb66 to
b5c47a0
Compare
20a04f8 to
6537be9
Compare
da15f89 to
7943027
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/i18n/src/locales/nb.i18n.json (1)
4469-4527: Restore SAML placeholders to canonical tokens and code formattingThe SAML template strings still use Italic
_formatting and the translated__utsteder__token. These break the documented variable names and must stay as the canonical English placeholders surrounded by backticks for inline code. Please revert the localized token and apply the backtick formatting to every placeholder in these entries.- "SAML_AuthnRequest_Template_Description": "Følgende variabler er tilgjengelige: \n- *\\_\\_newId\\_\\_*: Tilfeldig generert id-streng \n- *\\_\\_instant\\_\\_*: Gjeldende tidsstempel \n- *\\_\\_callbackUrl\\_\\_*: Rocket.Chats tilbakeringings-URL. \n- *\\_\\_entryPoint\\_\\_*: Verdien for *Custom Entry Point*-innstillingen. \n- **\\_\\_utsteder\\_\\_**: Verdien for *Custom Issuer*-innstillingen. \n- *\\_\\_identifierFormatTag\\_\\_*: Innholdet i *NameID Policy Template* hvis en gyldig *Identifier Format* er konfigurert. \n- *\\_\\_identifierFormat\\_\\_*: Verdien for *Identifier Format*-innstillingen. \n- *\\_\\_authnContextTag\\_\\_*: Innholdet i *AuthnContext Template* hvis en gyldig *Custom Authn Context* er konfigurert. \n- *\\_\\_authnContextComparison\\_\\_*: Verdien for *Authn Context Comparison*-innstillingen. \n- *\\_\\_authnContext\\_\\_*: Verdien til *Custom Authn Context*-innstillingen.", + "SAML_AuthnRequest_Template_Description": "Følgende variabler er tilgjengelige: \n- `__newId__`: Tilfeldig generert id-streng \n- `__instant__`: Gjeldende tidsstempel \n- `__callbackUrl__`: Rocket.Chats tilbakeringings-URL. \n- `__entryPoint__`: Verdien for *Custom Entry Point*-innstillingen. \n- `__issuer__`: Verdien for *Custom Issuer*-innstillingen. \n- `__identifierFormatTag__`: Innholdet i *NameID Policy Template* hvis en gyldig *Identifier Format* er konfigurert. \n- `__identifierFormat__`: Verdien for *Identifier Format*-innstillingen. \n- `__authnContextTag__`: Innholdet i *AuthnContext Template* hvis en gyldig *Custom Authn Context* er konfigurert. \n- `__authnContextComparison__`: Verdien for *Authn Context Comparison*-innstillingen. \n- `__authnContext__`: Verdien til *Custom Authn Context*-innstillingen.", - "SAML_LogoutRequest_Template_Description": "Følgende variabler er tilgjengelige: \n- *\\_\\_newId\\_\\_*: Tilfeldig generert id-streng \n- *\\_\\_instant\\_\\_*: Gjeldende tidsstempel \n- *\\_\\_idpSLORedirectURL\\_\\_*: IDP Single LogOut URL det skal omdirigeres til. \n- **\\_\\_utsteder\\_\\_**: Verdien for *Custom Issuer*-innstillingen. \n- *\\_\\_identifierFormat\\_\\_*: Verdien for *Identifier Format*-innstillingen. \n- *\\_\\_nameID\\_\\_*: NameID mottatt fra IdP når brukeren logget på. \n- *\\_\\_sessionIndex\\_\\_*: SessionIndex mottatt fra IdP når brukeren logget på.", + "SAML_LogoutRequest_Template_Description": "Følgende variabler er tilgjengelige: \n- `__newId__`: Tilfeldig generert id-streng \n- `__instant__`: Gjeldende tidsstempel \n- `__idpSLORedirectURL__`: IDP Single LogOut URL det skal omdirigeres til. \n- `__issuer__`: Verdien for *Custom Issuer*-innstillingen. \n- `__identifierFormat__`: Verdien for *Identifier Format*-innstillingen. \n- `__nameID__`: NameID mottatt fra IdP når brukeren logget på. \n- `__sessionIndex__`: SessionIndex mottatt fra IdP når brukeren logget på.", - "SAML_LogoutResponse_Template_Description": "Følgende variabler er tilgjengelige: \n- *\\_\\_newId\\_\\_*: Tilfeldig generert id-streng \n- *\\_\\_inResponseToId\\_\\_*: IDen til utloggingsforespørselen mottatt fra IdP \n- *\\_\\_instant\\_\\_*: Gjeldende tidsstempel \n- *\\_\\_idpSLORedirectURL\\_\\_*: IDP Single LogOut URL det skal omdirigeres til. \n- **\\_\\_utsteder\\_\\_**: Verdien for *Custom Issuer*-innstillingen. \n- *\\_\\_identifierFormat\\_\\_*: Verdien for *Identifier Format*-innstillingen. \n- *\\_\\_nameID\\_\\_*: NameID mottatt fra IdP-utloggingsforespørselen. \n- *\\_\\_sessionIndex\\_\\_*: SessionIndex mottatt fra IdP utloggingsforespørselen.", + "SAML_LogoutResponse_Template_Description": "Følgende variabler er tilgjengelige: \n- `__newId__`: Tilfeldig generert id-streng \n- `__inResponseToId__`: IDen til utloggingsforespørselen mottatt fra IdP \n- `__instant__`: Gjeldende tidsstempel \n- `__idpSLORedirectURL__`: IDP Single LogOut URL det skal omdirigeres til. \n- `__issuer__`: Verdien for *Custom Issuer*-innstillingen. \n- `__identifierFormat__`: Verdien for *Identifier Format*-innstillingen. \n- `__nameID__`: NameID mottatt fra IdP-utloggingsforespørselen. \n- `__sessionIndex__`: SessionIndex mottatt fra IdP utloggingsforespørselen.", - "SAML_Metadata_Certificate_Template_Description": "Følgende variabler er tilgjengelige: \n- *\\_\\_certificate\\_\\_*: Det private sertifikatet for påstandskryptering.", + "SAML_Metadata_Certificate_Template_Description": "Følgende variabler er tilgjengelige: \n- `__certificate__`: Det private sertifikatet for påstandskryptering.", - "SAML_Metadata_Template_Description": "Følgende variabler er tilgjengelige: \n- *\\_\\_sloLocation\\_\\_*: Rocket.Chats Single Logout URL. \n- **\\_\\_utsteder\\_\\_**: Verdien for *Custom Issuer*-innstillingen. \n- *\\_\\_identifierFormat\\_\\_*: Verdien for *Identifier Format*-innstillingen. \n- *\\_\\_certificateTag\\_\\_*: Hvis et privat sertifikat er konfigurert, vil dette inkludere *Metadata Certificate Template*, ellers vil det bli ignorert. \n- *\\_\\_callbackUrl\\_\\_*: Rocket.Chats tilbakeringings-URL.", + "SAML_Metadata_Template_Description": "Følgende variabler er tilgjengelige: \n- `__sloLocation__`: Rocket.Chats Single Logout URL. \n- `__issuer__`: Verdien for *Custom Issuer*-innstillingen. \n- `__identifierFormat__`: Verdien for *Identifier Format*-innstillingen. \n- `__certificateTag__`: Hvis et privat sertifikat er konfigurert, vil dette inkludere *Metadata Certificate Template*, ellers vil det bli ignorert. \n- `__callbackUrl__`: Rocket.Chats tilbakeringings-URL.",packages/i18n/src/locales/sv.i18n.json (1)
4427-4487: Anpassa platshållare till kodstilEngelska originalet bytte ut Markdown-italics (
*__placeholder__*) mot kodstil (`__placeholder__`). Den svenska översättningen lämnades kvar med kursivering, så platshållarna renderas annorlunda och ser inte längre ut som kod. Uppdatera raderna nedan till backticks så att formatet matchar källan.- "SAML_AuthnRequest_Template_Description": "Följande variabler är tillgängliga: \n- *\\_\\_newId\\_\\_*: Slumpmässigt genererad id-sträng \n- *\\_\\_instant\\_\\_*: Aktuell tidsstämpel \n- *\\_\\_callbackUrl\\_\\_*: Återanrops-URL:en för Rocket.Chat. \n- *\\_\\_entryPoint\\_\\_*: Värdet för inställningen *Custom Entry Point*. \n- *\\_\\_issuer\\_\\_*: Värdet för inställningen *Custom Issuer*. \n- *\\_\\_identifierFormatTag\\_\\_*: Innehållet i *NameID Policy Template* om ett giltigt *Identifier Format* har konfigurerats. \n- *\\_\\_identifierFormat\\_\\_*: Värdet för inställningen *Identifier Format*. \n- *\\_\\_authnContextTag\\_\\_*: Innehållet i *AuthnContext Template* om en giltig *Custom Authn Context* is har konfigurerats. \n- *\\_\\_authnContextComparison\\_\\_*: Värdet för inställningen *Authn Context Comparison*. \n- *\\_\\_authnContext\\_\\_*: Värdet för inställningen *Custom Authn Context*.", + "SAML_AuthnRequest_Template_Description": "Följande variabler är tillgängliga: \n- `__newId__`: Slumpmässigt genererad id-sträng \n- `__instant__`: Aktuell tidsstämpel \n- `__callbackUrl__`: Återanrops-URL:en för Rocket.Chat. \n- `__entryPoint__`: Värdet för inställningen *Custom Entry Point*. \n- `__issuer__`: Värdet för inställningen *Custom Issuer*. \n- `__identifierFormatTag__`: Innehållet i *NameID Policy Template* om ett giltigt *Identifier Format* har konfigurerats. \n- `__identifierFormat__`: Värdet för inställningen *Identifier Format*. \n- `__authnContextTag__`: Innehållet i *AuthnContext Template* om en giltig *Custom Authn Context* har konfigurerats. \n- `__authnContextComparison__`: Värdet för inställningen *Authn Context Comparison*. \n- `__authnContext__`: Värdet för inställningen *Custom Authn Context*.", - "SAML_LogoutRequest_Template_Description": "Följande variabler är tillgängliga: \n- *\\_\\_newId\\_\\_*: Slumpmässigt genererad id-sträng \n- *\\_\\_inResponseToId\\_\\_*: Id:t för utloggningsförfrågningen som mottagits från idP \n- *\\_\\_instant\\_\\_*: Aktuell tidsstämpel \n- *\\_\\_idpSLORedirectURL\\_\\_*: identitetsintygarens URL för enkel utloggning som omdirigering ska göras till. \n- *\\_\\_issuer\\_\\_*: Värdet för inställningen *Custom Issuer*. \n- *\\_\\_identifierFormat\\_\\_*: Värdet för inställningen *Identifier Format*. \n- *\\_\\_nameID\\_\\_*: Värdet för NameID som mottogs från identitetsintygaren när användaren loggade in. \n- *\\_\\_sessionIndex\\_\\_*: Värdet för sessionIndex som mottogs från identitetsintygaren när användaren loggade in.", + "SAML_LogoutRequest_Template_Description": "Följande variabler är tillgängliga: \n- `__newId__`: Slumpmässigt genererad id-sträng \n- `__inResponseToId__`: Id:t för utloggningsförfrågningen som mottagits från idP \n- `__instant__`: Aktuell tidsstämpel \n- `__idpSLORedirectURL__`: identitetsintygarens URL för enkel utloggning som omdirigering ska göras till. \n- `__issuer__`: Värdet för inställningen *Custom Issuer*. \n- `__identifierFormat__`: Värdet för inställningen *Identifier Format*. \n- `__nameID__`: Värdet för NameID som mottogs från identitetsintygaren när användaren loggade in. \n- `__sessionIndex__`: Värdet för sessionIndex som mottogs från identitetsintygaren när användaren loggade in.", - "SAML_LogoutResponse_Template_Description": "Följande variabler är tillgängliga: \n- *\\_\\_newId\\_\\_*: Slumpmässigt genererad id-sträng \n- *\\_\\_inResponseToId\\_\\_*: Id:t för utloggningsförfrågningen som mottagits från idP \n- *\\_\\_instant\\_\\_*: Aktuell tidsstämpel \n- *\\_\\_idpSLORedirectURL\\_\\_*: IdP URL för Single LogOut som omdirigering ska göras till. \n- *\\_\\_issuer\\_\\_*: Värdet för inställningen *Custom Issuer*. \n- *\\_\\_identifierFormat\\_\\_*: Värdet för inställningen *Identifier Format*. \n- *\\_\\_nameID\\_\\_*: NameID som mottas från idP Logout Request. \n- *\\_\\_sessionIndex\\_\\_*: sessionsIndex som mottas från idP Logout Request", + "SAML_LogoutResponse_Template_Description": "Följande variabler är tillgängliga: \n- `__newId__`: Slumpmässigt genererad id-sträng \n- `__inResponseToId__`: Id:t för utloggningsförfrågningen som mottagits från idP \n- `__instant__`: Aktuell tidsstämpel \n- `__idpSLORedirectURL__`: IdP URL för Single LogOut som omdirigering ska göras till. \n- `__issuer__`: Värdet för inställningen *Custom Issuer*. \n- `__identifierFormat__`: Värdet för inställningen *Identifier Format*. \n- `__nameID__`: NameID som mottas från idP Logout Request. \n- `__sessionIndex__`: sessionsIndex som mottas från idP Logout Request", - "SAML_Metadata_Certificate_Template_Description": "Följande variabler är tillgängliga: \n- *\\_\\_certificate\\_\\_*: Det privata certifikatet för verifieringskryptering.", + "SAML_Metadata_Certificate_Template_Description": "Följande variabler är tillgängliga: \n- `__certificate__`: Det privata certifikatet för verifieringskryptering.", - "SAML_Metadata_Template_Description": "Följande variabler är tillgängliga: \n- *\\_\\_sloLocation\\_\\_*: URL för enkel utloggning för Rocket.Chat. \n- *\\_\\_issuer\\_\\_*: Värdet för inställningen *Custom Issuer*. \n- *\\_\\_identifierFormat\\_\\_*: Värdet för inställningen *Identifier Format*. \n- *\\_\\_certificateTag\\_\\_*: Om ett privat certifikat har konfigurerats ska det innehålla *Metadata Certificate Template*, annars ignoreras det. \n- *\\_\\_callbackUrl\\_\\_*: Återanrops-URL för Rocket.Chat.", + "SAML_Metadata_Template_Description": "Följande variabler är tillgängliga: \n- `__sloLocation__`: URL för enkel utloggning för Rocket.Chat. \n- `__issuer__`: Värdet för inställningen *Custom Issuer*. \n- `__identifierFormat__`: Värdet för inställningen *Identifier Format*. \n- `__certificateTag__`: Om ett privat certifikat har konfigurerats ska det innehålla *Metadata Certificate Template*, annars ignoreras det. \n- `__callbackUrl__`: Återanrops-URL för Rocket.Chat.",Glöm inte att uppdatera samtliga platshållare i samma stil.
🧹 Nitpick comments (2)
packages/i18n/src/locales/hu.i18n.json (2)
3443-3443: Use code-style backticks for SAML template tokens (replace italic + escaped underscores).Current strings wrap variables like newId, instant, etc. with asterisks and escaped underscores (e.g., "\\newId\\"). For consistency and readability across locales and renderers, prefer code-style markers:
__newId__,__instant__, etc. This avoids heavy escaping and aligns with the “code-style markers” normalization mentioned elsewhere in the PR.Please update all SAML template description lists in these entries to use backticks for the token names:
- Line 3443 (SAML_AuthnContext_Template_Description):
__authnContext__- Line 3445 (SAML_AuthnRequest_Template_Description): all listed tokens
- Line 3449 (SAML_Custom_Authn_Context_description): reference to the template tokens
- Line 3494 (SAML_LogoutRequest_Template_Description): all listed tokens
- Line 3496 (SAML_LogoutResponse_Template_Description): all listed tokens
- Line 3498 (SAML_Metadata_Certificate_Template_Description):
__certificate__- Line 3500 (SAML_Metadata_Template_Description):
__sloLocation__,__issuer__,__identifierFormat__,__certificateTag__,__callbackUrl__Example transformation (apply similarly to the others):
- from: - \\newId\\: …
- to: -
__newId__: …Also applies to: 3445-3445, 3449-3449, 3494-3494, 3496-3496, 3498-3498, 3500-3500
3498-3498: Fix terminology and formatting for certificate token.The metadata includes a public certificate; “személyes tanúsítvány” is misleading. Also switch token to code-style.
Apply:
- "SAML_Metadata_Certificate_Template_Description": "A következő változók érhetők el: \n- *\\_\\_certificate\\_\\_*: a személyes tanúsítvány a helyességi feltétel titkosításához.", + "SAML_Metadata_Certificate_Template_Description": "A következő változók érhetők el: \n- `__certificate__`: a tanúsítvány a helyességi feltétel aláírásához/titkosításához."
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (92)
apps/meteor/.mocharc.base.json(1 hunks)apps/meteor/.mocharc.definition.js(0 hunks)apps/meteor/.mocharc.js(0 hunks)apps/meteor/.scripts/replaceTranslationSprintfParams.ts(0 hunks)apps/meteor/.scripts/translation-check.ts(0 hunks)apps/meteor/.scripts/translation-diff.ts(0 hunks)apps/meteor/.scripts/translation-fix-order.ts(0 hunks)apps/meteor/package.json(2 hunks)ee/apps/account-service/tsconfig.json(0 hunks)ee/apps/authorization-service/tsconfig.json(0 hunks)ee/apps/ddp-streamer/tsconfig.json(0 hunks)ee/apps/omnichannel-transcript/tsconfig.json(0 hunks)ee/apps/presence-service/tsconfig.json(0 hunks)ee/apps/queue-worker/tsconfig.json(0 hunks)ee/apps/stream-hub-service/tsconfig.json(0 hunks)packages/base64/package.json(1 hunks)packages/base64/tsconfig.json(0 hunks)packages/eslint-config/standard/index.js(3 hunks)packages/i18n/jest.config.ts(0 hunks)packages/i18n/package.json(1 hunks)packages/i18n/src/index.cts(1 hunks)packages/i18n/src/index.ts(2 hunks)packages/i18n/src/locales/ar.i18n.json(3 hunks)packages/i18n/src/locales/az.i18n.json(0 hunks)packages/i18n/src/locales/bn-BD.i18n.json(1 hunks)packages/i18n/src/locales/ca.i18n.json(2 hunks)packages/i18n/src/locales/cs.i18n.json(2 hunks)packages/i18n/src/locales/da.i18n.json(2 hunks)packages/i18n/src/locales/de-AT.i18n.json(0 hunks)packages/i18n/src/locales/de.i18n.json(4 hunks)packages/i18n/src/locales/el.i18n.json(0 hunks)packages/i18n/src/locales/en.i18n.json(5 hunks)packages/i18n/src/locales/eo.i18n.json(0 hunks)packages/i18n/src/locales/es.i18n.json(4 hunks)packages/i18n/src/locales/fa.i18n.json(1 hunks)packages/i18n/src/locales/fi.i18n.json(3 hunks)packages/i18n/src/locales/fr.i18n.json(3 hunks)packages/i18n/src/locales/he.i18n.json(0 hunks)packages/i18n/src/locales/hi-IN.i18n.json(11 hunks)packages/i18n/src/locales/hr.i18n.json(0 hunks)packages/i18n/src/locales/hu.i18n.json(2 hunks)packages/i18n/src/locales/id.i18n.json(0 hunks)packages/i18n/src/locales/it.i18n.json(1 hunks)packages/i18n/src/locales/ja.i18n.json(3 hunks)packages/i18n/src/locales/ka-GE.i18n.json(5 hunks)packages/i18n/src/locales/km.i18n.json(0 hunks)packages/i18n/src/locales/ko.i18n.json(3 hunks)packages/i18n/src/locales/ku.i18n.json(0 hunks)packages/i18n/src/locales/lo.i18n.json(0 hunks)packages/i18n/src/locales/lt.i18n.json(0 hunks)packages/i18n/src/locales/lv.i18n.json(6 hunks)packages/i18n/src/locales/mn.i18n.json(3 hunks)packages/i18n/src/locales/ms-MY.i18n.json(2 hunks)packages/i18n/src/locales/nb.i18n.json(4 hunks)packages/i18n/src/locales/nl.i18n.json(3 hunks)packages/i18n/src/locales/nn.i18n.json(3 hunks)packages/i18n/src/locales/pl.i18n.json(3 hunks)packages/i18n/src/locales/pt-BR.i18n.json(4 hunks)packages/i18n/src/locales/pt.i18n.json(0 hunks)packages/i18n/src/locales/ro.i18n.json(0 hunks)packages/i18n/src/locales/ru.i18n.json(2 hunks)packages/i18n/src/locales/sk-SK.i18n.json(0 hunks)packages/i18n/src/locales/sl-SI.i18n.json(0 hunks)packages/i18n/src/locales/sq.i18n.json(0 hunks)packages/i18n/src/locales/sr.i18n.json(0 hunks)packages/i18n/src/locales/sv.i18n.json(4 hunks)packages/i18n/src/locales/ta-IN.i18n.json(1 hunks)packages/i18n/src/locales/th-TH.i18n.json(0 hunks)packages/i18n/src/locales/tr.i18n.json(0 hunks)packages/i18n/src/locales/ug.i18n.json(0 hunks)packages/i18n/src/locales/uk.i18n.json(1 hunks)packages/i18n/src/locales/vi-VN.i18n.json(0 hunks)packages/i18n/src/locales/zh-HK.i18n.json(2 hunks)packages/i18n/src/locales/zh-TW.i18n.json(4 hunks)packages/i18n/src/locales/zh.i18n.json(3 hunks)packages/i18n/src/scripts/build.mts(5 hunks)packages/i18n/src/scripts/check.mts(1 hunks)packages/i18n/src/scripts/common.mts(1 hunks)packages/i18n/src/scripts/normalize.mts(3 hunks)packages/i18n/src/scripts/normalize.spec.ts(1 hunks)packages/i18n/src/scripts/replace-sprintf.mts(1 hunks)packages/i18n/tsconfig.build.json(1 hunks)packages/i18n/tsconfig.cjs.json(0 hunks)packages/i18n/tsconfig.esm.json(0 hunks)packages/i18n/tsconfig.json(1 hunks)packages/jest-presets/package.json(1 hunks)packages/jest-presets/src/client/index.ts(1 hunks)packages/jest-presets/tsconfig.json(1 hunks)packages/random/package.json(1 hunks)packages/random/tsconfig.json(0 hunks)packages/sha256/package.json(1 hunks)packages/sha256/tsconfig.json(0 hunks)
💤 Files with no reviewable changes (40)
- ee/apps/ddp-streamer/tsconfig.json
- packages/random/tsconfig.json
- ee/apps/omnichannel-transcript/tsconfig.json
- ee/apps/authorization-service/tsconfig.json
- packages/i18n/src/locales/he.i18n.json
- packages/i18n/src/locales/eo.i18n.json
- ee/apps/queue-worker/tsconfig.json
- apps/meteor/.scripts/translation-check.ts
- packages/i18n/src/locales/ku.i18n.json
- packages/i18n/src/locales/ro.i18n.json
- packages/i18n/src/locales/tr.i18n.json
- packages/i18n/src/locales/pt.i18n.json
- packages/i18n/src/locales/lt.i18n.json
- packages/i18n/src/locales/id.i18n.json
- packages/i18n/jest.config.ts
- packages/i18n/src/locales/km.i18n.json
- packages/i18n/src/locales/th-TH.i18n.json
- ee/apps/stream-hub-service/tsconfig.json
- packages/i18n/src/locales/sl-SI.i18n.json
- apps/meteor/.mocharc.definition.js
- packages/i18n/src/locales/de-AT.i18n.json
- packages/i18n/src/locales/sq.i18n.json
- packages/i18n/src/locales/el.i18n.json
- packages/i18n/src/locales/ug.i18n.json
- packages/i18n/src/locales/hr.i18n.json
- packages/i18n/src/locales/az.i18n.json
- ee/apps/account-service/tsconfig.json
- packages/i18n/src/locales/lo.i18n.json
- apps/meteor/.scripts/translation-diff.ts
- packages/i18n/src/locales/sk-SK.i18n.json
- packages/sha256/tsconfig.json
- packages/i18n/src/locales/sr.i18n.json
- packages/base64/tsconfig.json
- packages/i18n/tsconfig.esm.json
- packages/i18n/src/locales/vi-VN.i18n.json
- apps/meteor/.scripts/translation-fix-order.ts
- apps/meteor/.scripts/replaceTranslationSprintfParams.ts
- apps/meteor/.mocharc.js
- ee/apps/presence-service/tsconfig.json
- packages/i18n/tsconfig.cjs.json
🚧 Files skipped from review as they are similar to previous changes (22)
- packages/random/package.json
- packages/i18n/tsconfig.json
- packages/base64/package.json
- packages/i18n/src/locales/ta-IN.i18n.json
- packages/sha256/package.json
- packages/eslint-config/standard/index.js
- packages/i18n/src/locales/bn-BD.i18n.json
- apps/meteor/.mocharc.base.json
- packages/i18n/src/scripts/common.mts
- packages/i18n/src/scripts/replace-sprintf.mts
- packages/i18n/src/locales/mn.i18n.json
- packages/i18n/src/scripts/normalize.spec.ts
- packages/i18n/src/locales/en.i18n.json
- packages/i18n/src/locales/da.i18n.json
- packages/i18n/src/locales/ja.i18n.json
- packages/jest-presets/package.json
- packages/i18n/src/locales/nl.i18n.json
- packages/i18n/src/locales/fi.i18n.json
- apps/meteor/package.json
- packages/i18n/src/locales/uk.i18n.json
- packages/jest-presets/src/client/index.ts
- packages/i18n/src/locales/cs.i18n.json
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,tsx,js,jsx} : Write concise, technical TypeScript/JavaScript with accurate typing
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,tsx,js,jsx} : Avoid code comments in the implementation
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure a clean state for each test execution
🧬 Code graph analysis (3)
packages/i18n/src/scripts/check.mts (1)
packages/i18n/src/scripts/common.mts (6)
readResource(28-34)baseLanguage(7-7)writeResource(36-39)getResourceLanguages(9-12)getLanguagePlurals(14-22)readContent(24-26)
packages/i18n/src/index.ts (1)
apps/meteor/app/utils/lib/i18n.ts (1)
i18n(5-5)
packages/i18n/src/scripts/build.mts (2)
packages/i18n/src/scripts/common.mts (4)
resourcesDirectory(42-42)languageFromBasename(46-46)distDirectory(43-43)resourceBasename(45-45)packages/i18n/src/scripts/normalize.mts (1)
normalizeI18nInterpolations(93-107)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: 📦 Build Packages
- GitHub Check: CodeQL-Build
- GitHub Check: CodeQL-Build
🔇 Additional comments (16)
packages/i18n/src/locales/fa.i18n.json (1)
363-364: Localized placeholder looks goodSwitching to the
{{price}}placeholder keeps the string consistent with other locales while fixing the old Markdown-style markup. Looks correct.packages/i18n/src/locales/ar.i18n.json (1)
3180-3180: Restore the missing closing backtickThe placeholder
__authnContext__lacks its terminating backtick, so everything afterward renders as code. Please add the closing ``` to fix the markup.packages/i18n/src/locales/pt-BR.i18n.json (1)
4395-4398: Fix typo in Authn context description.Ainda aparece “authn contex” (faltando o “to” e sem concordância) em vez de “contexto de autenticação”. Segue correção sugerida.
- "SAML_Custom_Authn_Context_description": "Deixe vazio para omitir o authn contex da solicitação. \n \nPara adicionar vários authn contexts, inclua os adicionais diretamente à configuração *AuthnContext Template*.", + "SAML_Custom_Authn_Context_description": "Deixe vazio para omitir o contexto de autenticação (authn) da solicitação. \n \nPara adicionar vários contextos de autenticação, inclua-os diretamente na configuração “AuthnContext Template”.",packages/i18n/src/locales/nn.i18n.json (1)
4281-4281: Keep placeholders unescaped in translated strings.The SMS example still renders as
\{\{SERVER_URL\}\}; drop the backslashes so the UI shows{{SERVER_URL}}. Same for the department placeholder.Apply:
- "Hvis angitt, vil alle nye innkommende chatter initiert av denne integrasjonen bli rutet til denne avdelingen. \nDenne innstillingen kan overskrives ved å sende avdelingsspørringsparameter i forespørselen. \nf.eks. `https://\{\{SERVER_URL\}\}/api/v1/livechat/sms-incoming/twilio?department=\{\{Department Id or Name\}\}`. \nMerk: Hvis du bruker Avdelingsnavn, bør det være URL-sikkert.", + "Hvis angitt, vil alle nye innkommende chatter initiert av denne integrasjonen bli rutet til denne avdelingen. \nDenne innstillingen kan overskrives ved å sende avdelingsspørringsparameter i forespørselen. \nf.eks. `https://{{SERVER_URL}}/api/v1/livechat/sms-incoming/twilio?department={{Department Id or Name}}`. \nMerk: Hvis du bruker Avdelingsnavn, bør det være URL-sikkert.",packages/i18n/src/locales/ko.i18n.json (1)
2782-2782: Remove the extra escaping in the SMS URL exampleThe sample URL is still rendered with backslashes (
https://\{\{SERVER_URL\}\}/…), which is confusing for admins. Please drop the redundant escapes so the placeholder shows up as{{…}}.- "SMS_Default_Omnichannel_Department_Description": "설정하면 이 통합으로 시작된 모든 새로운 수신 채팅이 이 부서로 라우팅됩니다. \n요청에서 부서 쿼리 매개 변수를 전달하여 이 설정을 덮어쓸 수 있습니다. \n예: `https://\\{\\{SERVER_URL\\}\\}/api/v1/livechat/sms-incoming/twilio?department=\\{\\{Department Id or Name\\}\\}`. \n참고: 부서 이름을 사용하는 경우 URL에 안전해야 합니다.", + "SMS_Default_Omnichannel_Department_Description": "설정하면 이 통합으로 시작된 모든 새로운 수신 채팅이 이 부서로 라우팅됩니다. \n요청에서 부서 쿼리 매개 변수를 전달하여 이 설정을 덮어쓸 수 있습니다. \n예: `https://{{SERVER_URL}}/api/v1/livechat/sms-incoming/twilio?department={{Department Id or Name}}`. \n참고: 부서 이름을 사용하는 경우 URL에 안전해야 합니다.",packages/i18n/src/locales/de.i18n.json (1)
4488-4488: Restore{{at}}placeholder inVoip_call_started.The placeholder is still missing, so the UI drops the call timestamp. Please restore
{{at}}to keep the dynamic value.packages/i18n/src/locales/fr.i18n.json (1)
3227-3227: Fix the lingering “identificationt” typo.The wording still reads “Chaîne d'identificationt générée aléatoirement”; please drop the trailing “t” so the sentence is grammatically correct.
-"SAML_LogoutRequest_Template_Description": "Les variables suivantes sont disponibles : \n- *__newId__* : Chaîne d'identificationt générée aléatoirement \n- *__instant__* : Horodatage actuel \n- *__idpSLORedirectURL__* : URL de déconnexion unique IDP vers laquelle effectuer la redirection. \n- *__issuer__* : Valeur du paramètre *Custom Issuer*. \n- *__identifierFormat__* : Valeur du paramètre *Identifier Format*. \n- *__nameID__* : NameID reçu de l'IdP lorsque l'utilisateur s'est connecté. \n- *__sessionIndex__* : SessionIndex reçu de l'IdP lorsque l'utilisateur s'est connecté.", +"SAML_LogoutRequest_Template_Description": "Les variables suivantes sont disponibles : \n- *__newId__* : Chaîne d'identification générée aléatoirement \n- *__instant__* : Horodatage actuel \n- *__idpSLORedirectURL__* : URL de déconnexion unique IDP vers laquelle effectuer la redirection. \n- *__issuer__* : Valeur du paramètre *Custom Issuer*. \n- *__identifierFormat__* : Valeur du paramètre *Identifier Format*. \n- *__nameID__* : NameID reçu de l'IdP lorsque l'utilisateur s'est connecté. \n- *__sessionIndex__* : SessionIndex reçu de l'IdP lorsque l'utilisateur s'est connecté.",packages/i18n/src/locales/ru.i18n.json (1)
3312-3314: Remove escaping inside inline code placeholderИнлайн‑код не обрабатывает Markdown, поэтому
\_\_authnContext\_\_будет показан с обратными слешами. Нужно вернуть__authnContext__, чтобы админы видели корректный плейсхолдер.packages/i18n/src/locales/pl.i18n.json (1)
3510-3510: Przywróć placeholder__issuer__i napraw format listy SAML.Wystrzeliliśmy placeholder
__issuer__, Markdown jest popsuty (**\\Wydawca), a wpis dla Identifier Format ma błędne formatowanie. To psuje instrukcję dla administratora i jest niezgodne z resztą lokalizacji. Przywróć poprawną listę z literalnymi placeholderami.- "SAML_Metadata_Template_Description": "Dostępne są następujące zmienne: \n- *\\_\\_sloLocation\\_\\_*: Rocket.Chat Single LogOut URL. \n- **\\Wydawca: Wartość ustawienia *Custom Issuer*. \n- *\\_\\_identifierFormat\\_\\_*: Wartość ustawienia __Identifier Format_. \n- *\\_\\_certificateTag\\_\\_*: Jeśli skonfigurowany jest certyfikat prywatny, będzie on zawierał *Metadata Certificate Template*, w przeciwnym razie będzie on ignorowany. \n- *\\_\\_callbackUrl\\_\\_*: Rocket.Chat callback URL.", + "SAML_Metadata_Template_Description": "Dostępne są następujące zmienne: \n- *\\_\\_sloLocation\\_\\_*: Rocket.Chat Single LogOut URL. \n- *\\_\\_issuer\\_\\_*: Wartość ustawienia *Custom Issuer*. \n- *\\_\\_identifierFormat\\_\\_*: Wartość ustawienia *Identifier Format*. \n- *\\_\\_certificateTag\\_\\_*: Jeśli skonfigurowany jest certyfikat prywatny, będzie on zawierał *Metadata Certificate Template*, w przeciwnym razie będzie on ignorowany. \n- *\\_\\_callbackUrl\\_\\_*: Rocket.Chat callback URL.",packages/i18n/src/locales/ka-GE.i18n.json (1)
2841-2841: Fix Georgian genitive suffix in “Thread_message”.Genitive suffix still separated from the username; it should be attached with a hyphen. Please apply the previous suggestion.
- "Thread_message": "კომენტარი გააკეთა *{{username}}* ის გზავნილზე: _{{msg}}_", + "Thread_message": "კომენტარი გააკეთა *{{username}}*-ის გზავნილზე: _{{msg}}_",packages/i18n/src/locales/lv.i18n.json (1)
2236-2236: Fix spacing around placeholders in user audit strings.Both translations lost the spaces adjacent to the
<em>placeholders, so rendered text now glues words together (e.g.,pievienojaJānis). Restore the spaces to keep the Latvian output readable.- "User_added_by": "Lietotāju <em>{{user_added}}</em>pievienoja <em>{{user_by}}</em>.", + "User_added_by": "Lietotāju <em>{{user_added}}</em> pievienoja <em>{{user_by}}</em>.", … - "User_unmuted_by": "Lietotājam <em>{{user_unmuted}}</em>atļāva rakstīt<em>{{user_by}}</em>.", + "User_unmuted_by": "Lietotājam <em>{{user_unmuted}}</em> atļāva rakstīt <em>{{user_by}}</em>.",Also applies to: 2264-2264
packages/i18n/src/scripts/check.mts (2)
451-456: Reset the%smatcher before each translationThe global
sprintfRegexstill carrieslastIndexacross translations, so after the first match subsequent strings are skipped. Please restore the earlier fix (resetsprintfRegex.lastIndex = 0;before eachexec).
319-327: Fix placeholder replacement to preserve each captured tokenBecause the replacement string reuses
match[1], every placeholder in the string is rewritten to the same name as the first match (e.g.,__foo__ ... __bar__becomes{{foo}} ... {{foo}}). Swap to a replacer callback so each occurrence keeps its own capture.- fixedResource[key] = { - ...(fixedResource[key] as Record<string, string>), - [plural]: translation.replace(placeholderRegex, `{{${match[1]}}}`), - }; + fixedResource[key] = { + ...(fixedResource[key] as Record<string, string>), + [plural]: translation.replace(placeholderRegex, (_, placeholder) => `{{${placeholder}}}`), + }; } else { - fixedResource[key] = translation.replace(placeholderRegex, `{{${match[1]}}}`); + fixedResource[key] = translation.replace(placeholderRegex, (_, placeholder) => `{{${placeholder}}}`);packages/i18n/src/locales/hi-IN.i18n.json (2)
827-828: Queue count strings still read as an instructionThe Hindi copy keeps “कॉल करें”, which means “place a call”, not “calls waiting in queue”. Please rephrase both forms to state the number of queued calls (e.g. “कतार में {{count}} कॉल है/हैं”).
2771-2771: Fix mistranslated MAU label
"MAU_value": "हमेशा {{value}}"renders “Always {{value}}”, breaking the metric label. Restore the MAU wording so the UI shows the intended metric name.- "MAU_value": "हमेशा {{value}}", + "MAU_value": "MAU {{value}}",packages/i18n/src/locales/es.i18n.json (1)
3261-3318: Placeholders are still escaped instead of rendered as inline codeThe
_characters remain escaped and the values are wrapped in*…*, so the UI still emits the literal\_\_placeholder\_\_rather than the intended inline code. Please drop the escapes and switch these bullets to proper backtick formatting so the placeholders render as code (same issue flagged previously).- "SAML_AuthnContext_Template_Description": "Puedes usar cualquier variable de la plantilla AuthnRequest aquí. \n \nPara añadir contextos de autenticación adicionales, duplica la etiqueta `AuthnContextClassRef` y reemplaza la variable `\\_\\_authnContext\\_\\_` con el nuevo contexto.", + "SAML_AuthnContext_Template_Description": "Puedes usar cualquier variable de la plantilla AuthnRequest aquí. \n \nPara añadir contextos de autenticación adicionales, duplica la etiqueta `AuthnContextClassRef` y reemplaza la variable `__authnContext__` con el nuevo contexto.", @@ - "SAML_AuthnRequest_Template_Description": "Las siguientes variables están disponibles: \n- *\\_\\_newId\\_\\_*: Cadena de identificación generada aleatoriamente \n- *\\_\\_instant\\_\\_*: Fecha y hora actual \n- *\\_\\_callbackUrl\\_\\_*: URL de devolución de llamada de Rocket.Chat \n- *\\_\\_entryPoint\\_\\_*: Valor del ajuste *Custom Entry Point* \n- *\\_\\_issuer\\_\\_*: Valor del ajuste *Custom Issuer* \n- *\\_\\_identifierFormatTag\\_\\_*: Contenido de *NameID Policy Template* si un *Identifier Format* válido está configurado \n- *\\_\\_identifierFormat\\_\\_*: Valor del ajuste *Identifier Format* \n- *\\_\\_authnContextTag\\_\\_*: Contenido de *AuthnContext Template* si un *Custom Authn Context* válido está configurado \n- *\\_\\_authnContextComparison\\_\\_*: Valor del ajuste *Authn Context Comparison* \n- *\\_\\_authnContext\\_\\_*: Valor del ajuste *Custom Authn Context*", + "SAML_AuthnRequest_Template_Description": "Las siguientes variables están disponibles: \n- `__newId__`: Cadena de identificación generada aleatoriamente \n- `__instant__`: Fecha y hora actual \n- `__callbackUrl__`: URL de devolución de llamada de Rocket.Chat \n- `__entryPoint__`: Valor del ajuste *Custom Entry Point* \n- `__issuer__`: Valor del ajuste *Custom Issuer* \n- `__identifierFormatTag__`: Contenido de *NameID Policy Template* si un *Identifier Format* válido está configurado \n- `__identifierFormat__`: Valor del ajuste *Identifier Format* \n- `__authnContextTag__`: Contenido de *AuthnContext Template* si un *Custom Authn Context* válido está configurado \n- `__authnContextComparison__`: Valor del ajuste *Authn Context Comparison* \n- `__authnContext__`: Valor del ajuste *Custom Authn Context*", @@ - "SAML_Custom_Authn_Context_description": "Dejar esto vacío para omitir el contexto de autenticación de la solicitud. \n \nPara añadir múltiples contextos de autenticación, añade los adicionales directamente al ajuste *AuthnContext Template*.", + "SAML_Custom_Authn_Context_description": "Dejar esto vacío para omitir el contexto de autenticación de la solicitud. \n \nPara añadir múltiples contextos de autenticación, añade los adicionales directamente al ajuste *AuthnContext Template*.", @@ - "SAML_LogoutRequest_Template_Description": "Las siguientes variables están disponibles: \n- *\\_\\_newId\\_\\_*: Cadena de identificación generada aleatoriamente \n- *\\_\\_instant\\_\\_*: Fecha y hora actual \n- *\\_\\_idpSLORedirectURL\\_\\_*: URL de inicio de sesión único de IDP a la que redireccionar \n- *\\_\\_issuer\\_\\_*: Valor del ajuste *Custom Issuer* \n- *\\_\\_identifierFormat\\_\\_*: Valor del ajuste *Identifier Format* \n- *\\_\\_nameID\\_\\_*: NameID recibido desde el IdP cuando el usuario ha iniciado sesión \n- *\\_\\_sessionIndex\\_\\_*: SessionIndex recibido desde el IdP cuando el usuario ha cerrado sesión", + "SAML_LogoutRequest_Template_Description": "Las siguientes variables están disponibles: \n- `__newId__`: Cadena de identificación generada aleatoriamente \n- `__instant__`: Fecha y hora actual \n- `__idpSLORedirectURL__`: URL de inicio de sesión único de IDP a la que redireccionar \n- `__issuer__`: Valor del ajuste *Custom Issuer* \n- `__identifierFormat__`: Valor del ajuste *Identifier Format* \n- `__nameID__`: NameID recibido desde el IdP cuando el usuario ha iniciado sesión \n- `__sessionIndex__`: SessionIndex recibido desde el IdP cuando el usuario ha cerrado sesión", @@ - "SAML_LogoutResponse_Template_Description": "Las siguientes variables están disponibles: \n- *\\_\\_newId\\_\\_*: Cadena de identificación generada aleatoriamente \n- *\\_\\_inResponseToId\\_\\_*: ID de la respuesta de cierre de sesión recibida desde el IdP \n- *\\_\\_instant\\_\\_*: Fecha y hora actual \n- *\\_\\_idpSLORedirectURL\\_\\_*: URL de inicio de sesión único de IDP a la que redireccionar \n- *\\_\\_issuer\\_\\_*: Valor del ajuste *Custom Issuer* \n- *\\_\\_identifierFormat\\_\\_*: Valor del ajuste *Identifier Format* \n- *\\_\\_nameID\\_\\_*: NameID recibido desde la solicitud de cierre de sesión de IdP \n- *\\_\\_sessionIndex\\_\\_*: SessionIndex recibido desde la solicitud de cierre de sesión de IdP", + "SAML_LogoutResponse_Template_Description": "Las siguientes variables están disponibles: \n- `__newId__`: Cadena de identificación generada aleatoriamente \n- `__inResponseToId__`: ID de la respuesta de cierre de sesión recibida desde el IdP \n- `__instant__`: Fecha y hora actual \n- `__idpSLORedirectURL__`: URL de inicio de sesión único de IDP a la que redireccionar \n- `__issuer__`: Valor del ajuste *Custom Issuer* \n- `__identifierFormat__`: Valor del ajuste *Identifier Format* \n- `__nameID__`: NameID recibido desde la solicitud de cierre de sesión de IdP \n- `__sessionIndex__`: SessionIndex recibido desde la solicitud de cierre de sesión de IdP", @@ - "SAML_Metadata_Certificate_Template_Description": "Las siguientes variables están disponibles: \n- *\\_\\_certificate\\_\\_*: Certificado privado para cifrado de aserción", + "SAML_Metadata_Certificate_Template_Description": "Las siguientes variables están disponibles: \n- `__certificate__`: Certificado privado para cifrado de aserción", @@ - "SAML_Metadata_Template_Description": "Las siguientes variables están disponibles: \n- *\\_\\_sloLocation\\_\\_*: URL de cierre de sesión única de Rocket.Chat \n- *\\_\\_issuer\\_\\_*: Valor del ajuste *Custom Issuer* \n- *\\_\\_identifierFormat\\_\\_*: Valor del ajuste *Identifier Format* \n- *\\_\\_certificateTag\\_\\_*: Si un certificado privado está configurado, esto incluirá el *Metadata Certificate Template*, de lo contrario se ignorará \n- *\\_\\_callbackUrl\\_\\_*: URL de respaldo de Rocket.Chat", + "SAML_Metadata_Template_Description": "Las siguientes variables están disponibles: \n- `__sloLocation__`: URL de cierre de sesión única de Rocket.Chat \n- `__issuer__`: Valor del ajuste *Custom Issuer* \n- `__identifierFormat__`: Valor del ajuste *Identifier Format* \n- `__certificateTag__`: Si un certificado privado está configurado, esto incluirá el *Metadata Certificate Template*, de lo contrario se ignorará \n- `__callbackUrl__`: URL de respaldo de Rocket.Chat", @@ - "SMS_Default_Omnichannel_Department_Description": "Si se establece esta opción, todos los nuevos chats entrantes iniciados por esta integración se enrutarán a este departamento. \nEste ajuste se puede sobrescribir pasando el parámetro de consulta del departamento en la solicitud. \nPor ejemplo, `https://\\{\\{SERVER_URL\\}\\}/api/v1/livechat/sms-incoming/twilio?department=\\{\\{Department Id or Name\\}\\}`. \nNota: Si estás usando el nombre del departamento, debería poder usarse en la URL.", + "SMS_Default_Omnichannel_Department_Description": "Si se establece esta opción, todos los nuevos chats entrantes iniciados por esta integración se enrutarán a este departamento. \nEste ajuste se puede sobrescribir pasando el parámetro de consulta del departamento en la solicitud. \nPor ejemplo, `https://{{SERVER_URL}}/api/v1/livechat/sms-incoming/twilio?department={{Department Id or Name}}`. \nNota: Si estás usando el nombre del departamento, debería poder usarse en la URL.",
| "exports": { | ||
| ".": { | ||
| "types": "./dist/index.d.ts", | ||
| "import": "./dist/index.js", | ||
| "require": "./dist/index.cjs" | ||
| }, | ||
| "./dist/resources": { | ||
| "types": "./dist/resources.d.ts", | ||
| "import": "./dist/resources.js", | ||
| "require": "./dist/resources.cjs" | ||
| }, | ||
| "./dist/languages": { | ||
| "types": "./dist/languages.d.ts", | ||
| "import": "./dist/languages.js", | ||
| "require": "./dist/languages.cjs" | ||
| } | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Verify exports map doesn’t break existing deep imports
Moving to an explicit exports map narrows the surface area to ".", "./dist/resources", and "./dist/languages". Any existing call sites that reach for other deep paths (e.g., @rocket.chat/i18n/dist/index.js, @rocket.chat/i18n/dist/index.mjs, @rocket.chat/i18n/dist/locales/*) will now throw ERR_PACKAGE_PATH_NOT_EXPORTED. Please scan the repo and confirm we’re not relying on those legacy entry points, or expand the map accordingly.
🏁 Script executed:
#!/bin/bash
# Find imports that will be blocked by the new exports map.
rg -nP "@rocket\\.chat/i18n/(dist|src)/[^'\"]+" --type-add 'mjs:*.mjs' --type-add 'mts:*.mts' --type-add 'cjs:*.cjs' --type-add 'cts:*.cts' --type-add 'cts:*.cts' --type ts --type tsx --type js --type jsx --type mjs --type mts --type cjs --type ctsLength of output: 27
🏁 Script executed:
#!/bin/bash
# Search for any deep imports/require calls into @rocket.chat/i18n beyond the new exports map
rg -n "@rocket\\.chat/i18n/(dist|src)/" -g "*.{js,jsx,ts,tsx,mjs,mts,cjs,cts}"Length of output: 539
Expand exports or update deep imports to match allowed entrypoints
Deep imports will break under the new exports map. Add missing paths or adjust imports to use the package entrypoint:
• packages/mock-providers/src/MockedAppRootBuilder.tsx: @rocket.chat/i18n/dist/languages
• ee/apps/omnichannel-transcript/src/i18n.ts: @rocket.chat/i18n/dist/resources
• apps/meteor/client/providers/TranslationProvider.tsx:
– @rocket.chat/i18n/dist/languages
– @rocket.chat/i18n/dist/resources/en.i18n.json
• apps/meteor/server/lib/i18n.ts: @rocket.chat/i18n/dist/resources
Either expand exports in packages/i18n/package.json to include these deep paths (e.g. "./dist/resources/en.i18n.json") or refactor imports to use import … from '@rocket.chat/i18n'.
🤖 Prompt for AI Agents
In packages/i18n/package.json around lines 6–22, the exports map currently omits
the deep paths used by consumers (e.g. @rocket.chat/i18n/dist/languages and
@rocket.chat/i18n/dist/resources and the specific resources file en.i18n.json),
which breaks imports; fix by expanding the exports map to add entries for
"./dist/languages", "./dist/resources" and the specific JSON file
"./dist/resources/en.i18n.json" (each with types/import/require as appropriate),
or alternatively update the callers listed in the review to import from the
package entrypoint ('@rocket.chat/i18n') instead of deep-importing.
| @@ -0,0 +1 @@ | |||
| module.exports = require('./index.js'); | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix the CommonJS bridge to avoid ERR_REQUIRE_ESM.
index.js is now emitted as an ES module ("type": "module" in the package export map). Calling require('./index.js') from this CJS bridge will throw ERR_REQUIRE_ESM, so every CommonJS consumer will crash. Point the bridge at the compiled CommonJS build (e.g., ./index.cjs) or create a dedicated CJS bundle and export that instead.
🤖 Prompt for AI Agents
In packages/i18n/src/index.cts around line 1, the CommonJS bridge currently does
require('./index.js') which will throw ERR_REQUIRE_ESM because index.js is
emitted as an ES module; change the bridge to point at the compiled CommonJS
output (for example require('./index.cjs') or the appropriate CJS bundle path),
or alternatively produce and export a dedicated CJS bundle and require that
instead so CommonJS consumers no longer attempt to require an ES module.
| "SAML_Metadata_Certificate_Template_Description": "Les següents variables estan disponibles: \n- *\\_\\_newId\\_\\_*: Cadena d'identificació generada aleatòriament", | ||
| "SAML_Metadata_Template": "Plantilla de metadades", | ||
| "SAML_Metadata_Template_Description": "Les següents variables estan disponibles: \n - ** \\ _ \\ _ sloLocation \\ _ \\ _ **: L'URL de tancament de sessió simple de Rocket.Chat \n- ** \\ _ \\ _ issuer \\ _ \\ _ **: The value of the {{Custom Issuer}} setting. \n- ** \\ _ \\ _ identifierFormat \\ _ \\ _ **: el valor de l'opció {{Identifier Format }} \n- ** \\ _ \\ _ certificateTag \\ _ \\ _ **: Si un certificat privat és configurat, això inclourà el {{Metadata Certificate Template}}, en cas contrari serà ignorado. \n- ** \\ _ \\ _ callbackUrl \\ _ \\ _ **: L'URL de crida de Rocket.Chat", | ||
| "SAML_Metadata_Template_Description": "Les següents variables estan disponibles: \n - *\\_\\_sloLocation\\_\\_*: L'URL de tancament de sessió simple de Rocket.Chat \n- *\\_\\_issuer\\_\\_*: The value of the *Custom Issuer* setting. \n- *\\_\\_identifierFormat\\_\\_*: el valor de l'opció *Identifier Format* \n- *\\_\\_certificateTag\\_\\_*: Si un certificat privat és configurat, això inclourà el *Metadata Certificate Template*, en cas contrari serà ignorado. \n- *\\_\\_callbackUrl\\_\\_*: L'URL de crida de Rocket.Chat", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix untranslated fragment in metadata description.
The updated Catalan string now contains the English sentence The value of the *Custom Issuer* setting. (Line 3178), breaking locale consistency. Please translate this fragment back to Catalan (e.g., “El valor de l’opció Custom Issuer”) to keep the localization intact.
🤖 Prompt for AI Agents
In packages/i18n/src/locales/ca.i18n.json around line 3178, the
SAML_Metadata_Template_Description contains an English fragment "The value of
the *Custom Issuer* setting."; replace that fragment with the Catalan
translation (for example: "El valor de l'opció *Custom Issuer*") preserving
surrounding punctuation, newline escapes, and Markdown/asterisk formatting so
the full string remains consistent and properly escaped.
| "room_changed_description": "ოთახის აღწერა შეიცვალა: {{room_description}} მიერ {{user_by}}", | ||
| "room_changed_topic": "ოთახის თემა შეიცვალა: {{room_topic}} {{user_by}}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rephrase “room_changed_*” announcements for correct Georgian grammar.
Both strings leave the agent without the required “-მა” suffix and read awkwardly. Restructure to put the actor before the content.
- "room_changed_announcement": "ოთახის განცხადება შეიცვალა {{room_announcement}} მიერ {{user_by}}",
- "room_changed_description": "ოთახის აღწერა შეიცვალა: {{room_description}} მიერ {{user_by}}",
+ "room_changed_announcement": "{{user_by}}-მა შეცვალა ოთახის განცხადება: {{room_announcement}}",
+ "room_changed_description": "{{user_by}}-მა შეცვალა ოთახის აღწერა: {{room_description}}",Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In packages/i18n/src/locales/ka-GE.i18n.json around lines 3541–3542, the
"room_changed_description" and "room_changed_topic" keys are grammatically
incorrect in Georgian because the actor lacks the required "-მა" suffix and the
phrasing places the actor after the content; update both strings to put the
actor before the changed content and append the instrumental suffix to the actor
placeholder (e.g., move {{user_by}} to the front and use {{user_by}}-მა),
ensuring spacing and punctuation are adjusted for natural Georgian word order.
| "user-generate-access-token_description": "მომხმარებლისთვის წვდომის ტოკენის გენერირების უფლება", | ||
| "user_sent_an_attachment": "{{username}}– მა გაგზავნა დანართი", | ||
| "user_sent_an_attachment": "{{user}}– მა გაგზავნა დანართი", | ||
| "view-broadcast-member-list": "წევრების სია იხილეთ სამაუწყებლო ოთახში", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tighten the dash in “user_sent_an_attachment”.
There’s an extra space after the dash; join the agent suffix back to the username.
- "user_sent_an_attachment": "{{user}}– მა გაგზავნა დანართი",
+ "user_sent_an_attachment": "{{user}}–მა გაგზავნა დანართი",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "view-broadcast-member-list": "წევრების სია იხილეთ სამაუწყებლო ოთახში", | |
| "view-broadcast-member-list": "წევრების სია იხილეთ სამაუწყებლო ოთახში", | |
| "user_sent_an_attachment": "{{user}}–მა გაგზავნა დანართი", |
🤖 Prompt for AI Agents
In packages/i18n/src/locales/ka-GE.i18n.json around line 3626, the translation
for the key "user_sent_an_attachment" has an extra space after the dash
separating the username and the agent suffix; remove that extra space so the
dash is immediately followed by the agent suffix (i.e., join the suffix back to
the username), and ensure you use the correct dash character consistent with
other translations.
| "room_changed_description": "Istabas apraksts ir mainīts uz: <em>{{room_description}}</em> <em>{{user_by}}</em>", | ||
| "room_is_blocked": "Šī istaba ir bloķēta", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Restore actor clause in room change announcements.
room_changed_announcement/room_changed_description now drop the connective before {{user_by}}, so the message renders as … <em>teksts</em> Jānis, missing “ko mainīja” (or equivalent). Please reintroduce the user clause to preserve meaning.
- "room_changed_announcement": "Istabas paziņojums mainīts uz: <em>{{room_announcement}}</em> <em>{{user_by}}</em>",
- "room_changed_description": "Istabas apraksts ir mainīts uz: <em>{{room_description}}</em> <em>{{user_by}}</em>",
+ "room_changed_announcement": "Istabas paziņojums mainīts uz: <em>{{room_announcement}}</em>, ko mainīja <em>{{user_by}}</em>",
+ "room_changed_description": "Istabas apraksts ir mainīts uz: <em>{{room_description}}</em>, ko mainīja <em>{{user_by}}</em>",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "room_changed_description": "Istabas apraksts ir mainīts uz: <em>{{room_description}}</em> <em>{{user_by}}</em>", | |
| "room_is_blocked": "Šī istaba ir bloķēta", | |
| "room_changed_announcement": "Istabas paziņojums mainīts uz: <em>{{room_announcement}}</em>, ko mainīja <em>{{user_by}}</em>", | |
| "room_changed_description": "Istabas apraksts ir mainīts uz: <em>{{room_description}}</em>, ko mainīja <em>{{user_by}}</em>", | |
| "room_is_blocked": "Šī istaba ir bloķēta", |
🤖 Prompt for AI Agents
In packages/i18n/src/locales/lv.i18n.json around lines 2642-2643, the translated
string for "room_changed_description" dropped the connective before {{user_by}},
causing output like "… <em>teksts</em> Jānis"; restore an actor clause so the
sentence reads naturally (e.g., insert a phrase such as "ko mainīja {{user_by}}"
or equivalent Latvian connective before {{user_by}}) so the message becomes
"Istabas apraksts ir mainīts uz: <em>{{room_description}}</em> ko mainīja
<em>{{user_by}}</em>" (or a grammatically correct variant).
| const replaceNullValuesInterpolation = (translation: string) => { | ||
| return [undefined, translation === null] as const; | ||
| }; | ||
|
|
||
| const generator = (fn, id) => (dictionary, language, cb) => { | ||
| return Object.entries(dictionary).reduce((dic, [key, value]) => { | ||
| const [replacement, exist] = fn(value); | ||
| if (exist) { | ||
| cb?.(id, { language, key }); | ||
| } | ||
| if (replacement) { | ||
| dic[key] = replacement; | ||
| } | ||
| return dic; | ||
| }, dictionary); | ||
| }; | ||
| const generator = | ||
| (fn: (translation: string) => readonly [string | undefined, boolean], id: string) => | ||
| (dictionary: Record<string, any>, language: string, cb?: (id: string, info: { language: string; key: string }) => void) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix TypeScript null comparison regression
Line 33 compares translation against null, but since the parameter was tightened to string, the compiler now raises TS2367 (“this condition will always return false”) under strictNullChecks, breaking the build. Nested plural normalization can still surface real null entries, so we need to allow them through the typing. Please widen the helper (and the generator it feeds) to accept string | null before landing.
-const replaceI18nInterpolation = (translation: string) => {
+const replaceI18nInterpolation = (translation: string | null) => {
@@
-const replaceSprintfInterpolation = (translation: string) => {
+const replaceSprintfInterpolation = (translation: string | null) => {
@@
-const replaceI18nextComponentsArrayInterpolation = (translation: string) => {
+const replaceI18nextComponentsArrayInterpolation = (translation: string | null) => {
@@
-const replaceNullValuesInterpolation = (translation: string) => {
+const replaceNullValuesInterpolation = (translation: string | null) => {
@@
-const generator =
- (fn: (translation: string) => readonly [string | undefined, boolean], id: string) =>
+const generator =
+ (fn: (translation: string | null) => readonly [string | undefined, boolean], id: string) =>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const replaceNullValuesInterpolation = (translation: string) => { | |
| return [undefined, translation === null] as const; | |
| }; | |
| const generator = (fn, id) => (dictionary, language, cb) => { | |
| return Object.entries(dictionary).reduce((dic, [key, value]) => { | |
| const [replacement, exist] = fn(value); | |
| if (exist) { | |
| cb?.(id, { language, key }); | |
| } | |
| if (replacement) { | |
| dic[key] = replacement; | |
| } | |
| return dic; | |
| }, dictionary); | |
| }; | |
| const generator = | |
| (fn: (translation: string) => readonly [string | undefined, boolean], id: string) => | |
| (dictionary: Record<string, any>, language: string, cb?: (id: string, info: { language: string; key: string }) => void) => | |
| const replaceNullValuesInterpolation = (translation: string | null) => { | |
| return [undefined, translation === null] as const; | |
| }; | |
| const generator = | |
| (fn: (translation: string | null) => readonly [string | undefined, boolean], id: string) => | |
| (dictionary: Record<string, any>, language: string, cb?: (id: string, info: { language: string; key: string }) => void) => |
🤖 Prompt for AI Agents
In packages/i18n/src/scripts/normalize.mts around lines 32 to 38, the helper and
its generator are typed to accept only string which causes a TS2367 error when
comparing to null; widen the types so they accept string | null and permit null
in the tuple first element: change replaceNullValuesInterpolation to accept
(translation: string | null) and update the generator fn type from (translation:
string) => readonly [string | undefined, boolean] to (translation: string |
null) => readonly [string | undefined | null, boolean], ensuring downstream
usage expects the widened types.
| "target": "ES2024", | ||
| "module": "nodenext", | ||
| "moduleResolution": "nodenext", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hold on ES2024 target—verify Node/Jest runtime support.
These presets ship JS that Jest executes directly under whatever Node version the consumer runs. Targeting ES2024 means the compiler will emit 2024-level syntax (e.g., using declarations, RegExp v flag) without downleveling. Node 18 and 20—which we still support for Rocket.Chat and which Jest users may rely on—do not implement those features, so a single usage would crash at runtime. Unless we’re officially bumping the minimum Node requirement for this package to ≥22, please keep the target aligned with the current supported runtime (e.g., stay on ES2022) or document the requirement bump and update the release notes accordingly.
- "target": "ES2024",
+ "target": "ES2022",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "target": "ES2024", | |
| "module": "nodenext", | |
| "moduleResolution": "nodenext", | |
| "target": "ES2022", | |
| "module": "nodenext", | |
| "moduleResolution": "nodenext", |
🤖 Prompt for AI Agents
In packages/jest-presets/tsconfig.json around lines 7 to 9, the TS target is set
to ES2024 which can emit syntax not supported by Node/Jest runtimes we still
support (Node 18/20); change the compiler target to ES2022 (or another
runtime-compatible level) so emitted code runs on current supported Node
versions, or if you intend to require Node >=22, update package metadata
(engines), CI, and release notes to document the minimum Node bump before
keeping ES2024.
dougfabris
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.

Proposed changes (including videos or screenshots)
It rearranges some maintenance scripts for i18n resources.
Issue(s)
Steps to test or reproduce
Further comments
Summary by CodeRabbit
Internationalization
Tests
Chores