Files
mazegame/tools/script/js/MSXloc.js
T

245 lines
6.2 KiB
JavaScript

//-----------------------------------------------------------------------------
// Get the first non empty character (not space or tab)
//=============================================================================
// DEFINES
//=============================================================================
const fs = require('fs');
//-----------------------------------------------------------------------------
// Contants
const version = "1.0.0";
const lineTypeSection = 1;
const lineTypeText = 2;
//-----------------------------------------------------------------------------
// Variables
var bVerbose = true;
var outFilename = "./localization.h";
var structName = "g_LocData";
var bComment = true;
//=============================================================================
// FUNCTIONS
//=============================================================================
//-----------------------------------------------------------------------------
//
function log(str)
{
if(bVerbose)
console.log(str);
}
//-----------------------------------------------------------------------------
// Get the first non empty character (not space or tab)
function getFirstChar(str)
{
for (var i = 0; i < str.length; i++)
if((str[i] != ' ') && (str[i] != '\t'))
return str[i];
return 0;
}
//-----------------------------------------------------------------------------
// Parse a line and return a descriptor according to line type
function getLineType(str)
{
var obj = {};
const chr = getFirstChar(str);
if(chr == '[')
{
const reg = /\[[ \t]*(?<section>[a-zA-Z0-9]+)[ \t]*\]/;
const res = str.match(reg);
if(res == null)
{
console.log(`Error: Invalid section! ${str}`);
return null;
}
obj['type'] = lineTypeSection;
obj['value'] = res.groups.section.toUpperCase();
}
else if(chr != 0)
{
const reg = /[ \t]*(?<key>[a-zA-Z0-9]+)[ \t]*\=[ \t]*"(?<value>[^"]+)"/;
const res = str.match(reg);
if(res == null)
{
console.log(`Error: Invalid text! ${str}`);
return null;
}
obj['type'] = lineTypeText;
obj['key'] = res.groups.key.toUpperCase();
obj['value'] = res.groups.value;
}
else
return null;
return obj;
}
//-----------------------------------------------------------------------------
// Parse a localisation file
function parseLocFile(filename, locTable)
{
log("Parsing " + filename + "...");
var lang = null;
const fileData = fs.readFileSync(filename, 'utf8');
const lines = fileData.split('\n');
for (var line = 0; line < lines.length; line++)
{
const obj = getLineType(lines[line]);
if(obj != null)
{
switch(obj.type)
{
case lineTypeSection:
if(obj.value != lang)
{
lang = obj.value;
}
break;
case lineTypeText:
if(locTable[lang] == null)
locTable[lang] = [];
locTable[lang][obj.key] = obj.value;
break;
}
}
}
}
//-----------------------------------------------------------------------------
// Display program usage and options
function displayHelp()
{
console.log("\nUsage:");
console.log("\tMSXloc file1.loc [file2.loc [...]] [options]");
console.log("\nOptions:");
console.log("\t-h Display this help");
console.log("\t--help");
console.log(`\t-o {filename} Select the output filename (default is '${outFilename}')`);
console.log("\t--output {filename}");
console.log("\t-v Activate verbose mode");
console.log("\t--verbose");
console.log(`\t-s {structname} Select the structure name (default is '${structName}')`);
console.log("\t--struct {structname}");
}
//=============================================================================
// Main programm
//=============================================================================
console.log(`MSXloc ${version}`);
//-- Setup command line overwrite parameters
var inputFiles = [];
var cmdArgs = process.argv.slice(2);
for(var i = 0; i < cmdArgs.length; i++)
{
const arg = cmdArgs[i];
if(arg[0] == '-')
{
switch(arg.toLowerCase())
{
case "-?":
case "-h":
case "--help":
displayHelp();
return;
case "-v":
case "--verbose":
bVerbose = true;
break;
case "-o":
case "--output":
outFilename = cmdArgs[++i];
break;
case "-s":
case "--struct":
structName = cmdArgs[++i];
break;
}
}
else
inputFiles.push(arg);
}
//-----------------------------------------------------------------------------
// Parse the input file
var locTable = [];
for(var i = 0; i < inputFiles.length; i++)
parseLocFile(inputFiles[i], locTable);
// log(locTable);
//-----------------------------------------------------------------------------
// Analyze localisation data
var langIDs = [];
var textIDs = [];
var langKeys = Object.keys(locTable);
for(var i = 0; i < langKeys.length; i++)
{
langIDs.push(langKeys[i]);
var textKeys = Object.keys(locTable[langKeys[i]]);
for(var j = 0; j < textKeys.length; j++)
if(!textIDs.includes(textKeys[j]))
textIDs.push(textKeys[j]);
}
// log(langIDs);
// log(textIDs);
//-----------------------------------------------------------------------------
// Generate header file
var i;
var headContent = `// Generated by MSXloc ${version}\n#pragma once\n#include "core.h"\n\n`;
headContent += "// Langage definition\n";
for(i = 0; i < langIDs.length; i++)
headContent += `#define LANG_${langIDs[i]} ${i}\n`;
headContent += `#define LANG_MAX ${i}\n\n`;
headContent += "// Text ID definition\n";
for(i = 0; i < textIDs.length; i++)
headContent += `#define TEXT_${textIDs[i]} ${i}\n`;
headContent += `#define TEXT_MAX ${i}\n\n`;
headContent += "// Localization data table\n";
headContent += `const c8* ${structName}[LANG_MAX][TEXT_MAX] =\n{\n`;
var langKeys = Object.keys(locTable);
for(var i = 0; i < langKeys.length; i++)
{
headContent += `\t// ${langKeys[i]}\n\t{\n`;
for(var j = 0; j < textIDs.length; j++)
{
if(locTable[langKeys[i]][textIDs[j]] == null)
{
headContent += `\t\tNULL,`;
log(`Warning: Text ID '${textIDs[j]}' not defined for langage '${langKeys[i]}'`);
}
else
headContent += `\t\t"${locTable[langKeys[i]][textIDs[j]]}",`;
if(bComment)
headContent += ` // TEXT_${textIDs[j]}`;
headContent += "\n";
}
headContent += `\t},\n`;
}
headContent += `};`;
// log(headContent);
fs.writeFileSync(outFilename, headContent);