Localizing strings using Qt which are declared in Global Scope - c++

I'm developing Qt UI application and localizing the UI strings. In my application, I'm using QLabel and setting the texts dynamically. I experimented two ways of setting the texts for localization. While executing the application, I could see, in my first approach strings are getting localized but in second approach they are not.
//Approach 1:
//ui.cpp
//Directly hardcoding the values
labelBox1->setText(QApplication::translate("context","test string"));
//Approach 2:
//UI_Consts.h
static const QString str = QT_TRANSLATE_NOOP("Context","Test String");
//variable 'str' is in global scope
//ui.cpp
#include "UI_Consts.h"
...
labelBox1->setText(str);
When I debugged why second approach not worked, I found that global variables are initialized before the execution of main function. We generally write code for Translation in main() and hence those global variables are not getting translated.
I prefer second approach as we can list down all the UI strings in a single file and easily maintain them. I want to know is there any way to localize the strings which are declared in Global Scope(like used in my second approach)?

Well, that's not the way Qt's translation system is meant to be used...
But if you want to do it that way you could write a function (or implement a class/struct holding all strings) that initializes all your string variables after loading the translations in main() - of course this would result in even more code :D

I think you've misunderstood what for is QT_TRANSLATE_NOOP. In the Qt Linguist Manual: Programmers you can read under the section: Using QT_TR_NOOP() and QT_TRANSLATE_NOOP()
If you need to have translatable text completely outside a function, there are two macros to help: QT_TR_NOOP() and QT_TRANSLATE_NOOP(). These macros merely mark the text for extraction by lupdate. The macros expand to just the text (without the context).
So, the problem isn't the global variable str.

Related

How to resolve Qt Creator variable-“<not accessible>” behavior (Opencv)

As observed in the screenshot above, I have the problem that variables in the Locals and Expressions window in QT Creator are displayed as being . How can I get Qt Creator to show the values for the OpenCV filter functions?
QtCreator marks "not accessible" for the value, not for the variable. That means those variables are not initialized yet. Try to inspect the same values by adding another debugging point after the matrices are initialized.
I was getting this for a struct I had defined. I could see the contents of other structs, but not this particular one. It turned out that I was declaring the struct inside a function in my main window object. I just had to take the struct out of the function, just declaring it at global level before the function (not even bothering to put it in the header, although that's better practice). That was enough to allow me to see the values of a QList, that is itself still declared in the function in question.

How can I make a Stata plugin not depend on the order of variables?

I am writing a plugin for Stata in C++, and it seems to me that accessing the data depends on the order of variables passed to the plugin, as SF_vdata() only takes integer arguments to index the variables.
The best solution I have at the moment, is to first run ds, store the macro containing all variable names, and then call my plugin. My plugin can then search the macro for the variable that it is interested in, and get the index base don its position in the list.
This works, but I would like my plugin not to depend on certain Stata commands being run first. I know this is silly, as the plugin requires the dataset to be formatted in a specific way, but something feels wrong about first having to call ds and store a macro before calling my plugin.
Is there anyway to access the order of variable names from inside the plugin if ds is not called first?
I agree with Nick. Unfortunately your macro solution is the only answer, and is what I use. You can only access the data directly using the SF_data functions, as a "matrix", and that's all you get by default, there are no headers like in a table. I use macros to save all the data information and pass the whole dataset, reading the variable I'm interested in, just like you, and even wrote translators to retain the format settings, but have not yet used the value labels.

Try to find global variables from compiled files. The program can't distinguish constants from global variables.

Good Day! I'm trying to find the decision for a long time.
My problem is:
For example I have 2 .cpp files, one of them containing
const std::string DICTIONARY_DEFAULT = "blah";
const std::string ADDTODICTIONARY_DEFAULT = "blah";
const std::string BUTTONS = "blah";
and the second one with
static int x1;
static int NewY1, NewY2, NewX1, NewX2;
Both fragments are in the global variables section. I need to print the global static variables (for example), but ignore constants. In nm output they're looking absolutely identical (b-type for every case, which means uninitialized local scope symbol). Is there any way to separate this cases automatically using only linux utilities (grep, regexps and so on are perfectly okay)?
MY TASK FOR BETTER UNDERSTANDING:
There is a program in C++, the main task is to find and to withdraw the list of global variables.
Input data looks like archives with lots of .cpp files. Every .cpp file is syntactically correct program in C++ (It Must successfully compiled using compilier GNU C++ and Microsoft Visual C++).
For every file from the archive I must output in separate string the name of the file and the list of global variables, like in the example:
Output Data :
000000.cpp ancestor ansv cost graph M N p qr query u
000001.cpp
000002.cpp
000003.cpp
000004.cpp
000005.cpp
000006.cpp
000007.cpp edge tree
finding global variables is a 'subject' of this clang tutorial -- in this tutorial author did it 'just for fun', but you may add some code to do exactly what you need... (btw, it is not so hard as one may guess :))
Short answer: There is actually no way to do it in every case
Long answer: Take a look at the SYMBOL TABLE using 'objdump -x file.o'. You can see that all global variables, both static and const, are allocated into a section called .bss. A section called .rodata also exists and it is, generally speaking, used to store const data. Unfortunately, in your case you are declaring two const std::string objects. Those objects are initialized by invoking their constructor before the 'main' function is run. Still, the initialization of their fields happens at run-time and so they are only 'logically' const, and not really const.
The compiler has no choice but to allocate them into the .bss section with all other globals.
If you add the following line
const int willBeInRoData = 42;
You will find that its symbol will be in the .rodata section and so it will be distinguishable from the other global integers.

isDefined function?

In C++ is there any function that returns "true" when the variable is defined or false in vice versa. Something like this:
bool isDefined(string varName)
{
if (a variable called "varName" is defined)
return true;
else
return false;
}
C++ is not a dynamic language. Which means, that the answer is no. You know this at compile time, not runtime.
There is no such a thing in runtime as it doesn't make sense in a non-dynamic language as C++.
However you can use it inside a sizeof to test if it exists on compile time without side-effects.
(void)sizeof(variable);
That will stop compilation if var doesn't exist.
As already stated, the C++ runtime system does not support the querying of whether or not a variable is declared or not. In general a C++ binary doesn't contain information on variable symbols or their mappings to their location. Technically, this information would be available in a binary compiled with debugging information, and you could certainly query the debugging information to see if a variable name is present at a given location in code, but it would be a dirty hack at best (If you're curious to see what it might look at, I posted a terrible snippet # Call a function named in a string variable in C which calls a C function by a string using the DWARF debugging information. Doing something like this is not advised)
Microsoft has two extensions to C++ named: __if_exists and __if_not_exists. They can be useful in some cases, but they don't take string arguments.
If you really need such a functionality you can add all your variables to a set and then query that set for variable existance.
Already mentioned that C++ doesn't provide such facility.
On the other hand there are cases where the OS implement mechanisms close to isDefined(),
like the GetProcAddress Function, on Windows.
No. It's not like you have a runtime system around C++ which keeps remembers variables with names in some sort of table (meta data) and lets you access a variable through a dynamically generated string. If you want this, you have to build it yourself, for example using a std::map that maps strings to some objects.
Some compile-time mechanism would fit into the language. But I don't think that it would be any useful.
In order to achieve this first you need to implement a dynamic variable handling system, or at least find some on the internet. As previously mentioned the C++ is designed to be a native language so there are no built-in facilities to do this.
What I can suggest for the most easy solution to create a std::map with string keys storing global variables of interest with a boost::any, wxVariant or something similar, and store your variables in this map. You can make your life a bit easier with a little preprocessor directive to define a variables by their name, so you don't need to retype the name of the variable twice. Also, to make life easier I suggest to create a little inline function which access this variable map, and checks if the given string key is contained by the map.
There are implementation such a functionality in many places, the runtime property handling systems are available in different fashion, but if you need just this functionality I suggest to implement by yourself, because most of these solutions are quite general what you probably don't need.
You can make such function, but it wouldn't operate strings. You would have to send variable name. Such a function would try to add 0 to the variable. If it doesn't exists, an error would occur, so you might want to try to make exception handling with try...throw...catch . But because I'm on the phone, I don't know if this wouldn't throw an error anyways when trying to send non-existing variable to the function...

Localization of string literals

I need to localize error messages from a compiler. As it stands, all error messages are spread throughout the source code as string literals in English. We want to translate these error messages into German. What would be the best way to approach this? Leave the string literals as-is, and map the char* to another language inside the error reporting routine, or replace the english literals with a descriptive macro, eg. ERR_UNDEFINED_LABEL_NAME and have this map to the correct string at compile time?
How is such a thing approached in similar projects?
On Windows, typically this is done by replacing the string with integer constants, and then using LoadString or similar to get them from a resource in a DLL or EXE. Then you can have multiple language DLLs and a single EXE.
On Unixy systems I believe the most typical approach is gettext. The end result is similar, but instead of defining integer constants, you wrap your English string literals in a macro, and it will apply some magic to turn that into a localized string.
The most flexible way would be for the compiler to read the translated messages from message catalogs, with the choice of language being made according to the locale. This would require changing the compiler to use some tool like
gettext.
Just a quick thought...
Could you overload your error reporting routine? Say you are using
printf("MESSAGE")
You could overload it in a way that "MESSAGE" is the input, and you hash it to the corresponding message in German.
Could this work?
You could use my CMsg() and CFMsg() wrappers around the LoadString() API. They make your life easier to load and format the strings pulled out of the resources.
And of course, appTranslator is your best friend to translate your resources ;-)
Disclaimer: I'm the author of appTranslator.
On Windows you can use the resource compiler and the WinAPI load functions to have localized strings and other resources. FindResource() and its specialized derivatives like LoadString() will automatically load language specific resources according to the user's current locale. FindResourceEx() even allows you to manually specify the language version of the resource you wish to retrieve.
In order to enable this in your program you must first change your program to compile the strings in an resource file(.rc) and use LoadString() to fetch the strings at runtime instead of using a literal string. Within the resource file you then setup multiple language versions of the STRINGTABLEs you use, with the LANGUAGE modifier. The multi-lingual resources are then loaded based on the search order described here on MSDN: Multiple-Language Resources
Note: If you have no reason to need a single executable, or are doing something like using a user selected language from within your app, it gives you more control and less confusion to compile each language in a seperate dll and load them dynamically rather than have a large single resource file and trying to dynamically switch locales.
Here is an example of a multiple language StringTable resource file (ie:strings.rc):
#define IDS_HELLOSTR 361
STRINGTABLE
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_CAN
BEGIN
IDS_HELLO, "Hello!"
END
STRINGTABLE
LANG_FRENCH, SUBLANG_NEUTRAL
BEGIN
IDS_HELLO, "Bonjour!"
END