Jump to content

Guide for creating translatable mods


Recommended Posts

Hi everyone!

So there is a thing where many modders manually register their strings in their mods with Strings.Add(key, actual values), for each and every string entry they need. This method is fine for tiny mods, and mods that don't want to have translation support.
But for others, there isn't much resource on how to create translatable mods, so I wanted to share my way of doing it:

image.png.db487cce5f93387102dd25396570795f.png

First, simply create your own STRINGS class inside your own namespace, and mimicking the game's STRINGS:

using static STRINGS.UI;

namespace Curtain
{
    public class STRINGS
    {
        public class BUILDINGS
        {
            public class PREFABS
            {
                public class AC_PLASTICCURTAIN
                {
                    public static LocString NAME = FormatAsLink("Plastic Door", PlasticCurtainConfig.ID);
                    public static LocString DESC = "A transparent insulating door.";
                    public static LocString EFFECT = $"Quarters off dangerous areas and prevents gases" +
                        $" from seeping into the colony while closed, while allowing {FormatAsLink("Light", "LIGHT")}" +
                        $" and {FormatAsLink("Decor", "DECOR")} to pass through.\n\nDuplicants passing through will open the door for a short while, letting gases and liquids to pass through.";
                }
            }
        }
    }
}

And then in the Localization.Initialize patch where you would set those manual strings, instead you can do this:

using Harmony;
using KMod;
using System;
using System.IO;
using static Localization;

namespace TestObject
{
    class Patches
    {
        [HarmonyPatch(typeof(Localization), "Initialize")]
        public class Localization_Initialize_Patch
        {
            public static void Postfix() => Translate(typeof(STRINGS));
 
            public static void Translate(Type root)
            {
                // Basic intended way to register strings, keeps namespace
                RegisterForTranslation(root);
 
                // Load user created translation files
                LoadStrings();
 
                // Register strings without namespace
                // because we already loaded user transltions, custom languages will overwrite these
                LocString.CreateLocStringKeys(root, null);
 
                // Creates template for users to edit
                GenerateStringsTemplate(root, Path.Combine(Manager.GetDirectory(), "strings_templates"));
            }
 
            private static void LoadStrings()
            {
                string path = Path.Combine(ModPath, "translations", GetLocale()?.Code + ".po");
                if (File.Exists(path))
                    OverloadStrings(LoadStringsFile(path, false));
            }
        }
    }
}

My building now with the ID AC_PlasticCurtain gets these strings assigned, and it's translatable! Simply dropping a .po file into the translations folder in my mods folder will load up when the game is set to that language.

Prefabs like buildings will know automatically which one is theirs, just make sure your prefabs ID matches the class name in all caps. (AC_PlasticCurtain AC_PLASTICCURTAIN). 
 
Why register without and with namespace? 
Because many things in the game strongly expect STRING at the highest level of the key, and namespaced version will not work. but you can only export your templates with namespace, as you cannot create another STRINGS class inside root. Yes you could code something up to go around this, but this really isn't costing the game anything, and is much simpler to implement.
 
I hope this was helpful to some of you!
Let me know if you have feedback on how to further improve any of this or if you notice anything.
Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

Please be aware that the content of this thread may be outdated and no longer applicable.

×
  • Create New...