QObject::tr() not translating dynamically generated strings - qt

QObject::tr("%1").arg(_value);
Here _value is of QString type, which is dynamically generated. Is the above way correct to translate dynamically generated strings as in my code it doesn't seem to work.

There are two steps:
1. Make Qt extract the strings for translation.
This means using one of
tr() in a QObject subclass
QCoreApplication::translate()
QT_TR_NOOP / QT_TRANSLATE_NOOP
lupdate will extract the strings passed to those functions/macros, and make them available to linguist for translation.
2. Performing the translation (i.e. the "lookup")
This is again done by tr() and QCoreApplication::translate(). So for instance:
// marking the strings for extraction
static const char *strings[] = {
QT_TRANSLATE_NOOP("MyContext", "hello"),
QT_TRANSLATE_NOOP("MyContext", "world");
};
// performing the translation at runtime
qApp->translate("MyContext", strings[0]);
There's a ton of documentation about the whole process, see here.

You perhaps meant to do:
QObject::trUtf8(QString("%1").arg(_value).toUtf8(), "dynamic1");
You must ensure that your translation file contains all values that _value can take with the dynamic1 for the disambiguation value, iff you wish to disambiguate them, that is.
Of course, the _value must be selected from a fixed list of strings anyway - since tr isn't a human translator, it simply does a lookup of the string in a translation list.
So, you should really do this:
QString value;
select (variant) {
case VarA: value = QObject::tr("foo"); break;
case VarB: value = QObject::tr("bar"); break;
...
}
That way the relevant strings will be included in the translation list.

You're trying to translate _value in the wrong place. As stated in other answers, QObject::tr() can't guess by itself how to translate anything. It works only on fixed strings. You should mark constants you're setting _value to for translation, not _value itself.

Related

Unable to understand extension function in Kotlin Android?

I am not able to understand extension function and use it in my project. Can anyone guide me here please?
From the docs - “Kotlin provides the ability to extend a class with new functionality without having to inherit from the class or use design patterns such as Decorator. This is done via special declarations called extensions.”
To understand this in an easy way, let’s consider the below example:
First things first.
Write 10 and then put a dot(.) after it and then try to write addTwoNumbers().
You’ll be getting errors at this stage as there is no property named addTwoNumbers() for an integer.
Now, write this method:
fun Int.addTwoNumbers(y: Int): Int = this.plus(y) //“this” corresponds to the integer number. (In this example, “this” refers to 10).
Notice how we are using Int.addTwoNumbers().
Let’s try to follow the same thing again:
Write 10.
Put a dot(.) after it.
Try to write addTwoNumbers().
And this time you’ll notice, it’s appearing as if this is the property of integer.
Check the below code:
fun main() {
val sum = 10.addTwoNumbers(20) //here “this” will be assigned “10” and “y” will be assigned “20”
println("sum: $sum")
}
This will print sum: 30 in the console.
This phenomena is known as “Extension Function”.

Why is fmt.Println not consistent when printing pointers?

I'm an experienced programmer but have never before touched Go in my life.
I just started playing around with it and I found that fmt.Println() will actually print the values of pointers prefixed by &, which is neat.
However, it doesn't do this with all types. I'm pretty sure it is because the types it does not work with are primitives (or at least, Java would call them that, does Go?).
Does anyone know why this inconsistent behaviour exists in the Go fmt library? I can easily retrieve the value by using *p, but for some reason Println doesn't do this.
Example:
package main
import "fmt"
type X struct {
S string
}
func main() {
x := X{"Hello World"}
fmt.Println(&x) // &{Hello World} <-- displays the pointed-to value prefixed with &
fmt.Println(*(&x)) // {Hello World}
i := int(1)
fmt.Println(&i) // 0x10410028 <-- instead of &1 ?
fmt.Println(*(&i)) // 1
}
The "technical" answer to your question can be found here:
https://golang.org/src/fmt/print.go?#L839
As you can see, when printing pointers to Array, Slice, Struct or Map types, the special rule of printing "&" + value applies, but in all other cases the address is printed.
As for why they decided to only apply the rule for those, it seems the authors considered that for "compound" objects you'd be interested in always seeing the values (even when using a pointer), but for other simple values this was not the case.
You can see that reasoning here, where they added the rule for the Map type which was not there before:
https://github.com/golang/go/commit/a0c5adc35cbfe071786b6115d63abc7ad90578a9#diff-ebda2980233a5fb8194307ce437dd60a
I would guess this had to do with the fact that it is very common to use for example pointers to Struct to pass them around (so many times you'd just forget to de-reference the pointer when wanting to print the value), but no so common to use pointers to int or string to pass those around (so if you were printing the pointer you were probably interested in seeing the actual address).

QtLinguist: Define a single context

How do I define a single context in a QtLinguist .ts file, rather than having one context per file?
I need this because I have identical strings showing up in different files for which I want the same translation (and no duplicates)
From C++, you can explicitly specify the translation context on a string-by-string basis by using the static function QCoreApplication::translate(const char* context, const char* text) instead of the traditional QObject::tr(const char* text) (see this doc for more details: http://doc.qt.io/qt-5/qcoreapplication.html#translate)
e.g.
menuItem->setText(QCoreApplication::translate("UniversalContext", "Exit"));
Similarly, you can specify the context in QML using the qsTranslate(context, text) function, a la
Text { text: qsTranslate("UniversalContext", "hello") }
These will all get picked up by lupdate as belonging to the same context (duplicate strings will only show up once in your .ts file)
If you have a lot of strings and it gets painful to specify the context on every call to translate/qsTranslate, you should be fairly simple to create a 1-arg macro (c++) or a js function (qml) as a wrapper.

What's the Nicest Way to do This? (Qt and Enum style arguments)

In Qt, it is common to see something similar to the following:
QSettings obj3(QSettings::SystemScope, "MySoft", "Star Runner");
The important bit is the QSettings::SystemScope, which is an enum.
I want to have a settings provider (pay no attention to the previous example here, it has nothing to do with the following), with a get/set property.
Settings.set(Settings::refreshRate)
The refreshRate has to link to a key (string), and a default value (variant).
Should I make an enum and two dicts for the key and default values, or make a struct and a whole bunch of variables that encapsulate the settings I need? Should I try something else?
Thanks!
Edit!
This is what I did.
// Interface
class Settings {
public:
static QVariant get(Setting setting);
static void set(Setting setting, QVariant value);
const static Setting serverRefreshRate;
const static Setting serverReportTimeout;
};
// Implementation
const Setting Settings::serverRefreshRate = { "server/refreshRate", 10000 };
const Setting Settings::serverReportTimeout = { "server/reportTimeout", 1000 };
Well I guess since you're using enum which most likely will be easily castable to numbers from to 0 to N-1 I guess just storing variants and strings in two vectors or one vector of pairs would work just fine.
There's also another question though -- how to initialize all of that and how you will be adding new settings to it. I can suggest two methods - first one writing a bunch of function calls with arguments: enum, string, variant. Thus way though if programmer adds another value to enum he can forget to call initializing function. The other way is to create function (or maybe two) which will do switch on all enum values (without default case) and will return pair of string and variant. You can turn on the compiler warning about all enum values being processed in switch and thus way control if you forget to implement some of them in that function. And then initialize your structures using loop on all of enum values. These initializing functions should be called somewhere near the beginning of your program (before reading settings initially).
Well, that's my thoughts on it, you are free to try some different ways though.

qt tr() in static variable

I have problem concerning translations in qt. All translations in my porject work fine, but one, which is in a static variable of a class. Corresponding part of code looks as follows
The header file is similar to this:
typedef struct {
int type;
QString problematicString;
} info;
MyClass::QObject_Descendant
{
Q_OBJECT;
//some functions like constructor, destructor... etc.
....
static info myClassInfo;//class that makes problems
}
and in implementation file I initialize the variable as follows:
info MyClass::myClassInfo={
1,
tr("something to be translated")
};
And whatever I do (trying with QT_TR_NOOP, then tr() and others) I cannot get myClassInfo.problematicString translated. The weirdest thing is that the text "something to be translated"
appears in *.ts file.
If someone has any hints, please share them with me. Thanks in advance.
Chris.
Static variables are instantiated (and thus, constructor code run) before your int main function is run. The translation code is set up in the QApplication constructor (I believe), which isn't run until your int main function has been entered. Thus, you are trying to get the translation of a string before the code to support it has been initialized.
To avoid this, you could either accept that the given string isn't translated and explicitly translate it every time it is used, or use the Construct on First Use idiom instead of a static member variable.

Resources