{"record":{"id":"d00e6c0b6117c66f","repo":"RocketChat/Rocket.Chat","slug":"moment-locale-not-found-locale","errorCode":null,"errorMessage":"Moment locale not found: ${locale}","messagePattern":"Moment locale not found: (.+?)","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"warning","filePath":"apps/meteor/server/meteor-methods/platform/loadLocale.ts","lineNumber":21,"sourceCode":"import { Meteor } from 'meteor/meteor';\n\nimport { getMomentLocale } from '../../lib/getMomentLocale';\n\ndeclare module '@rocket.chat/ddp-client' {\n\t// eslint-disable-next-line @typescript-eslint/naming-convention\n\tinterface ServerMethods {\n\t\tloadLocale(locale: string): string | undefined;\n\t}\n}\n\nMeteor.methods<ServerMethods>({\n\tloadLocale(locale) {\n\t\tcheck(locale, String);\n\n\t\ttry {\n\t\t\treturn getMomentLocale(locale);\n\t\t} catch (error: any) {\n\t\t\tthrow new Meteor.Error(error.message, `Moment locale not found: ${locale}`);\n\t\t}\n\t},\n});\n","sourceCodeStart":3,"sourceCodeEnd":25,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/platform/loadLocale.ts#L3-L25","documentation":"The `loadLocale` Meteor method returns the Moment.js locale source so clients can format dates. It calls `getMomentLocale(locale)`, which tries the server assets `moment-locales/<locale>.js`, then the primary subtag (`zh-cn` -> `zh`), then a small alias map (`ug`->`ug-cn`, `zh`->`zh-cn`); if none of those asset files exist it throws, and the method re-wraps it as `Moment locale not found: ${locale}` (code `moment-locale-not-found`). Moment locale filenames are lowercase and hyphenated, so codes like `zh_CN` (underscore) or unknown variants fail all three lookups.","triggerScenarios":"Calling `Meteor.call('loadLocale', locale)` with a code that has no matching moment-locales asset: `zh_CN` instead of `zh-cn`, a regional variant that is not bundled (`en-US` has no asset; only the fallback to `en` saves it if `en.js` exists), or a typo like `ptb`. Clients usually forward the user's saved `language` setting or `navigator.language` verbatim.","commonSituations":"Browser BCP47 tags (en-US, zh-Hant) passed unnormalized; a user language saved by an older Rocket.Chat whose moment bundle differed from the current server's `moment-locales` assets; locale strings with underscores or uppercase letters.","solutions":["Normalize the code before calling: lowercase it and replace underscores with hyphens (`'zh_CN'.toLowerCase().replace('_', '-')` -> `zh-cn`)","Trim to the primary subtag when the full tag is unavailable (`pt-br` -> `pt`), mirroring the server's own fallback order","Map special cases the server maps (`zh` -> `zh-cn`, `ug` -> `ug-cn`) and check the locale exists client-side via `moment.locales()` before requesting","On failure, retry once with the workspace default locale (e.g. `en`) so date formatting still works"],"exampleFix":"// before\nMeteor.call('loadLocale', user.language, (err, src) => { ... });\n// after\nconst normalize = (l) => l.toLowerCase().replace('_', '-');\nconst primary = (l) => l.split('-').shift();\nMeteor.call('loadLocale', normalize(user.language), (err, src) => {\n  if (err) return Meteor.call('loadLocale', primary(normalize(user.language)) || 'en', cb);\n  useLocaleSource(src);\n});","handlingStrategy":"validation","validationCode":"const KNOWN = new Set(['en', 'pt', 'pt-br', 'zh', 'zh-cn', 'ug', 'ug-cn' /* ... */]);\nconst normalize = (l) => l.toLowerCase().replace('_', '-');\nconst resolveLocale = (l) => {\n  const n = normalize(l);\n  if (KNOWN.has(n)) return n;\n  const primary = n.split('-').shift();\n  if (KNOWN.has(primary)) return primary;\n  return 'en';\n};\nMeteor.call('loadLocale', resolveLocale(user.language), cb);","typeGuard":"const isKnownMomentLocale = (locale: string): boolean =>\n  typeof moment !== 'undefined' &&\n  moment.locales().includes(locale.toLowerCase().replace('_', '-'));","tryCatchPattern":"Meteor.call('loadLocale', locale, (err, src) => {\n  if (err) {\n    // degrade gracefully: retry once with the default locale\n    return Meteor.call('loadLocale', 'en', fallbackCb);\n  }\n  useLocaleSource(src);\n});","preventionTips":["Always normalize locale strings (lowercase, hyphen-separated) before sending them to the server","Keep the client's list of supported locales in sync with the server's moment-locales assets","Never forward raw navigator.language; map it to a moment-supported code first"],"tags":["i18n","moment","locale","meteor-method"],"backgroundTag":"unsupported-locale","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}