Система переводов в Qt, на мой взгляд, является одной из наименее проработанных частей этого фреймворка. Да, имеются все необходимые возможности, но не хватает некоторых мелочей. Вместо тысячи слов: QT_TRANSLATE_NOOP3
Для чего нужен этот макрос? Он позволяет инициализировать массив структур, состоящих из исходной строки и комментария (параметры функции tr). При этом исходные строки будут помечены для перевода. Если в дальнейшем передать их функции tr, то они будут переведены. Данный макрос может быть использован только для инициализации переменной-массива. Подобные решения, на мой взгляд, ну никак не тянут на серьёзные. Больше похоже на временную заплатку, словно у разработчика не было времени хоть сколько-нибудь подумать.
Не пускаясь в абстрактные рассуждения и высокие материи, рассмотрим вполне реальный пример. Допустим, нам нужно показывать пользователю определённые сообщения в ответ на ввод соответствующих команд (например, в справочной системе консольного приложения). Конечно, если это отдельное приложение, то можно просто захардкодить нужные строки, обёрнутые в функцию tr. Но если данная возможность реализована в библиотеке и используется несколькими разными приложениями, то такой вариант не пройдёт. Можно, конечно, использовать виртуальные методы, но такой подход, на мой взгляд, излишне громоздкий. Гораздо более естественно создать словарь, в котором команде будет сопоставляться строка, а затем пополнять этот словарь. Вот как это может выглядеть:
Пример использования:
Для чего нужен этот макрос? Он позволяет инициализировать массив структур, состоящих из исходной строки и комментария (параметры функции tr). При этом исходные строки будут помечены для перевода. Если в дальнейшем передать их функции tr, то они будут переведены. Данный макрос может быть использован только для инициализации переменной-массива. Подобные решения, на мой взгляд, ну никак не тянут на серьёзные. Больше похоже на временную заплатку, словно у разработчика не было времени хоть сколько-нибудь подумать.
Не пускаясь в абстрактные рассуждения и высокие материи, рассмотрим вполне реальный пример. Допустим, нам нужно показывать пользователю определённые сообщения в ответ на ввод соответствующих команд (например, в справочной системе консольного приложения). Конечно, если это отдельное приложение, то можно просто захардкодить нужные строки, обёрнутые в функцию tr. Но если данная возможность реализована в библиотеке и используется несколькими разными приложениями, то такой вариант не пройдёт. Можно, конечно, использовать виртуальные методы, но такой подход, на мой взгляд, излишне громоздкий. Гораздо более естественно создать словарь, в котором команде будет сопоставляться строка, а затем пополнять этот словарь. Вот как это может выглядеть:
QMap<QString, QString> map;
map.insert("command", "This is a command. It does nothing.");
Отлично, осталось сделать строку переводимой. Ясно, что средствами Qt тут ничего хорошего добиться не удастся. Поэтому предлагаю использовать вот такой простенький класс: class Translation
{
public:
static Translation translate(const char *context, const char *sourceText, const char *disambiguation = 0, int n = -1)
{
if (n < 0)
n = -1;
Translation t;
mcontext = context;
msourceText = sourceText;
mdisambiguation = disambiguation;
mn = n;
return t;
}
public:
explicit Translation()
{
mn = -1;
}
public:
QString Translation::translate() const
{
QCoreApplication::translate(mcontext.toUtf8().constData(), msourceText.toUtf8().constData(), mdisambiguation.toUtf8().constData(), mn);
}
private:
QString mcontext;
QString msourceText;
QString mdisambiguation;
int mn;
};
Как известно, если обернуть строку в функцию translate, то она будет помечена к переводу. Не важно, в каком пространстве имён находится эта функция. В классе Translation использовано данное обстоятельство. Экземпляр класса создаётся посредством вызова статического метода translate. То есть этот класс — просто обёртка, хранящая исходную строку, которую в любом месте программы можно перевести с использованием QCoreApplication::translate. Конструктор копирования и различные операторы в коде отсутствуют, но подразумеваются.Пример использования:
//создаём словарь и пополняем его
QMap<QString, Translation> map;
map.insert("command", Translation::translate("Some context", "This is a command. It does nothing.", "Some comment"));
//выводим соответствующую строку при вводе команды
QTextStream in(stdin, QIODevice::ReadOnly);
QString command = in.readLine();
QTextStream out(stdout, QIODevice::WriteOnly);
out << map.value(command).translate();
На выходе получим переведённую строку. Казалось бы, мелочь, а весьма удобно и естественно по сравнению с этим ужасным макросом QT_TRANSLATE_NOOP3 и по сравнению с использованием виртуальных методов. Есть, конечно, некоторый проигрыш в скорости и объёме памяти, но... как говорится, не смешите мои тапочки. :)