[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
If you encounter issues pm me.
Some output for example:
w3strings.exe v0.3.3
size: 4650080 bytes
md5: e57af93653bdaa33d4cfe4569252156e
sha256: 833d577d9b49906c85980732e77f2f3d84dbcf0551affd556162a9975c29df3b
link to nexusmods
Have fun.
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 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: