This is a follow up to #655
I'm working on a fix to enable Windows users to set the default language of the App.exe, Setup.exe etc. (currently set to English (US) for all exe's).
atom/rcedit would be the ideal repo to take care of this, but I grew tired of waiting for a response from the maintainers. So here is my simple node script to modify the language / locale id :
'use strict';
const fs = require('fs');
// T r a n s l a t i o n 0x09 0x04 ( English (US) 16-bit word suffix )
const keywordBuffer = [0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04];
const keywordLength = keywordBuffer.length;
var buffer;
try {
var filename = './App.exe'; // hard-coded for simplicity (script variable TODO)
var fd = fs.openSync(filename, 'r+'); // read + write
buffer = fs.readFileSync(fd);
console.log(`Input File read: ${buffer.length} bytes`);
var modified = false;
for (var i = 0; i < buffer.length - keywordLength; i++) {
if (keywordMatch(i)) {
console.log('Language found at decimal address', i);
buffer[i + 26] = 0x09; // Language: English
buffer[i + 27] = 0x0c; // Sublanguage: Australia see https://msdn.microsoft.com/en-au/goglobal/bb964664.aspx?f=255&MSPPError=-2147217396 for all valid hex locale ids
modified = true;
}
}
if (modified) {
fs.writeSync(fd, buffer, 0, buffer.length, 0);
console.log('Language Updated!');
} else {
console.log('US language not found. File NOT modified!');
}
fs.closeSync(fd);
} catch (err) {
console.log(`There was an error: ${err}`);
}
function keywordMatch(index) {
var i = 0;
while (i < keywordLength) {
if (keywordBuffer[i] === buffer[index]) {
i++;
index++;
} else {
return false;
}
}
return true;
}
Notes:
build.win.localeId = "0x0c09" where the user looks the locale id up manually ?Remaining Issues To Solve
NSIS
For NSIS installer we don't use rcedit. VIAddVersionKey (or another NSIS instruction) should be used instead.
I'm working on a fix to enable Windows users to set the default language of the App.exe, Setup.exe etc.
Does it matter? Where this key is used?
I've hard-coded the filename above for simplicity. This should accept a command-line arg
Script will be and should be used not as CLI, but as in-process. It can be integrated into electron-builder sources. But I don't like it — it is better just fix rcedit. We bundle own version of rcedit in any case (not from npm).
VIAddVersionKey (or another NSIS instruction) should be used instead.
I agree. In the past I had to create my own English_AU.nlf file and manually set the localeid (as explained here. Are you intending to implement this into electron-builder ? That would be great !
Where this key is used?
When the user opens or views the file properties (Properties->Details). Everything else electron-builder sets (file version, trademark etc) is listed there so why not language too ?
Does it matter?
It's not a deal breaker for myself (since English US is acceptable for English Australia where my company is located) but I would imagine it's more professional for devs who wish to release other than English.
Script will be and should be used
Makes it easier then.
it is better just fix rcedit
Sure, just trying to help ;)
Are you intending to implement this into electron-builder ? That would be great !
PR welcome. Thanks for info, I was not aware of that.
it is better just fix rcedit
I am afraid that your approach is not so robust as rcedit, so, it is better to fix rcedit than manually change bytes.
rcedit
I did attempt this at first, but my c++ skills are lacking (I've been using c# too long now!) and it made my head hurt
PR welcome. Thanks for info, I was not aware of that.
It shouldn't be too hard to automate a script to make a copy of the ${NSISDIR}\Contrib\Language Files\English.nlf file and set the localeid. Might have to investigate other language templates.
The same technique could be used for the ${NSISDIR}\Contrib\Contrib\Modern UI\Language files\English.nsh file too, instead updating the contents with MUI_LANGUAGEFILE_BEGIN "ENGLISH{{suffix}}".
I'll see what I can do, but I'm pretty short on time at the moment (I'm sure you are too!).
Found an easy fix for NSIS language setting (No need to create own language files etc).
Change src/targets/nsis.ts#L122-L130 From:
const versionKey = [
`ProductName "${appInfo.productName}"`,
`ProductVersion "${appInfo.version}"`,
`CompanyName "${appInfo.companyName}"`,
`LegalCopyright "${appInfo.copyright}"`,
`FileDescription "${appInfo.description}"`,
`FileVersion "${appInfo.buildVersion}"`,
]
use(this.packager.platformSpecificBuildOptions.legalTrademarks, it => versionKey.push(`LegalTrademarks "${it}"`))
To:
const localeId = appInfo.localeId; // arg from build.win (decimal)
const versionKey = [
`/LANG=${localeId} ProductName "${appInfo.productName}"`,
`/LANG=${localeId} ProductVersion "${appInfo.version}"`,
`/LANG=${localeId} CompanyName "${appInfo.companyName}"`,
`/LANG=${localeId} LegalCopyright "${appInfo.copyright}"`,
`/LANG=${localeId} FileDescription "${appInfo.description}"`,
`/LANG=${localeId} FileVersion "${appInfo.buildVersion}"`,
]
use(this.packager.platformSpecificBuildOptions.legalTrademarks, it => versionKey.push(`/LANG=${localeId} LegalTrademarks "${it}"`))
This now works without CRC check fail!
it is better to fix rcedit than manually change bytes.
Looking at the atom/rcedit source code, essentially they seem to just change bytes too.
your approach is not so robust as rcedit
I agree it appears hacky, but it works (it only changes 2-bytes). As long as you only use it on the files that you use rcedit for (i.e. non-NSIS) AND only use it BEFORE code-signing.
Remaining Issues To Solve - NSIS performs some sort of CRC check at startup
Now solved with the code above this comment by setting /LANG=${localeId} before each versionKey.
Since it's now possible to set the Language for all Windows targets with the above solutions I'm unlikely to do anymore work on this. I understand if you want to wait for an official rcedit solution.
language added to build.nsis.

Great. Small correction on your latest commit: you missed a /LANG=${localeId} on the trademark, which is outside of the versionKey array, just below in the use(this.packager.platformSpecificBuildOptions.legalTrademarks, ...)
I don't think this oversight results in changing anything though. But best to be complete. AFAIK it's the FileVersion that actually sets the language, but it's best to set them all.
Actually, it errors when build.nsis.language is set to something other than 1033 AND legalTrademarks is set (electron-builder 5.34.1):

(click to zoom)
Fix: Change src/targets/nsis.ts#L131 From:
use(this.packager.platformSpecificBuildOptions.legalTrademarks, it => versionKey.push(`LegalTrademarks "${it}"`))
To:
use(this.packager.platformSpecificBuildOptions.legalTrademarks, it => versionKey.push(`/LANG=${localeId} LegalTrademarks "${it}"`))
Also, small correction in docs/Options.md#L147. Change:
Hex LCID
To:
LCID Dec
NSIS expects decimal LCID (and I couldn't find any HEX->Decimal conversion in your code).
Ping @develar
Latest 6.3.0 release still erroring when legalTrademarks is set. See fix above.
(I would submit a PR but my dev env is windows, and currently broken)
Thanks @develar for the fast response!
However, I think the issue should still remain open until rcedit sets language too. Currently, only NSIS does.
Thanks for your amazing work!
However, I think the issue should still remain open until rcedit sets language too.
Moved to backlog, marked as help-wanted and closed. I really want to finish work on #529 and currently no short-terms plans to fix it :)
@develar is german the fallback language when a user's locale is rtl?
You posted German in this comment and our Hebrew users are seeing installer text in German.
Is there a workaround for this?
Can we set default fallback to English if user's OS language isn't supported?
btw specifically for Hebrew I can translate the text if that's all we need to get support for Hebrew language. I can't help with PR for rtl support tho, me don't know c++ :(
@goldylucks do you use latest electron builder?
updating tov20.24.4 seemed to do the trick, thanks @develar !!