Jump to content

LangGen - a Minecraft Language Generator


Simon_kungen
 Share

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
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.

 Share



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • [01:12:23] [01:12:23] [main/INFO]: ModLauncher running: args [--username, ytjasonsas, --version, release minecraft modde, --gameDir, C:\Users\jason\AppData\Roaming\.minecraft\versions\release minecraft modde, --assetsDir, C:\Users\jason\AppData\Roaming\.minecraft\assets, --assetIndex, 1.16, --uuid, 281b40fd-958f-11eb-90a8-d45d64bce613, --accessToken, ????????, --userType, mojang, --versionType, release, --width, 925, --height, 530, --launchTarget, fmlclient, --fml.forgeVersion, 36.2.39, --fml.mcVersion, 1.16.5, --fml.forgeGroup, net.minecraftforge, --fml.mcpVersion, 20210115.111550] [main/INFO]: ModLauncher 8.1.3+8.1.3+main-8.1.x.c94d18ec starting: java version 1.8.0_51 by Oracle Corporation [01:12:23] [main/WARN]: LEGACY JDK DETECTED, SECURED JAR HANDLING DISABLED [01:12:23] [main/INFO]: Added Lets Encrypt root certificates as additional trust [01:12:23] [main/INFO]: SpongePowered MIXIN Subsystem Version=0.8.4 Source=file:/C:/Users/jason/AppData/Roaming/.minecraft/libraries/org/spongepowered/mixin/0.8.4/mixin-0.8.4.jar Service=ModLauncher Env=CLIENT [01:12:25] [main/INFO]: Launching target 'fmlclient' with arguments [--version, release minecraft modde, --gameDir, C:\Users\jason\AppData\Roaming\.minecraft\versions\release minecraft modde, --assetsDir, C:\Users\jason\AppData\Roaming\.minecraft\assets, --uuid, 281b40fd-958f-11eb-90a8-d45d64bce613, --username, ytjasonsas, --assetIndex, 1.16, --accessToken, ????????, --userType, mojang, --versionType, release, --width, 925, --height, 530] [01:12:30] [main/INFO]: Environment: authHost='https://authserver.mojang.com', accountsHost='https://api.mojang.com', sessionHost='https://sessionserver.mojang.com', servicesHost='https://api.minecraftservices.com', name='PROD' [01:12:30] [main/INFO]: Setting user: ytjasonsas [01:12:31] [main/INFO]: Backend library: LWJGL version 3.2.2 build 10 [01:12:32] [main/FATAL]: Error during pre-loading phase net.minecraftforge.fml.ModLoadingException: fml.modloading.dupedmod     at net.minecraftforge.fml.ModLoadingException.lambda$fromEarlyException$0(ModLoadingException.java:50) ~[?:?]     at net.minecraftforge.fml.ModLoadingException$$Lambda$2937/1237743088.apply(Unknown Source) ~[?:?]     at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[?:1.8.0_51]     at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374) ~[?:1.8.0_51]     at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:512) ~[?:1.8.0_51]     at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:502) ~[?:1.8.0_51]     at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) ~[?:1.8.0_51]     at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) ~[?:1.8.0_51]     at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:1.8.0_51]     at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) ~[?:1.8.0_51]     at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:270) ~[?:1.8.0_51]     at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374) ~[?:1.8.0_51]     at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:512) ~[?:1.8.0_51]     at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:502) ~[?:1.8.0_51]     at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) ~[?:1.8.0_51]     at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:1.8.0_51]     at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) ~[?:1.8.0_51]     at net.minecraftforge.fml.ModLoader.<init>(ModLoader.java:106) ~[?:?]     at net.minecraftforge.fml.ModLoader.get(ModLoader.java:140) [?:?]     at net.minecraftforge.fml.client.ClientModLoader.lambda$begin$1(ClientModLoader.java:89) [?:?]     at net.minecraftforge.fml.client.ClientModLoader$$Lambda$2934/873769155.run(Unknown Source) [?:?]     at net.minecraftforge.fml.client.ClientModLoader.lambda$createRunnableWithCatch$4(ClientModLoader.java:109) [?:?]     at net.minecraftforge.fml.client.ClientModLoader$$Lambda$2935/919376773.run(Unknown Source) [?:?]     at net.minecraftforge.fml.client.ClientModLoader.begin(ClientModLoader.java:89) [?:?]     at net.minecraft.client.Minecraft.<init>(Minecraft.java:437) [?:?]     at net.minecraft.client.main.Main.main(Main.java:149) [?:?]     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_51]     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_51]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_51]     at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_51]     at net.minecraftforge.fml.loading.FMLClientLaunchProvider.lambda$launchService$0(FMLClientLaunchProvider.java:37) [forge-1.16.5-36.2.39.jar:36.2]     at net.minecraftforge.fml.loading.FMLClientLaunchProvider$$Lambda$416/1445758842.call(Unknown Source) [forge-1.16.5-36.2.39.jar:36.2]     at cpw.mods.modlauncher.LaunchServiceHandlerDecorator.launch(LaunchServiceHandlerDecorator.java:37) [modlauncher-8.1.3.jar:?]     at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:54) [modlauncher-8.1.3.jar:?]     at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:72) [modlauncher-8.1.3.jar:?]     at cpw.mods.modlauncher.Launcher.run(Launcher.java:82) [modlauncher-8.1.3.jar:?]     at cpw.mods.modlauncher.Launcher.main(Launcher.java:66) [modlauncher-8.1.3.jar:?] [01:12:32] [main/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.sound.SoundLoadEvent to a broken mod state [01:12:32] [main/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.ColorHandlerEvent$Block to a broken mod state [01:12:32] [main/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.ColorHandlerEvent$Item to a broken mod state [01:12:34] [main/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.ParticleFactoryRegisterEvent to a broken mod state [01:12:34] [main/INFO]: Narrator library for x64 successfully loaded [01:12:34] [main/INFO]: Reloading ResourceManager: Default [01:12:34] [Worker-Main-8/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Pre to a broken mod state [01:12:34] [Worker-Main-9/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Pre to a broken mod state [01:12:34] [Worker-Main-12/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.ModelRegistryEvent to a broken mod state [01:12:34] [Worker-Main-10/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Pre to a broken mod state [01:12:37] [Worker-Main-12/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Pre to a broken mod state [01:12:38] [Worker-Main-12/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Pre to a broken mod state [01:12:38] [Worker-Main-12/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Pre to a broken mod state [01:12:38] [Worker-Main-12/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Pre to a broken mod state [01:12:38] [Worker-Main-12/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Pre to a broken mod state [01:12:38] [Worker-Main-12/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Pre to a broken mod state [01:12:38] [Worker-Main-12/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Pre to a broken mod state [01:12:38] [main/INFO]: OpenAL initialized. [01:12:38] [main/INFO]: Sound engine started [01:12:39] [main/INFO]: Created: 1024x512x4 minecraft:textures/atlas/blocks.png-atlas [01:12:39] [main/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Post to a broken mod state [01:12:39] [main/INFO]: Created: 256x128x4 minecraft:textures/atlas/signs.png-atlas [01:12:39] [main/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Post to a broken mod state [01:12:39] [main/INFO]: Created: 512x512x4 minecraft:textures/atlas/banner_patterns.png-atlas [01:12:39] [main/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Post to a broken mod state [01:12:39] [main/INFO]: Created: 512x512x4 minecraft:textures/atlas/shield_patterns.png-atlas [01:12:39] [main/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Post to a broken mod state [01:12:39] [main/INFO]: Created: 256x256x4 minecraft:textures/atlas/chest.png-atlas [01:12:39] [main/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Post to a broken mod state [01:12:39] [main/INFO]: Created: 512x256x4 minecraft:textures/atlas/beds.png-atlas [01:12:39] [main/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Post to a broken mod state [01:12:39] [main/INFO]: Created: 512x256x4 minecraft:textures/atlas/shulker_boxes.png-atlas [01:12:39] [main/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Post to a broken mod state [01:12:40] [main/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.ModelBakeEvent to a broken mod state [01:12:40] [main/INFO]: Created: 256x256x0 minecraft:textures/atlas/particles.png-atlas [01:12:40] [main/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Post to a broken mod state [01:12:40] [main/INFO]: Created: 256x256x0 minecraft:textures/atlas/paintings.png-atlas [01:12:40] [main/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Post to a broken mod state [01:12:40] [main/INFO]: Created: 128x128x0 minecraft:textures/atlas/mob_effects.png-atlas [01:12:40] [main/ERROR]: Cowardly refusing to send event net.minecraftforge.client.event.TextureStitchEvent$Post to a broken mod state [01:12:40] [main/INFO]: [net.minecraft.crash.CrashReport:func_85057_a:196]: Negative index in crash report handler (23/26) [01:12:40] [main/FATAL]: Crash report saved to C:\Users\jason\AppData\Roaming\.minecraft\versions\release minecraft modde\crash-reports\crash-2022-12-09_01.12.40-fml.txt
    • Change your max fps to be larger than 0, either in the options menu or the options.txt
    • Solved, didn't see the inventoryTick method before writing this.
    • Problem solved . The mods need to be updated to the 1.19.3 version and rightly . The mods citadel, better animal plus , journey map all works fine . Only architectury doesn’t work even after the update . I sent them a message to make them aware of the situation . 
    • i installed java 8 after i read something online about it, how do i make sure it opens with java 8 and not java 19? since that seems to be the problem  
  • Topics

×
×
  • Create New...

Important Information

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