Environment
- air-datepicker: 3.6.0
- vite: 8.x
- Bundler: esbuild (via Vite's dependency pre-bundling)
Problem
Importing a locale subpath in a Vite 8 project causes the datepicker to fall back to Russian (the default locale), even when the locale is passed correctly:
import localeEn from 'air-datepicker/locale/en';
new AirDatepicker('#el', { locale: localeEn }); // renders in Russian
Root cause
package.json has no exports field covering the ./locale/* subpaths. Without an exports map, Vite 8 no longer automatically pre-bundles these files via esbuild. When the raw CJS file (locale/en.js) is
served without esbuild processing it, the browser receives the full module.exports object — { default: locale, __esModule: true } — rather than the unwrapped locale. AirDatepicker receives an object
with no days/months properties and silently falls back to Russian.
In Vite 7 this worked by accident because all node_modules imports were pre-bundled by default. Vite 8 tightened that behavior.
Workaround
Users can force Vite to pre-bundle the locale by adding it to optimizeDeps.include in vite.config.js:
optimizeDeps: {
include: ['air-datepicker/locale/en']
}
Suggested fix
Add a proper exports map to package.json with ESM entry points for the locale subpaths. Example:
"exports": {
".": {
"import": "./index.es.js",
"require": "./index.js"
},
"./locale/": {
"import": "./locale/.mjs",
"require": "./locale/*.js"
},
"./air-datepicker.css": "./air-datepicker.css"
}
This would require shipping ESM versions of the locale files (.mjs), which removes the CJS interop ambiguity entirely and makes the library work correctly across all modern bundlers without any
user-side configuration.
Environment
Problem
Importing a locale subpath in a Vite 8 project causes the datepicker to fall back to Russian (the default locale), even when the locale is passed correctly:
import localeEn from 'air-datepicker/locale/en';
new AirDatepicker('#el', { locale: localeEn }); // renders in Russian
Root cause
package.json has no exports field covering the ./locale/* subpaths. Without an exports map, Vite 8 no longer automatically pre-bundles these files via esbuild. When the raw CJS file (locale/en.js) is
served without esbuild processing it, the browser receives the full module.exports object — { default: locale, __esModule: true } — rather than the unwrapped locale. AirDatepicker receives an object
with no days/months properties and silently falls back to Russian.
In Vite 7 this worked by accident because all node_modules imports were pre-bundled by default. Vite 8 tightened that behavior.
Workaround
Users can force Vite to pre-bundle the locale by adding it to optimizeDeps.include in vite.config.js:
optimizeDeps: {
include: ['air-datepicker/locale/en']
}
Suggested fix
Add a proper exports map to package.json with ESM entry points for the locale subpaths. Example:
"exports": {
".": {
"import": "./index.es.js",
"require": "./index.js"
},
"./locale/": {
"import": "./locale/.mjs",
"require": "./locale/*.js"
},
"./air-datepicker.css": "./air-datepicker.css"
}
This would require shipping ESM versions of the locale files (.mjs), which removes the CJS interop ambiguity entirely and makes the library work correctly across all modern bundlers without any
user-side configuration.