QtHelpFramework: как использовать для мультиязычного приложения?
Делаю своего хелп ассистента, основанного на QtHelpFramework. Ищу решение, которое позволит изменяя язык в приложении получать ссылки на документы того языка, который нужен. Есть ли у кого-то опыт в этой области? может ли кто-то подсказать, есть ли варианты предусмотренные варианты нативного использования или механизмы для использования?
Ответы (1 шт):
Пусть имеется тестовый код, закоментированный по правилам Doxygen для автогенерации документации:
/** \~english
* @mainpage Here you can place an ad
* \~
* \~russian
* @mainpage Здесь вы можете разместить рекламу
* \~
*/
/** \~english
* @defgroup FOO FOO Module
* @brief Some module description
* \~
* \~russian
* @defgroup FOO Модуль FOO
* @brief Какое-то описание модуля
* \~
* @{
*/
/** \~english
* @brief Main Foo interface
* \~
* \~russian
* @brief Главный интерфейс Foo
* \~
*/
class IFoo
{
public:
/**
* \~english
* @brief Make foo
* @param[in] bar Bar value
* @return true if bar is true; otherwise returns false
* \~
* \~russian
* @brief выполнить foo
* @param[in] bar Значение bar
* @return true если bar истинно; иначе false
* \~
*/
virtual bool makeFoo(int bar) = 0;
};
/**
* @}
*/
Как видно, документация представлена для русского и английского языков.
Далее запустить doxywizard и создать новый проект для документации, указав путь до файла выше. Во вкладке Expert выбрать Project и справа найти параметр OUTPUT_LANGUAGE, который выставить English.
Ниже выбрать HTML и отметить параметр GENERATE_QHP галочкой, параметру QHG_LOCATION указать абсолютный путь до программы qhelpgenerator для генерации сжатых файлов документации Qt (у меня /usr/bin/qhelpgenerator), параметру QHP_VIRTUAL_FOLDER указать название виртуальной папки без слешей (например doc) и в параметре QHP_NAMESPACE указать пространство имён с двумя первыми буквами языка (например en.foomaker.1.0):
# Записи в файле проекта документации Doxygen
GENERATE_QHP = yes
QHP_NAMESPACE = "en.foomaker.1.0"
QHP_VIRTUAL_FOLDER = "doc"
QHG_LOCATION = "/usr/bin/qhelpgenerator"
Во вкладке Run запустить генерацию документации кнопкой Run doxygen. В директории проекта появится папка qch c файлом документации. Переименуйте его в en.qch.
Теперь выставите параметр OUTPUT_LANGUAGE в Russian, а QHP_NAMESPACE в "ru.foomaker.1.0", и снова сгенерируйте документацию, уже на русском языке. Файл из папки qch переименовать в ru.qch.
Итого получили файлы со сжатой документацией en.qch и ru.qch на английской и русском языках соответственно.
Теперь создадим файл проекта для коллекции сжатых файлов документации collection.qhcp, в котором указать отксительные пути к вышеуказанным файлам:
<?xml version="1.0" encoding="utf-8" ?>
<QHelpCollectionProject version="1.0">
<docFiles>
<register>
<file>qch/en.qch</file>
<file>qch/ru.qch</file>
</register>
</docFiles>
</QHelpCollectionProject>
Теперь сгенерировать файл collection.qhc, который будет понимать движок Qt Help Framework:
qhelpgenerator collection.qhcp -o qhc/collection.qhc
Полученные файлы qch/en.qch, qch/en.qch и qhc/collection.qhc это по сути базы данных SQLite, которые должны поставляться вместе с программой как отдельные файлы, т.к. механизм ресурсов Qt их не поддерживает.
Для отображения доки создать класс HelpBrowser, наследуемый от QTextBrowser (т.к. он может отображать ссылки со схемой документации Qt qthelp://), и переопределить ему член-функцию:
QVariant HelpBrowser::loadResource(int type, const QUrl &url)
{
if (url.scheme() == "qthelp")
return QVariant(m_helpEngine->fileData(url));
else
return QTextBrowser::loadResource(type, url);
}
Ну и в окошке приложения создать комбобокс со значениями ru и en, и выполнить код по типу такого:
// Системный язык (ru, en, ...)
const QString lang { QLocale::system().name().left(2) };
// Создаём движок с файлом коллекции
QHelpEngine* engine = new QHelpEngine(QString{"/path/to/qhc/collection.qhc"}, this);
engine->setupData();
// По умолчанию все файлы документации из коллекции зарегистрированы, поэтому я их сперва un'регистрирую :)
QStringList files{};
for(const auto& namSpace : engine->registeredDocumentations()) {
files << engine->documentationFileName(namSpace);
engine->unregisterDocumentation(namSpace);
}
// и регистрирую доку в соответствии с текущей локалью
engine->registerDocumentation( QString{"/path/to/qch/%1.qch"}.arg(lang) );
engine->contentWidget()->setWindowTitle("Content widget");
engine->contentWidget()->show();
// Создаём браузер доки, и выставляем доку в соответствии с текущей локалью
HelpBrowser* browser = new HelpBrowser(engine);
browser->setWindowTitle("Browser");
browser->resize(800,600);
browser->setSource(QUrl(QString{"qthelp://%1.foomaker.1.0/doc/index.html"}.arg(lang)));
connect(engine->contentWidget(), &QHelpContentWidget::linkActivated, browser, qOverload<const QUrl&>(&HelpBrowser::setSource));
browser->show();
connect(ui->comboBox, &QComboBox::currentTextChanged,
[engine](const QString& lang) {
QStringList files{};
for(const auto& namSpace : engine->registeredDocumentations()) {
files << engine->documentationFileName(namSpace);
engine->unregisterDocumentation(namSpace);
}
engine->registerDocumentation( QString{"/path/to/qch/%1.qch"}.arg(lang) );
engine->setupData();
});
ui->comboBox->setCurrentIndex(ui->comboBox->findText(lang));