How to use STRINGTABLE with a Python Command Plugin
-
Hello,
I'm trying to add multi-language support in my plugin.I currently have the strings hardcoded in the GeDialog's CreateLayout method like this:
self.AddStaticText(self.HELP_ID, c4d.BFV_BOTTOM | c4d.BFV_SCALE | c4d.BFH_LEFT, 0, 0, "Help")
All of the strings are labels for UI menu commands and gadgets. I understand that the best practice is to put the UI strings into folders within a 'res' folder like so:
res └ strings_en-US └ c4d_strings.str └ strings_fr-FR └ c4d_strings.str
My issue is I don't know how to use the STRINGTABLE in the .str with my Python CommandPlugin. Here's an example of the c4d_strings.str content:
c4d_strings.str (strings_en-US)
STRINGTABLE { IDS_TEST "Test Plugin"; TITLEVIEW_ID "Test - View"; HELP_ID "Help";} }
c4d_strings.str (strings_fr-FR)
STRINGTABLE { IDS_TEST "Test Plugin"; TITLEVIEW_ID "Test - Vue"; HELP_ID "Aide"; }
Please forgive all of these questions:
- What is the best practice for loading these STRINGTABLES and using them in the UI? I couldn't find an example using a CommandPlugin in the official Cinema 4D Python examples though I did see that the py-ies_meta_r12.py SceneSaverPlugin example uses a method called c4d.plugins.GeLoadString.
- If GeLoadString is the way to go, would I set up my IDs in my GeDialog class and reference the corresponding ID in the STRINGTABLE with this method?
- Would Cinema 4D then grab the correct string based on the user's language if my folder structure is set up appropriately?
- Is there a similar method for automatically handling the localized date and time format?
- As mine is not an Object plugin, I won't need a description folder, is that correct?
- What should I do with the c4d_symbols.h file?
Thank you so much!
-
GeLoadString()
is the way to go. You actually find plenty of examples ofGeLoadString()
being used in the C++ code base (e.g. asynctest.cpp) and this doc: String Manual (Classic). -
Hi, @blastframe as @PluginStudent pointed you should use GeLoadString.
To make GeLoadString working, you should use as you already did, the .str file but also the
c4d_symbols.h
so this way Cinema 4D can link the ID you provided in the str file to an actualint
value.res └ c4d_symbols.h └ strings_en-US └ c4d_strings.str └ strings_fr-FR └ c4d_strings.str
c4d_symbols.h
enum { IDS_TEST = 10000, TITLEVIEW_ID, // This will have id 10000 + 1 HELP_ID, // This will have id 10000 + 2 // End of symbol definition _DUMMY_ELEMENT_ };
However, due to the nature of Python, the
int
value defined in thec4d_symbols.h
is not ported to python so you have to redefine it in your python code as well.And here is how to use it in your pyp file. This needs the __res__ to be defined, this is done automatically, for more information see Issue with registering a ToolData.
print c4d.plugins.GeLoadString(10000) # Will print the str value of IDS_TEST
Finally, note that these Symbol IDs must be unique through all Cinema 4D so instead of
IDS_TEST
is would recommend you rename it withBLASTFRAME_IDS_TEST
.Cheers,
Maxime. -
Since this topic is older than a week I marked is as closed, but feel free to reopen it if you have further questions.
Cheers,
Maxime -
@m_adam Hi Maxime! I wanted to make sure I had all of my strings before implementing this. I am very grateful for your help. I will come back to this thread soon! Thank you!
-
@m_adam I got it working with your help! Thank you so much. I have a couple more questions (more for advice really):
- Are there tools for creating C++ STRINGTABLES like the ones Cinema 4D uses?
- I am currently using a spreadsheet for editing my stringtables. Are there any tools I can use to export the non-ascii characters as unicode that Cinema 4D will understand?
Thank you!
-
I don't think there are any official "tools". But the docs describe how to handle unicode (Dialog Layout
The encoding is 7-bit ASCII with other characters encoded as \uHHHH. For example 'Natürlich' is written 'Nat\u00fcrlich'. Byte-order marks are not used.