[Utility] Strings encoder for adding new strings (new ids and keys) as standalone w3strings file

+
[Utility] Strings encoder for adding new strings (new ids and keys) as standalone w3strings file

Hello everybody,

here's a w3strings cli decoder / encoder for adding new strings (new ids and optionally string keys) as standalone w3string files to your mods. It's compiled for 64bit windows (If anyone wants the sourcecode pm me. Caveat: I took this opportunity to finally take a first look at rust. So there are a couple of things where I have no idea why I had to do it this way)

The usage is simple (there is a --help option, too): it decodes a w3strings file to a csv file and it encodes csv files (utf8!) with this format to a w3strings file. The resulting [language].w3strings file must be put directly into the contents directory of the mod/dlc mod. An example csv is provided with some info.

However a couple of things may need some further explanation.

Restriction of id space
I intentionally restricted the useable string id space to prevent multiple mods to overwrite strings of other mods. The idspace is partitioned in 1000 bins and starts at 2110000000. This means to encode a csv file you have to provide an idspace number n between 0 and 9999. The encoder then checks if the ids used in the csv file are between 211nnnn000 and 211nnnn999. 1000 ids per file "should be enough for everybody" :)

I suggest you use your nexusmods mod id. This way at least the nexus mods will play nice with each other.

But there is also a manual override switch if you know what you are doing...

Usage of string keys
Localized strings can be accessed either by id and (if a mapping exists) by a string key, eg for menu strings, items, etc. The games "hashing" algorithm of the keys is simple and it produces collisions. There are multiple "key strings" which map to the same strings. So use keys sparingly and only if you need them. And if a collision happens: modify your key somehow.

String keys are not case-sensitive and they cannot be obtained from key hashes, don't forget them. Also I restricted the characters for key definitions to: a-z0-9_

Overwrite game strings

You can overwrite strings from the game in a standalone w3strings file by reusing the original id. The last string loaded with the same id will be used in the game. Also any string with a key mapping can be overriden by using a *different* id but the *same* key hash: the last string loaded with the same hash will be used in the game. There is an example in the provided csv.

Generation of test script
The encoder generates a ws script file to test the availability of the strings to game scripts. It contains a console function "test_verifyW3strings" which requests the localized string for every id and every key in the encoded csv and compares it to your definition. The results are logged in the script log and a HUF message is generated is any string didn't match.

The ws file must be put into the mods scripts folder and is meant only for local testing as it doesn't use the id space number to generate a "unique" function name (hmm, might have thought of that earlier... oh well.) There is a second file included which provides some required assert and log functions (from my modBaseUtils). Put it into a scripts folder, too.

Known issues
  • I tested mostly en files. For the other languages I decoded, reencoded and binary compared the reencoded file with the original w3strings file. For some languages (jp, kr, zh) a couple of game files differ. I *think* the problem may be UTF8<->UTF16 conversion issues but well... my jp, kr and zh are a bit too rusty to figure it out. I'll investigate if there is any "real-world" demand...
  • The above binary compare fails for every language on patch0 and patch1 (v1.11) w3strings in at least one of them. A quick look at some diffs revealed that those files contain multiple dupe definitions. So it seems in these cases sorting is different but I haven't looked further. Again, I'll investigate if it turns out to be a "real-world" problem.

If you encounter issues pm me.

Some output for example:

w3strings.exe --encode example.en.csv --id-space 9999

w3strings decoder/encoder v0.2.1
INFO - ENCODING example.en.csv to example.en.csv.w3strings (testscript: example.en.csv.w3strings.ws)
INFO - opening example.en.csv...
INFO - identified language: en
INFO - verifying string ids are within [2119999000..2119999999]
INFO - creating example.en.csv.w3strings...
INFO - storing language: en
INFO - storing 7 strings
INFO - creating example.en.csv.w3strings.ws...

w3strings.exe --decode example.en.csv.w3strings

w3strings decoder/encoder v0.2.1
INFO - DECODING example.en.csv.w3strings to example.en.csv.w3strings.csv
INFO - opening example.en.csv.w3strings...
INFO - identified language: en
INFO - found 7 strings
INFO - found 5 string key mapping infos
INFO - creating example.en.csv.w3strings.csv...
INFO - storing 7 strings

w3strings.exe v0.3.3
size: 4650080 bytes
md5: e57af93653bdaa33d4cfe4569252156e
sha256: 833d577d9b49906c85980732e77f2f3d84dbcf0551affd556162a9975c29df3b

link to nexusmods

Have fun.
 
Last edited:
Hey bro, have a good day firstly and thanks for this great mod. But i didn't understand the mechanics of this system. Let's say i want to put a new option to the MAIN Menu, let's say, My Favorite Books tab. How can i do that? I know that such thing would need a new string code but i dont know to put it in the game, where i wanted it to be. :skepticalzoltan:
 
Hey bro, have a good day firstly and thanks for this great mod. But i didn't understand the mechanics of this system. Let's say i want to put a new option to the MAIN Menu, let's say, My Favorite Books tab. How can i do that? I know that such thing would need a new string code but i dont know to put it in the game, where i wanted it to be. :skepticalzoltan:

Well, as you write the w3strings files are just a container for localized strings and doesn't enable any functionality.

Menu extension is not really my area of expertise. But I got curious how the menu can be extended and took a quick look at one of the mods which already modify the menu (CAPA14's AMM). I poked around a bit to figure out how to actually use localized strings in new menu options.

Turn's out it's not that difficult, but it seems you can only extend the option panel. So maybe not the thing you are looking for. Anyway here's a short how-to:

1. create a modXsettings.xml in the bin/config/r4game/user_config_matrix/pc directory of the game installation

PHP:
<?xml version="1.0" encoding="UTF-16"?>
<UserConfig>
    <!-- This creates panel_mods and a subpanel panel_modx. displayName is case sensitive for subpanel creation
            (mods.modX and MODS.modX create too entries under options) but not case sensitive for the string key -->
    <Group id="modX" displayName="mods.modX">
        <VisibleVars>
            <!-- do not include the tag "nonLocalized" for any option -->
            <Var id="modX_toggle1_id" displayName="modX_toggle1" displayType="TOGGLE"/>
            <!-- customDisplayName => string key is "modX_option1" otherwise "option_modX_option1" -->
            <Var id="modX_option1_id" displayName="modX_option1" displayType="OPTIONS" tags="customNames;customDisplayName">
                <OptionsArray>
                    <Option id="0" displayName="modX_option1_value0">
                        <Entry varId="modX_option1_id" value="0"/>
                    </Option>
                    <Option id="1" displayName="modX_option1_value1">
                        <Entry varId="modX_option1_id" value="1"/>
                    </Option>
                </OptionsArray>
            </Var>
            <Var id="modX_slider1_id" displayName="modX_slider1" displayType="SLIDER;5;20;3"/>
        </VisibleVars>
    </Group>
</UserConfig>

2. create w3strings file with the used string keys

en.modXsettings.csv:
PHP:
;meta[language=en]
; id      |key(hex)|key(str)| text
2119999100|        |panel_mods|My Mods Panel
2119999101|        |panel_modX|My Favorite Books
2119999102|        |option_modX_toggle1|Mod X Setting Toggle 1
2119999103|        |modX_option1|Mod X Setting Option 1
2119999104|        |modX_option1_value0|Mod X Option 1 Value 0
2119999105|        |modX_option1_value1|Mod X Option 1 Value 1
2119999106|        |option_modX_slider1|Mod X Slider 1
w3strings --encode en.modXsettings.csv --id-space 9999

3. rename file to en.w3strings and put it in the contents/scripts/ folder of your mod

That's it. And this is how you get the chosen setting in one of your scripts:

PHP:
// defined as a console command
exec function test_modXSetting() {
    var conf: CInGameConfigWrapper;
    var value: String;
    
    conf = theGame.GetInGameConfigWrapper();
    
    // groupid, varid
    value = conf.GetVarValue('modX', 'modX_option1_id');
    GetWitcherPlayer().DisplayHudMessage("currently set modX_option1_id value: " + value);
}

For debugging you can set the option "UsePlaceholdersForMissingStrings" in bin/config/base/localization.ini to true.
This will show the used string keys for all localized strings which are not found (instead of empty strings).

For further infos (especially if you want to make more complex settings) I suggest you look into the xml of AMM and others mods.

There's also a sticky thread with HOW-TOs for various topics which may give more insights.

Hope that helped.
 
Last edited:
For decoding is it possible to get the key(str) back out of w3strings files? Thanks a lot.
Sorry, this is not possible. The used hashing function maps multiple key(str) to one key(hex).

What you are asking for is roughly: if I give you a number (say 10) tell me what two numbers I added to get the number. In case of 10 there are only a few combinations which you could try by "brute force" and pick any one. But in the case of the key(str/hex) there are way too many combinations possible.

If you desperately want to figure out a specific str(key) you can try to set the "UsePlaceholdersForMissingStrings" option in bin/config/base/localization.ini to true and rename *all* w3strings files to something like en.w3strings.bak. Then start the game and look what placeholder is used for the string you want the str(key) for. This should be the str(key) if I remember correctly.
 
Sorry, this is not possible. The used hashing function maps multiple key(str) to one key(hex).

What you are asking for is roughly: if I give you a number (say 10) tell me what two numbers I added to get the number. In case of 10 there are only a few combinations which you could try by "brute force" and pick any one. But in the case of the key(str/hex) there are way too many combinations possible.

If you desperately want to figure out a specific str(key) you can try to set the "UsePlaceholdersForMissingStrings" option in bin/config/base/localization.ini to true and rename *all* w3strings files to something like en.w3strings.bak. Then start the game and look what placeholder is used for the string you want the str(key) for. This should be the str(key) if I remember correctly.

Fantastic suggestion. Thanks.
 
Hey,wanna use your utility to localize all my new added stuff from "The Enhancement System" . You said your utility would decode a w3strings to an csv file and backwards,but I have found nothing in the internet which describes how to create an w3strings file.Or is it supposed to modify the games w3string and add them back to make the mod work?
Also,in the xmls,I tricked the game by changing the localized_key_name of each added stuff,I have manually written the names in english into it,like that:


Since your tutorial is very well written,but needs basic knowledge about how the systems working,I really dont have a clue what to do to translate my mod.Maybe you have the patience to explain it a little bit more noobish for me,as I have no clue how to create w3strings for it.Till now there are no textures my mod adds,so no new mapping/strings as you described seem to be integrated.I just made duplicates of existing things,renamed them/gave new stats/abilitys.In Short:I took existing things and modified everything what I needed,including changing the names in localisation_key_name.For first my mod was just usable with UsePlaceholdersForMissingStrings=true,but then uacvax modified his Custom Localization Fix Mod to get my mod running without changed inis.

I would appreciate any help,there was even a new tool added to nexus today,which should be used with this tool together:http://www.nexusmods.com/witcher3/m...3/ajax/moddescription/?id=1203&preview=&pUp=1

Basically it adds a GUI to your tool.
 

Attachments

  • Screenshot (11).png
    Screenshot (11).png
    201.3 KB · Views: 634
Last edited:
Hey,wanna use your utility to localize all my new added stuff from "The Enhancement System" . You said your utility would decode a w3strings to an csv file and backwards,but I have found nothing in the internet which describes how to create an w3strings file.Or is it supposed to modify the games w3string and add them back to make the mod work?
To create a w3strings file you need a csv file with string definitions. Whether the csv is created by decoding an already present game w3strings file or created manually doesn't matter. The provided example.en.csv was created manually.

The used ids and key(str) determine if existing game strings are changed or if new strings are available:

  • If you decode a w3strings file from the game you get a csv with ids from the game. Just changing the text in the text column and encoding the csv to a w3strings file (and adding it to your mods content directory) will *change* the displayed strings of the referenced strings in the game. Meaning your changed strings "overlay" the original strings of the game.

  • If you decode a w3strings file from the game into a csv and change the ids to some ids that are not used in the game until now (or create a csv from scratch with new ids) then those strings do not overlay any strings from the game. And thus these *new* strings can be accessed by your mod by your defined ids.

The same goes for the key(hex)/key(str) column: if you use any from the game every time the game asks for the string with the key(str) it will display your changed strings. If you define new key(str) the game strings are not overlayed and you can access your strings by your key(str).

The important part here is: choose ids from an unsed id space (see above) and if required unused key(str).

I hope this cleared some things up.

Since your tutorial is very well written,but needs basic knowledge about how the systems working,I really dont have a clue what to do to translate my mod.Maybe you have the patience to explain it a little bit more noobish for me,as I have no clue how to create w3strings for it.
As far as I understand your request: You want to add/change the names and descriptions of items. If so the general idea is something like this:

1. Change the "localisation_key_name" and "localisation_key_description" of the item in the xml to some unique name only your mod uses, e.g. something prefixed by your mod acronym or id. This will be the key(str).
def_item_crafting_armor.xml:
PHP:
<!-- ... -->
<item
    <!-- ... -->
    localisation_key_name = "modtes_item_name_blackviper_armor4" 
    localisation_key_description = "modtes_item_category_blackviper_armor4_description" 
    <!-- ... -->
</item>
<!-- ... -->

2. Create a csv file, choose an id-space for you mod (e.g. your nexus mod id 1112) and add your localized strings with the new id and new key(str) into the csv.
en.modtest.csv:
PHP:
;meta[language=en]
; id      |key(hex)|key(str)| text
2111112000|        |modtes_item_name_blackviper_armor4|Legendary Dark Viper Armor
2111112001|        |modtes_item_category_blackviper_armor4_description|Legendary Dark Viper Armor Description

3. Encode and put into the content folder of your mod.
w3strings --encode en.modtest.csv --id-space 1112

This should work but I haven't tested. It would be nice if you can confirm it worked.

Till now there are no textures my mod adds,so no new mapping/strings as you described seem to be integrated.
Textures have nothing to do with strings. I don't understand what you mean.

I would appreciate any help,there was even a new tool added to nexus today,which should be used with this tool together:http://www.nexusmods.com/witcher3/m...3/ajax/moddescription/?id=1203&preview=&pUp=1

Basically it adds a GUI to your tool.
Yes I've seen it. Tailored for specific usecases but it seems very useful.
 
So,I did all what you said,and had a lot of help by DJ_Kovrik who is advanced in using your tool,but anything without sucess.I can see the strings with the test,but the items themselves have no/vanilla names.Here some pictures:
I am really getting headaches with that,as I did exactly as you both said.My created en.w3strings and de.w3strings lay directly in the content folder of my mod.This is what I did exactly:

I changed in every xml JUST the localisation_key_name,nothing else.Everyone Begins with TES,between every word are no spaces but underscores,and every new word has a big letter at the start,like this: TES_Enhanced_Viper_Kaer_Morhen_Armor.My test csv file looks like this:
;meta[language=en]
; id |key(hex)|key(str)| text
2111112000| |TES_Viper_Kaer_Morhen_Armor|Viper Kaer Morhen Armor
2111112001| |TES_Legendary_Viper_Kaer_Morhen_Armor|Legendary Viper Kaer Morhen Armor
2111112002| |TES_Viper_Kaer_Morhen_Boots|Viper Kaer Morhen Boots
2111112003| |TES_Legendary_Viper_Kaer_Morhen_Boots|Legendary Viper Kaer Morhen Boots
2111112004| |TES_Viper_Kaer_Morhen_Gloves|Viper Kaer Morhen Gloves
2111112005| |TES_Legendary_Viper_Kaer_Morhen_Gloves|Legendary Viper Kaer Morhen Gloves
2111112006| |TES_Viper_Kaer_Morhen_Pants|Viper Kaer Morhen Pants
2111112007| |TES_Legendary_Viper_Kaer_Morhen_Pants|Legendary Viper Kaer Morhen Pants
After that,I used a batch file to reimport,putted the w3strings file directly into the content direction of my mod,and the created .ws file + TestUtils.ws in the script directory (I tried it without both scripts too).However,in the .ws file were those messages after using the batch file:
// autogenerated tests for w3strings (require modBase-Utils)
// language: en

function _test_verifyW3strings() : int {
var failed: int;
failed = 0;

// test by id
if (!assertTrue(GetLocStringById(2111112000) == "Viper Kaer Morhen Armor", "w3string.byId: 2111112000")) failed += 1;
if (!assertTrue(GetLocStringById(2111112001) == "Legendary Viper Kaer Morhen Armor", "w3string.byId: 2111112001")) failed += 1;
if (!assertTrue(GetLocStringById(2111112002) == "Viper Kaer Morhen Boots", "w3string.byId: 2111112002")) failed += 1;
if (!assertTrue(GetLocStringById(2111112003) == "Legendary Viper Kaer Morhen Boots", "w3string.byId: 2111112003")) failed += 1;
if (!assertTrue(GetLocStringById(2111112004) == "Viper Kaer Morhen Gloves", "w3string.byId: 2111112004")) failed += 1;
if (!assertTrue(GetLocStringById(2111112005) == "Legendary Viper Kaer Morhen Gloves", "w3string.byId: 2111112005")) failed += 1;
if (!assertTrue(GetLocStringById(2111112006) == "Viper Kaer Morhen Pants", "w3string.byId: 2111112006")) failed += 1;
if (!assertTrue(GetLocStringById(2111112007) == "Legendary Viper Kaer Morhen Pants", "w3string.byId: 2111112007")) failed += 1;

// test by key
if (!assertTrue(GetLocStringByKey("TES_Viper_Kaer_Morhen_Armor") == "Viper Kaer Morhen Armor", "w3string.byKey: TES_Viper_Kaer_Morhen_Armor")) failed += 1;
if (!assertTrue(GetLocStringByKey("TES_Legendary_Viper_Kaer_Morhen_Armor") == "Legendary Viper Kaer Morhen Armor", "w3string.byKey: TES_Legendary_Viper_Kaer_Morhen_Armor")) failed += 1;
if (!assertTrue(GetLocStringByKey("TES_Viper_Kaer_Morhen_Boots") == "Viper Kaer Morhen Boots", "w3string.byKey: TES_Viper_Kaer_Morhen_Boots")) failed += 1;
if (!assertTrue(GetLocStringByKey("TES_Legendary_Viper_Kaer_Morhen_Boots") == "Legendary Viper Kaer Morhen Boots", "w3string.byKey: TES_Legendary_Viper_Kaer_Morhen_Boots")) failed += 1;
if (!assertTrue(GetLocStringByKey("TES_Viper_Kaer_Morhen_Gloves") == "Viper Kaer Morhen Gloves", "w3string.byKey: TES_Viper_Kaer_Morhen_Gloves")) failed += 1;
if (!assertTrue(GetLocStringByKey("TES_Legendary_Viper_Kaer_Morhen_Gloves") == "Legendary Viper Kaer Morhen Gloves", "w3string.byKey: TES_Legendary_Viper_Kaer_Morhen_Gloves")) failed += 1;
if (!assertTrue(GetLocStringByKey("TES_Viper_Kaer_Morhen_Pants") == "Viper Kaer Morhen Pants", "w3string.byKey: TES_Viper_Kaer_Morhen_Pants")) failed += 1;
if (!assertTrue(GetLocStringByKey("TES_Legendary_Viper_Kaer_Morhen_Pants") == "Legendary Viper Kaer Morhen Pants", "w3string.byKey: TES_Legendary_Viper_Kaer_Morhen_Pants")) failed += 1;

// return number of failed
return failed;
}

exec function test_verifyW3Strings() {
logTestResult("Verify W3Strings", _test_verifyW3strings(), true);
}

Till I get some serious help,my mod stands still :/ Through changing all the names in the xmls for the localisation,I damaged my mod when this localising wont work.I really would appreciate any help,so that the work of the last week wasnt for nothing...

---------- Post merged on 02-02-2016 at 06:45 AM ----------

UPDATE: Today I have achieved that all strings are displayed properly in the items.However,the game language doesnt change,no matter how many strings for different languages I have and in which language I play,the strings are always displayed just in english (like I defined them). Do I need any scripts or data to make the w3strings working correctly for each language?
PS: To create strings for different languages,I just copy and pasted the english string to another place,renamed it to de.w3strings (for example), and put that data back in the content directory of mod.Is this wrong?I mean,just copy,paste and renaming sounds too easy

---------- Updated at 08:01 AM ----------

Another EDIT: I was the meaning that my english added strings could be automatically translated into other languages with your or some other tool.But it seems that every language has to be manually written,thats too bad.But I guess this is how it works.Witcher 3 modding really has its awkward limits compared to other games.
Thanks for your Guide and tool :)
 

Attachments

  • PM8SCG.jpg
    PM8SCG.jpg
    81.9 KB · Views: 570
  • Z6FHY.jpg
    Z6FHY.jpg
    80.5 KB · Views: 379
  • xapd9Bb.jpg
    xapd9Bb.jpg
    305.8 KB · Views: 335
Glad it finally worked for you. To help I'd need to try it out for myself but that would have been next WE at the earliest. Can you confirm the posted howto is correct or is there anything I can add to clear it up for others?

After that,I used a batch file to reimport,putted the w3strings file directly into the content direction of my mod,and the created .ws file + TestUtils.ws in the script directory (I tried it without both scripts too).However,in the .ws file were those messages after using the batch file:
For the record: the script files are NOT needed in any way for the strings to work. They provide just a quick way to test if the strings are available within the game.

PS: To create strings for different languages,I just copy and pasted the english string to another place,renamed it to de.w3strings (for example), and put that data back in the content directory of mod.Is this wrong?I mean,just copy,paste and renaming sounds too easy
Every language needs a differently encoded w3strings file. And no, there is no automatic language translation involved :) But you can reuse the csv by changing the language key in the headerline of the csv to the appropriate language and running the encoder again. Then you can rename the file and the game will display the strings for this language. There are some tools and batch files which do this automatically, see the tools-thread.
 
Last edited:
Hey rmemr, just wanted to let you know that I will look over your tutorial again,and if there are things you could add to make it easier,I will tell you.But for first I have to finish the whole localisation myself.I think it is easier to say when I saw all aspects,so it could still take some days,but I won`t forget you :)

Thanks for your help till now,expect a detailed answer from me towards weekend
 
So rmemr,

I promised you a detailed feedback,so here it is:

Localizing a mod is,as god knows,not the easiest thing to to when creating a Witcher 3 mod. XMLs have to be localized on another way than menus,and maybe there are even other things you can localize,I didnt had to do during my process.As I said in a post earlier,your guide is very well written,but maybe a lil bit too professional.It may help some people to read it like this,but for some others like me,it was very confusing.Maybe you should state clear,what localizing exactly is,before you add the description what to do.I for myself knew that it would display the names and descriptions of items ingame properly,but I also thought it would create translations for other languages automatically.Honestly this was the only reason why I first started the whole localization process at all.As I am lucky,I found many willing translators in a very short time,but this may just be the fact,that Enhancement System has become popular in just one month.Smaller mods could not have this luck.Also,I would post a tutorial on nexus article sites,as the localizing process is something EVERY mod creator should do,and it would be best if he knows this before he creates his mod.I for myself had to change all localization_key_names of nearly 60 xmls,before I could even start the localizing process.Because they had spaces,and not allowed signs in it.And this was just because I didnt knew better,when I started to create my mod.Just the name changing process took me several days,and it was really a pain.Of course that is not your fault,as you have written this detailed guide :D But it is a lil bit hided in here,as not every modder is member here on CDPR forum (many are just using the nexus), and even if they find this tool,not everyone is sure what he has to do.I would suggest attaching some example xml/csv/menu datas,as well as some ingame pictures,that you can compare to each other,and see in detail what has to be done.As you know,sometimes pictures say more than thousands of words.But that is just my oppinion.I am finished with the localization and do know now what to do,but there are many other modders that may be just as so slow on the uptake as I was.Or even not.There were also members that were able to localize just because of your tutorial,and they didnt need more instructions.

I believe this was everything I have to say about it.I thank you for taking your time,and reponse to your users questions so detailed btw that you appreciate feedback to make your tool easier to use for everyone.

Best regards

Mange
 
Is it possible to add new letters to the game? I made new item, created new strings but how to select the content of new book or letter?
 

Guest 2364765

Guest
Is it possible to add new letters to the game? I made new item, created new strings but how to select the content of new book or letter?
Inside item definition.

I don't remember details but i'm quite sure content is referenced by auto-generated key that adds _content to item name key name.
You can enable showing placeholder labels for missing localizations to see what keys you need to create in case you don't know them.
 
about those prefixes:

PHP:
;meta[language=en]
;id|key(hex)|key(str)|text
2112501000||panel_W3SF_Options|W3 ScriptFix
2112501001||preset_W3SF_Options|W3 ScriptFix Options
2112501002||preset_value_W3SF_Enabled|Enabled
2112501003||preset_value_W3SF_Disabled|Disabled
2112501100||option_W3SF_InstaCast_Signs|InstaCast Signs
2112501101||option_W3SF_Randomize_Food|Randomized Food
2112501102||option_W3SF_Randomize_Alcohol|Randomized Alcohol
2112501103||option_W3SF_LoadScreen_Music|LoadScreen Music
2112501104||preset_value_W3SF_Wild_Hunt|Wild Hunt
2112501105||preset_value_W3SF_Hearts_of_Stone|Hearts of Stone

- <Group> = panel_
- <Group> = preset_
- TOGGLE = option_
- OPTIONS = option_
- SLIDER = option_
- <Preset> = preset_value_
- <Option> = preset_value_

PHP:
---- igmOptions.ws : function IngameMenu_FillOptionsSubMenuData()

IngameMenu_FetchAndGenerateGroupMenuObject(flashSt  orageUtility,  "panel_", "W3SF_ScriptFix", l_optionChildList, groupParenArray);

also, if you insert that line into igmOptions.ws, you can reposition and change some characteristics of the menu you are displaying. although it is unnessary to correctly read the xml file.

NOTE: the last trick/piece of the puzzle (when using preset groups) was to name both the preset group and the igmOptions.ws string the SAME. ie: (both named W3SF_Options).

PHP:
2112501000||panel_W3SF_Options|W3 ScriptFix
2112501001||preset_W3SF_Options|W3 ScriptFix Options

IngameMenu_FetchAndGenerateGroupMenuObject(flashSt  orageUtility,   "panel_", "W3SF_Options", l_optionChildList, groupParenArray);

<Group id="W3SF_ID" displayName="W3SF_Options">
    <PresetsArray>

if the name of the preset group and the panel do not match (except the panel_ preset_ prefix), then the UI will break bad. you can consider this the 'GroupID' as far as InGameConfigWrapper is concerned.

adding this here too (in case you want custom callback functions when a GUI option changes). optionName is the 'id' in the XML file:

ingameMenu.ws (OnOptionValueChanged):
PHP:
if (optionName == 'LoadScreenMusic')
{
    doSomething(optionValue); /* the value which was just set */
}

and with that said, thanks very much for this encoding tool, sir.
 
Last edited:
decode + merge all localized content

tools - decode.cmd
@SETLOCAL ENABLEEXTENSIONS
@ECHO OFF

@SET witcher3=C:\Program Files (x86)\Steam\steamapps\common\The Witcher 3
@SET basedir=%CD%
echo.
echo --------------------------------------------------------------------------------
echo decode and merge all localized w3strings content.
echo.
echo --------------------------------------------------------------------------------
pause

for /r "%witcher3%\content" %%F in (*.w3strings?) do ( w3strings.exe --decode "%%F"

echo -------------------------------------------------------------------------------- )
echo processing/merging files...
echo.

if not exist "%basedir%\decode" md "%basedir%\decode"
for %%F in ("%basedir%\decode\*.w3strings.csv") do del "%%F"
for /r "%witcher3%\content" %%F in (*.w3strings.csv) do type "%%F" >> "%basedir%\decode\%%~nF.csv"
for /r "%witcher3%\content" %%F in (*.w3strings.csv) do del "%%F"
for %%F in ("%basedir%\decode\*.w3strings.csv") do echo "%%F"

echo.
echo --------------------------------------------------------------------------------
pause

there's a short script i wrote to merge all of the .w3strings files and dump them in the currentdirectory\decode folder.

place in the same folder as w3strings.exe, set the "witcher3" variable in script to your witcher 3 folder.

use at your own risk, as it does delete the old files it creates.
 
Last edited:
Hello @rmemr
I'm tryingto change already existing lines in the game for Russian localization. And I'm encountered an issue, when w3string file is bigger then 9.1kb the text becomes broken.

This is less then 9.1kb file:

View attachment 36880
And this is bigger then 9.1kb file:

View attachment 36890
 

Attachments

  • witcher3_2016_05_01_17_52_04_380.jpg
    witcher3_2016_05_01_17_52_04_380.jpg
    183 KB · Views: 427
  • witcher3_2016_05_01_17_50_36_172.jpg
    witcher3_2016_05_01_17_50_36_172.jpg
    184.1 KB · Views: 349
I'm tryingto change already existing lines in the game for Russian localization. And I'm encountered an issue, when w3string file is bigger then 9.1kb the text becomes broken.

The size should not be a problem. I tested decoding and reencoding of the game files which are much bigger.

This looks like some broken utf8 <-> utf16 conversion. Try to decode your encoded file again and check if the results differ from your input csv.

If they do or if the file cannot be decoded again then please attach/sent me a minimal version of your csv file that is not working and I look into it.
 
Top Bottom