Jump to content

LangGen - a Minecraft Language Generator


Simon_kungen

Recommended Posts

Introduction:

 

This is not really a tutorial per se, but as this fits the bill the best, here we are.

 

I got sick of having to manually create new lines for, and every, new item and block in the language file. Sure copy-pasting and run a replace search did kind of solve the issue, but it was still very tedious. So I sat down and made a generator tool written in JavaScript for Node.js. And that is what this post is about.

 

Requirements:

 

You will need Node.js installed on your system if you want to run it locally, but I'm sure there is an online version you can run from too. Anyways, the program needs a Json blueprint from which it will generate all the finished language translations. A generic one is in a spoiler down here:

 

Tutorial:

 

{

    "domain": "examplemod",

    "types": [
        { "ingot" : "%s Ingot" },
        { "nugget" : "%s Nugget" },
        { "dust" : "%s Dust" },
        { "plate" : "%s Plate" },
        { "gear" : "%s Gear" },
        { "block" : "%s Block", "flag" : "block" },
        { "frame" : "%s Frame", "flag" : "block" },
        { "ore" : "%s Ore", "flag" : "ore" }
    ],

    "elements": [
        { "silver" : "Silver" },
        { "gold" : "Gold",
            "filter": [ "ingot","nugget","block","ore" ]
        },
        { "copper" : "Copper" },
        { "iron" : "Iron",
            "filter": [ "ingot","nugget","block","ore" ]
        },
        { "lead" : "Lead" },
        { "tin" : "Tin" }

    ]
}

 

Ok, so what's going on here? The "domain" is your mod's name, that can be anything. Then there are the array "types", it is what type of item you want to make a translation of off. It first needs a name as the key, and then the translation. It is important you have the "%s" symbol in there as that is what is going to be replaced with an entry in the "types" array. You can change however you want of the translated key, as long as it has the "%s" in it. A second optional argument called "flag" can be used. Not sure if you're like me, but I do like to have some structure in my language files, so types with the same flag will be grouped in the output file (if enabled). And if you have it be the same in the program options' blockKeywords array it will automatically make it a block contrary to item. By default, it will make types with the flag "block" or "ore" to be blocks in the output file.

 

In the "elements" array is what materials you want them in. It first needs a key and then a translated version of it. There is an optional argument too called "filter". It is an array of types you don't want translated, ex. you might not want to make a translation for Iron Ingot as Minecraft already adds that, so adding "ingot" in the filter array it will not generate in the output file. Something to note is if it has the keyword "none" it will skip over it entirely, might only be useful in very particular cases like if you go by a pre-decided dictionary.

 

 

In the program (index.js) there are a few options you can tweak, but I have already explained what they do in the file so I'm going to skip that and explain how on to set up the program:

After you've extracted the program you should just have to open the command prompt and type "node .". "node" is the program, and the "." tells it to use the package.json in that directory. If everything worked as intended it should have created a new file in "output/" with the same name as the input file in "input/".

 

Technical part:

 

When creating the language key, it first decides between using "item." or "block.", thereafter the domain. The item/block key name is generated by first using the key name, then dividing it with a "_" and the type key. Example:

Domain: "buildcraftcore"

Type: "gear"

Element: "gold"

"item.buildcraftcore.gold_gear" : "Gold Gear"

 

Download:

 

LangGen.zip

 

The plain index.js file

/**
 * A tool to generate language translations for blocks and items for my Minecraft mods
 * with similar names from a Json file blueprint. A high degree of customization of the Json
 * is possible to generate a large amount of different translations with language keys in specified order
 * ready for file transfer or manually copy-paste into desired language file, written in JavaScript in Node.js.
 *
 * By Simon
 */

const fs = require('fs');


const lang          = 'en_us.json'; // Change this to the desired language file name in input/.
const spacing       = 2;            // The desired spacing in the output file (recom. 2 or 4).
const separated     = true;         // If the flagged types should be separated or mixed in the output file.
const logging       = false;        // Whenever it should write out the language key to the console.
const blockKeywords = [             // If a flag matches a word here it will change the language key to be a block.
    'block', 'ore'
]

//////////////////////// Don't edit below this unless you know what you're doing ////////////////////////

fs.readFile('input/' + lang, (err,data) => {
    if (err) throw err;
    const json = JSON.parse(data);

    let JSONObjects = [{}];

    json.elements.forEach(element => {

        for (let i in json.types) {

            let shouldSkip = false;
            if (element.filter)
                for (var j=0;j<element.filter.length;j++) {
                    if (element.filter[j] == Object.keys(json.types[i])[0] || element.filter[j] == 'none') {
                        shouldSkip = true;
                        break;
                    }
                }
            

            if (shouldSkip) continue;

            let translation = json.types[i][Object.keys(json.types[i])[0]];
            let keyword = json.domain + "." + Object.keys(element)[0] + "_" + Object.keys(json.types[i])[0];

            translation = translation.replace("%s", element[Object.keys(element)[0]]);

            let t = blockKeywords.includes(json.types[i].flag) ? 'block.' : 'item.';

            if (logging) {
                console.log(line(t + keyword, translation));
            }


            if (separated) {
                let index = 0;
                if (json.types[i].flag) {
                    index = json.types[i].flag;
                    if (JSONObjects[index] == undefined) {
                        JSONObjects[index] = {};
                    }
                }                
                JSONObjects[index][t + keyword] = translation;
            }
            else
                JSONObjects[0][t + keyword] = translation;
        }
    });

    fs.readFile('output/' + lang, (err, data) => {

        const text = JSON.stringify(separated ? merge(JSONObjects) : JSONObjects[0], null, spacing);

        if (!err)
            if (text == data.toString()) {
                console.log('No changes to output/' + lang);
                return;
            }
        
        fs.writeFileSync('output/' + lang, text);
        console.log('Wrote to output/' + lang);
    });
});
function line(a,b) { return "\"" + a + "\" : \"" + b + "\"" }
function merge(a) { const r = {};Object.keys(a).forEach(j => Object.keys(a[j]).forEach(key => r[key] = a[j][key]));return r; }

 

Edited by Simon_kungen
Spoilers are bugged here for some reason, removed them*.
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.