Feature Request: Automatic translate() for GUI elements?


#1

Hi,

I really like the current Introjucer. But as I’m currently working on a multilang project I’m asking:
Wouldn’t it make sense to generate a translate("…") automatically for every tooltip, text, […] string that is entered in the GUI editor and will be most likely presented to the user?
I would appreciate that as an introjucer feature, as this would spare me much time, because I would not have to reset these text strings manually in the code after designing the GUI.
Thanks


#2

Yes, that’d probably be a good idea. But since my plans are eventually for the Projucer to take over GUI design duties from the old GUI editor, any feature requests for the old one get an ultra-low priority… If you fancy tweaking it yourself and letting me know the changes I could merge them in :wink:


#3

That would be great.
Below are the changes I propose for the Introjucer. For testing, I created a component in the Introjucer that contains all the sub components and properties for that I made the changes (see the attachments). It works fine and also compiles without warnings in VS2012.
[attachment=1]TestGuiComponent.h[/attachment][attachment=0]TestGuiComponent.cpp[/attachment]


Tooltips (except for HyperLink Buttons)
Source/ComponentEditor/components/jucer_ComponentTypeHandler.cpp
[list]
[]inserted “translate(String(” and “))” around the quotedS ttc->getTooltip() if this is not a hyperlink button[/][/list]
In [color=#008000]void ComponentTypeHandler::fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName)[/color]:
// […]

if (SettableTooltipClient* ttc = dynamic_cast <SettableTooltipClient*> (component)) { if (ttc->getTooltip().isNotEmpty()) { s << memberVariableName << "->setTooltip (" << ((dynamic_cast<HyperlinkButton*>(component)) ? String::empty : "translate(String(") << quotedString (ttc->getTooltip()) << ((dynamic_cast<HyperlinkButton*>(component)) ? String::empty : "))") << ");\n"; } } // […]


Labels
Source/ComponentEditor/components/jucer_LabelHandler.h
[list]
[]inserted “translate(String(” and “))” around the quoted l->getText()[/][/list]
In [color=#008000]String getCreationParameters (Component* component)[/color]:

Label* const l = dynamic_cast <Label*> (component);

return quotedString (component->getName())
         + ",\n"
         + "translate(String("
         + quotedString (l->getText())
         + "))";

Group Components
Source/ComponentEditor/components/jucer_GroupComponentHandler.h
[list]
[]inserted “translate(String(” and “))” around the quoted g->getText()[/][/list]
In [color=#008000]String getCreationParameters (Component* component)[/color]:

GroupComponent* g = dynamic_cast <GroupComponent*> (component);

return quotedString (component->getName())
        + ",\n"
        + "translate(String("
        + quotedString (g->getText())
        + "))";

Hyperlink Buttons
Source/ComponentEditor/components/jucer_HyperlinkButtonHandler.h
[list]
[]inserted “translate(String(” and “))” around the quoted hb->getButtonText()[/][/list]
In [color=#008000]String getCreationParameters (Component* comp)[/color]:

HyperlinkButton* const hb = dynamic_cast <HyperlinkButton*> (comp);

return "translate(String("
        + quotedString (hb->getButtonText())
        + "))"
        + ",\nURL ("
        + quotedString (hb->getURL().toString (false))
        + ")";

Buttons
Source/ComponentEditor/components/jucer_ButtonHandler.h
[list]
[]inserted “translate(String(” and “))” around the quoted b->getButtonText()[/][/list]
In [color=#008000]void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName)[/color]:
// […]

if (b->getButtonText() != b->getName()) { code.constructorCode << memberVariableName << "->setButtonText (" << "translate(String(" << quotedString (b->getButtonText()) << "))" << ");\n"; } // […]


Text Editors
Source/ComponentEditor/components/jucer_TextEditorHandler.h
[list]
[]inserted “translate(String(” and “))” around the quoted te->getProperties() [“initialText”].toString()[/][/list]
In [color=#008000]void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName)[/color]:
// […]

s << memberVariableName << "->setMultiLine (" << CodeHelpers::boolLiteral (te->isMultiLine()) << ");\n" << memberVariableName << "->setReturnKeyStartsNewLine (" << CodeHelpers::boolLiteral (te->getReturnKeyStartsNewLine()) << ");\n" << memberVariableName << "->setReadOnly (" << CodeHelpers::boolLiteral (te->isReadOnly()) << ");\n" << memberVariableName << "->setScrollbarsShown (" << CodeHelpers::boolLiteral (te->areScrollbarsShown()) << ");\n" << memberVariableName << "->setCaretVisible (" << CodeHelpers::boolLiteral (te->isCaretVisible()) << ");\n" << memberVariableName << "->setPopupMenuEnabled (" << CodeHelpers::boolLiteral (te->isPopupMenuEnabled()) << ");\n" << getColourIntialisationCode (component, memberVariableName) << memberVariableName << "->setText (translate(String(" << quotedString (te->getProperties() ["initialText"].toString()) << ")));\n\n"; // […]


Combo Boxes
Source/ComponentEditor/components/jucer_ComboBoxHandler.h
[list]
[]inserted “translate(String(” and “))” around the quoted c->getTextWhenNothingSelected()[/]
[]inserted “translate(String(” and “))” around the quoted c->getTextWhenNoChoicesAvailable()[/]
[]inserted “translate(String(” and “))” around the quoted lines[/][/list]
In [color=#008000]void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName)[/color]:
// […]

s << memberVariableName << "->setEditableText (" << CodeHelpers::boolLiteral (c->isTextEditable()) << ");\n" << memberVariableName << "->setJustificationType (" << CodeHelpers::justificationToCode (c->getJustificationType()) << ");\n" << memberVariableName << "->setTextWhenNothingSelected (translate(String(" << quotedString (c->getTextWhenNothingSelected()) << ")));\n" << memberVariableName << "->setTextWhenNoChoicesAvailable (translate(String(" << quotedString (c->getTextWhenNoChoicesAvailable()) << ")));\n"; // […]

else s << memberVariableName << "->addItem (" << "translate(String(" << quotedString (lines[i]) << ")), " << itemId++ << ");\n"; // […]


Tabbed Components
Source/ComponentEditor/components/jucer_TabbedComponentHandler.h
[list]
[]inserted “translate(String(” and “))” around the quoted t->getTabNames()[/][/list]
In [color=#008000]void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName)[/color]:
// […]

code.constructorCode << memberVariableName << "->addTab (" << "translate(String(" << quotedString (t->getTabNames() [i]) << "))" << ", " << CodeHelpers::colourToCode (t->getTabBackgroundColour (i)); // […]


#4

Ok, thanks! I’ll take a look when I get a moment.

A couple of top tips for you:

Wrapping a string literal in a String like that will introduce a lot of unnecessary extra overhead (both size and performance) in every place you use it. I provided different overloads for the translate() function to let it accept raw char pointers, but even if that wasn’t the case, there’d be no sense in using an explicit String cast. (Actually, there are very few situations where you ever need to explicitly cast a literal in a String like that)

Also, it’s best to use the TRANS macro rather than calling translate() directly, because some people will have redefined that macro to avoid any translation overhead. The macro version is also recognised by the introjucer’s automatic translation scanner tool, whereas the function call isn’t.


#5

Thanks a lot!

Obviously you are right about the overhead when doing an extra string cast, and also I didn’t do it like this in the first place. But:
during tests I came up with a label, that should carry the UTF character “±”. As a windows user i copied that from MS Windows’ charmap.exe tool into the label’s text property in introjucer, which generated a CharPointer_UTF8 ("\xc2\xb1") for it.
Now when I try to compile a translate(CharPointer_UTF8) with Visual Studio (or use TRANS) I get a Compiler Error C2668 http://msdn.microsoft.com/en-us/library/da60x087(v=vs.110).aspx
I had no better solution for fixing this but using a string() cast, but maybe you do?


#6

Hmm. Surprising that it’d find that ambiguous - I’d have thought the String overload would be the obvious choice. Ah well, compilers generally know best - I guess I’ll need to add an other overload for the function that takes a CharPointer_UTF8.