jspaint/localization/preprocess.js

97 lines
4.0 KiB
JavaScript
Raw Permalink Normal View History

2020-12-07 01:02:48 +00:00
const fs = require("fs");
const glob = require("glob");
2020-12-07 01:02:48 +00:00
const parse_rc_file = require("./parse-rc-file");
2020-12-07 01:02:48 +00:00
const base_lang = "en";
2022-01-19 14:59:49 +00:00
const available_langs = fs.readdirSync(__dirname).filter((dir) => dir.match(/^\w+(-\w+)?$/));
const target_langs = available_langs.filter((lang) => lang !== base_lang);
console.log("Target languages:", target_langs);
// @TODO: DRY hotkey helpers
// & defines accelerators (hotkeys) in menus and buttons and things, which get underlined in the UI.
// & can be escaped by doubling it, e.g. "&Taskbar && Start Menu"
function index_of_hotkey(text) {
// Returns the index of the ampersand that defines a hotkey, or -1 if not present.
// return english_text.search(/(?<!&)&(?!&|\s)/); // not enough browser support for negative lookbehind assertions
// The space here handles beginning-of-string matching and counteracts the offset for the [^&] so it acts like a negative lookbehind
return ` ${text}`.search(/[^&]&[^&\s]/);
}
function has_hotkey(text) {
return index_of_hotkey(text) !== -1;
}
function remove_hotkey(text) {
return text.replace(/\s?\(&.\)/, "").replace(/([^&]|^)&([^&\s])/, "$1$2");
}
const remove_ellipsis = str => str.replace("...", "");
2022-01-19 14:59:49 +00:00
const only_unique = (value, index, self) => self.indexOf(value) === index;
2020-12-13 16:40:47 +00:00
2022-01-19 14:59:49 +00:00
const get_strings = (lang) => {
2020-12-13 02:30:01 +00:00
return glob.sync(`${__dirname}/${lang}/**/*.rc`).map(
2022-01-19 14:59:49 +00:00
(rc_file) => parse_rc_file(fs.readFileSync(rc_file, "utf16le").replace(/\ufeff/g, ""))
2020-12-13 02:30:01 +00:00
).flat();
2020-12-07 01:02:48 +00:00
};
2020-12-07 01:02:48 +00:00
const base_strings = get_strings(base_lang);
for (const target_lang of target_langs) {
2020-12-07 01:02:48 +00:00
const target_strings = get_strings(target_lang);
const localizations = {};
2022-01-19 14:59:49 +00:00
const add_localization = (base_string, target_string, fudgedness) => {
2020-12-13 16:40:47 +00:00
localizations[base_string] = localizations[base_string] || [];
2022-01-19 14:59:49 +00:00
localizations[base_string].push({ target_string, fudgedness });
};
2022-01-19 14:59:49 +00:00
const add_localizations = (base_strings, target_strings) => {
2020-12-07 17:38:42 +00:00
for (let i = 0; i < target_strings.length; i++) {
const base_string = base_strings[i];
const target_string = target_strings[i];
if (base_string !== target_string && base_string && target_string) {
// Split strings like "&Attributes...\tCtrl+E"
// and "Fills an area with the current drawing color.\nFill With Color"
const splitter = /\t|\r?\n/;
if (base_string.match(splitter)) {
2020-12-07 17:38:42 +00:00
add_localizations(
base_string.split(splitter),
target_string.split(splitter)
2020-12-07 17:38:42 +00:00
);
} else {
// add_localization(base_string, target_string, 0);
2020-12-13 16:40:47 +00:00
add_localization(remove_ellipsis(base_string), remove_ellipsis(target_string), 1);
if (has_hotkey(base_string)) {
// add_localization(remove_hotkey(base_string), remove_hotkey(target_string), 2);
2020-12-13 16:40:47 +00:00
add_localization(remove_ellipsis(remove_hotkey(base_string)), remove_ellipsis(remove_hotkey(target_string)), 3);
2020-12-07 01:02:48 +00:00
}
}
}
}
2020-12-07 17:38:42 +00:00
};
add_localizations(base_strings, target_strings);
2020-12-13 16:40:47 +00:00
for (const base_string in localizations) {
const options = localizations[base_string];
2022-01-19 14:59:49 +00:00
options.sort((a, b) => a.fudgedness - b.fudgedness);
const unique_strings = options.map(({ target_string }) => target_string).filter(only_unique);
2020-12-13 16:40:47 +00:00
if (unique_strings.length > 1) {
console.warn(`Collision for "${base_string}": ${JSON.stringify(unique_strings, null, "\t")}`);
}
localizations[base_string] = unique_strings[0];
}
const js = `//
// NOTE: This is a generated file! Don't edit it directly.
// Eventually community translation will be set up on some translation platform.
//
// Generated with: npm run update-localization
//
loaded_localizations("${target_lang}", ${JSON.stringify(localizations, null, "\t")});\n`;
fs.writeFileSync(`${__dirname}/${target_lang}/localizations.js`, js);
2020-12-07 01:02:48 +00:00
}
Greatly improve localization automation workflow Workflow previously: - find and download VM image - Internet Archive / WinWorldPC - make sure of language code (for instance, dk was actually da under the ISO standard) - https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes - move/rename so it's clear what it is - renaming it after creating the VM is complicated because it'll break virtualbox file references - in command line, `bash ./localization/install-windows-98.sh <language code> ` - drag and drop iso into command line to complete the command - attempt the command, and if it doesn't work, try other product keys or update the script as needed or install manually - close VM - in command line, `bash ./localization/grab-files-from-vm.sh <language code> ` - drag and drop vdi into command line to complete the command - run desktop automation, pressing Down at the appropriate time if there's a media notification like for YouTube - close window - go into Windows 10 VM - find the new mspaint.exe - right click, open resource tuner - wait for it to load - click the save multiple (batch export) button - hit Next - choose directory `Z:\extracted-resources\<language code>\mspaint`, creating the directories as needed - hit Finish - close window - pause VM - go to `/home/io/Downloads/Windowses/VirtualBox VMs/Win10 Share/extracted-resources/<language code>/mspaint` - select Dialog, Menu, and String Table for now, maybe Accelerator Table later - copy it to `/home/io/Projects/jspaint/localization/<language code>`, creating directory as needed - run `npm run update-localization` - add language to list of available languages in index.html (may become localization.js at some point) - test the new language - commit Workflow now: - find and download VM image - Internet Archive / WinWorldPC - make sure of language code (for instance, dk was actually da under the ISO standard) - https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes - move/rename so it's clear what it is - renaming it after creating the VM is complicated because it'll break virtualbox file references - in command line, `bash ./localization/install-windows-98.sh <language code> ` - drag and drop iso into command line to complete the command - attempt the command, and if it doesn't work, try other product keys or update the script as needed or install manually - close VM - in command line, `bash ./localization/grab-files-from-vm.sh <language code>` - run desktop automation, pressing Down at the appropriate time if there's a media notification like for YouTube - test the new language - commit
2020-12-13 21:12:36 +00:00
// Update available_languages list automatically!
const file = require("path").resolve(__dirname + "/../index.html");
let code = fs.readFileSync(file, "utf8");
code = code.replace(/(available_languages\s*=\s*)\[[^\]]*\]/, `$1${JSON.stringify(available_langs).replace(/","/g, `", "`)}`);
fs.writeFileSync(file, code, "utf8");
console.log(`Updated available_languages list in "${file}"`);