Skip to content

registerLocaleForEsBuild() returns undefined -> bootstrap crash "Cannot read properties of undefined (reading 'then')" for cultures absent from its hardcoded localeSupportList (e.g. ja, ko, vi) #25730

Description

@duguankui

Is there an existing issue for this?

  • I have searched the existing issues. Related but distinct from Unable to use registerLocaleForEsBuild with locales such as "de-DE" #21483: that one fixed cultureNameLocaleFileMap not being respected (checking locale instead of the mapped l). This report is about cultures absent from localeSupportList entirely, where no mapping can help and the early return; yields undefined.

Description

registerLocaleForEsBuild() (npm/ng-packs/packages/core/locale/src/utils/register-locale.ts) hardcodes a 20-entry locale list. For any active culture whose (mapped) value l is not in that list, the returned function hits return;undefined, before it ever reaches the loadLocale(l).catch(errorHandlerFn) fallback. ABP's locale APP_INITIALIZER then calls registerLocaleFn(locale).then(...) on that undefined:

TypeError: Cannot read properties of undefined (reading 'then')

Bootstrap is aborted → blank app for every user whose active culture resolves to a non-listed language (ja, ko, vi, th, …).

Two things make this distinct from #21483 and hard to work around with configuration alone:

  • cultureNameLocaleFileMap cannot help: it can only remap a culture onto another listed locale file, and there is no listed file carrying Japanese (or Korean/Vietnamese/Thai) data. A backend with Japanese enabled in Language Management therefore blank-screens any ja client with no config-only fix.
  • The documented storeLocaleData escape hatch also doesn't help on the esbuild path — its data is only read by errorHandlerFn, which lives inside the loadLocale(l).catch(...) that the early return; never reaches.

The declared return type is Promise<any>, but the return; branch actually returns undefined, so callers that trust the type (ABP's own locale initializer) crash.

Reproduction Steps

import { registerLocaleForEsBuild } from '@abp/ng.core/locale';

registerLocaleForEsBuild()('ja').then(x => console.log(x));
// TypeError: Cannot read properties of undefined (reading 'then')

End-to-end: enable Japanese (ja) in Language Management, build the Angular app with the esbuild application builder (Angular 17+ default) using registerLocaleFn: registerLocaleForEsBuild(), then open the app with Accept-Language: ja (or with ja persisted in localStorage) → blank app with the error above.

Expected behavior

An unsupported culture should degrade gracefully — return a resolved Promise (and/or route through errorHandlerFn / consult the extraLocales populated by storeLocaleData), never undefined, so bootstrap can't crash. Ideally the esbuild loadLocale list should also cover the cultures ABP ships localization resources for (e.g. ja, ko).

Actual behavior

return; yields undefined; the initializer's .then() throws; the app is blank for the affected users.

Regression?

No. Present since the esbuild loader was introduced; still present on the current dev branch (verified register-locale.ts today). The fix for #21483 (checking l instead of locale) did not touch this return;/undefined path.

Known Workarounds

Wrap registerLocaleFn in app.config.ts to (a) load the extra locale yourself via a literal import('@angular/common/locales/ja') + storeLocaleData, and (b) never return undefined for any unlisted culture:

import { registerLocaleForEsBuild, storeLocaleData } from '@abp/ng.core/locale';

const extra: Record<string, () => Promise<unknown>> = {
  ja: () => import('@angular/common/locales/ja'),
};
const abp = registerLocaleForEsBuild();
const registerLocaleFn = (locale: string) => {
  const handled = abp(locale);
  if (handled) return handled;                          // listed cultures: unchanged
  const load = extra[locale];
  if (!load) return Promise.resolve({ default: null }); // unknown culture: safe no-op, never undefined
  return load()
    .then(m => { let d: any = m; while (d?.default) d = d.default; storeLocaleData(d, locale); return { default: d }; })
    .catch(() => ({ default: null }));
};
// provideAbpCore(withOptions({ environment, registerLocaleFn }))

Suggested fix

Replace the bare return; with return Promise.resolve({ default: null }); (or route unsupported locales through errorHandlerFn, which already consults extraLocales), and/or extend the loadLocale / localeSupportList set to the cultures ABP ships resources for.

Version

@abp/ng.core 10.4.1 (source identical on the current dev branch; reported through 10.5.0). Angular 21, esbuild application builder.

User Interface

Angular

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions