pkg
pkg copied to clipboard
exe packaged by pkg doesn't follow Date().toLocaleDateString() locale parameter
What version of pkg are you using?
5.8.0
What version of Node.js are you using?
18.4.0 and 10.19.0
What operating system are you using?
Windows and ubuntu 20.04
What CPU architecture are you using?
x86_64 and arm64
What Node versions, OSs and CPU architectures are you building for?
node18-win-x64 and node10-linux-arm64
Describe the Bug
exe and linux binary files packaged by pkg seem to not work properly with Date().toLocaleDateString() code in the .js file. More specifically, the packaged executables default the locales parameter in .toLocaleDateString(locales, options) to en-US. More can be read about this method here: [(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString)]
Expected Behavior
Passing a date through the .toLocaleDateString(locales) method should return a date that is formatted according to the locales parameter. For eg. console.log(date.toLocaleDateString('en-US')); should print the date in month-day-year order console.log(date.toLocaleDateString('en-GB')); should print the date in day-month-year order console.log(date.toLocaleDateString('ko-KR')); should print the date in year-month-day order
To Reproduce
-
make a js file with the following code
const date = new Date('2022-08-14').toLocaleDateString('ko-KR', { day: 'numeric', month: 'short', year: 'numeric' }) console.log(date)
'ko-KR' can be changed to other locales such as 'en-GB'. -
pkg the js file into an executable and run the executable
Same occurs here. Any solution for that?
I tried with https://www.npmjs.com/package/full-icu , with no luck
Before PKG
root@f0e3a6143f75:/app# node index.js
{
nodever: '14.19.1',
node_maj: '14',
node_min: '19',
icu_small: false,
icuver: '70.1',
icumaj: '70',
icuend: 'l',
icupkg: 'icu4c-data@70l',
icudat: 'icudt70l.dat',
haveDat: [Function: haveDat],
datPath: [Function: datPath]
}
2022년 8월 14일
14 août 2022
After PKG
root@f0e3a6143f75:/app# ./app.bin
{
nodever: '14.20.0',
node_maj: '14',
node_min: '20',
icu_small: true,
icuver: '70.1',
icumaj: '70',
icuend: 'l',
icupkg: 'icu4c-data@70l',
icudat: 'icudt70l.dat',
haveDat: [Function: haveDat],
datPath: [Function: datPath]
}
Aug 14, 2022
Aug 14, 2022
Tried with pkg --output app.bin --target node14-linux-x64 index.js
and NODE_ICU_DATA=node_modules/full-icu pkg --output app.bin --target node14-linux-x64 index.js
#1749 #1570 #1563
Alright I finally managed to do it. Here's a small working tutorial, that you'll only need to adapt to your usage.
Goal
Use pkg
to build a node app (target: node14-linux-x64
) with ICU, to fix dates displaying for example.
Steps
- Run a
node
docker with the same version as your goal
docker run -it --rm node:14.20.0 /bin/bash
- Create a demo app
mkdir app && cd app
npm init
touch index.js
npm install full-icu
- Add code to that demo app
const icu = require('full-icu');
console.log(icu);
try { console.log(icu.datPath()); } catch (ex) { console.log(ex.message); }
const dateKO = new Date('2022-08-14').toLocaleDateString('ko-KR', { day: 'numeric', month: 'short', year: 'numeric' });
console.log(dateKO);
const dateFR = new Date('2022-08-14').toLocaleDateString('fr-FR', { day: 'numeric', month: 'short', year: 'numeric' });
console.log(dateFR);
- Run the app to get ICU information
node index.js
{
nodever: '14.20.0',
node_maj: '14',
node_min: '20',
icu_small: false,
icuver: '70.1',
icumaj: '70',
icuend: 'l',
icupkg: 'icu4c-data@70l',
icudat: 'icudt70l.dat',
haveDat: [Function: haveDat],
datPath: [Function: datPath]
}
ENOENT: no such file or directory, lstat '/app/node_modules/full-icu/icudt70l.dat'
2022년 8월 14일
14 août 2022
-
As you can see here, the node docker is built with full ICU (
icu_small: false
), and display foreign dates correctly. That's great, but that also mean thatfull-icu
won't download any more files to fixsmall-icu
... We'll have to do it manually ! -
Now you know that you need
icudt70l.dat
file, at the location/app/node_modules/full-icu/icudt70l.dat
, so head over https://icu.unicode.org/download and select the right version (ICU 70 - ICU4C 70.1). On that version page you'll find the GitHub release page. You need to download the file that matches the version you need, here it'shttps://icu4c-70_1-data-bin-l.zip
-
Let's download that file and unzip it in the needed location
cd node_modules/full-icu/
wget https://github.com/unicode-org/icu/releases/download/release-70-1/icu4c-70_1-data-bin-l.zip
unzip icu4c-70_1-data-bin-l.zip
cd ../..
- Everything is set up, you can now use
pkg
and get a good result 😄
npm install -g pkg
pkg --output app.bin --target node14-linux-x64 --options icu-data-dir=./node_modules/full-icu index.js
- Let's test our binary
./app.bin
{
nodever: '14.20.0',
node_maj: '14',
node_min: '20',
icu_small: true,
icuver: '70.1',
icumaj: '70',
icuend: 'l',
icupkg: 'icu4c-data@70l',
icudat: 'icudt70l.dat',
haveDat: [Function: haveDat],
datPath: [Function: datPath]
}
Does not exist: /snapshot/app/node_modules/full-icu/icudt70l.dat
2022년 8월 14일
14 août 2022
If you see the same result as me, congratulations, you fixed your PKG ! As you can see, it uses small-icu
(icu_small: true
) but the foreign dates are correctly displaying, thanks to full-icu
🥳
@TBG-FR Could you create a PR to add that to docs ?
Hello @TBG-FR
Thanks for the trick👍
I manage to display correctly date/number using icu-data-dir
option as you did.
However I can not manage to embed the icu.dat
in the binary output (even using pkg/assets). Have you ?
Because once compiled, if I remove the .dat file from specified location, it does not work anymore.. see error below :
bin\sample.exe: could not initialize ICU (check NODE_ICU_DATA or --icu-data-dir parameters)
Doesn't work here, it says that exactly that it should, but doesn't work
wget https://github.com/unicode-org/icu/releases/download/release-71-1/icu4c-71_1-data-bin-l.zip
unzip icu4c-71_1-data-bin-l.zip
mv icudt71l.dat node_modules/full-icu
const icu = require('full-icu')
console.log(icu)
try {
console.log(icu.datPath())
} catch (ex) {
console.log(ex)
}
console.log('GB', dateObj.toLocaleDateString('en-gb', options))
console.log('US', dateObj.toLocaleDateString('en-us', options))
outputs
{
nodever: '18.5.0',
node_maj: '18',
node_min: '5',
icu_small: true,
icuver: '71.1',
icumaj: '71',
icuend: 'l',
icupkg: 'icu4c-data@71l',
icudat: 'icudt71l.dat',
haveDat: [Function: haveDat],
datPath: [Function: datPath]
}
/snapshot/app/node_modules/full-icu/icudt71l.dat
GB Nov 17, 2022
US Nov 17, 2022
I managed to get it working, but as @afrz said - it cannot be packaged inside binary - it works in dat file lives outside binary.
I managed to get it working, but as @afrz said - it cannot be packaged inside binary - it works in dat file lives outside binary.
You're right, for now I didn't find a solution for that issue, I'm forced to move and use the dat files with the binary (outside)
I think I tried modifying package.json
tu put them in assets/scripts or something, but maybe I did it wrong
This issue is stale because it has been open 90 days with no activity. Remove the stale label or comment or this will be closed in 5 days. To ignore this issue entirely you can add the no-stale label
This issue is now closed due to inactivity, you can of course reopen or reference this issue if you see fit.