编写用于翻译的源代码

以能够本地化应用程序的方式编写 QML 和 Qt C++ 源代码:

开发 C++ 应用程序时,另请参阅C++ 代码的其他注意事项

标记要翻译的字符串

应用程序中必须翻译的文本大多由单词或短语组成。这些文本通常显示为窗口标题、菜单项、工具提示以及按钮、复选框和单选按钮的标签。

Qt 在创建每个窗口时都会为其翻译短语,从而将使用翻译的性能成本降至最低。在大多数应用程序中,主窗口只创建一次。对话框通常只创建一次,然后根据需要显示或隐藏。一旦完成初始翻译,翻译后的窗口就不会再有运行时开销。只有那些创建、销毁和随后创建的窗口才会产生翻译性能成本。

您可以创建在运行时切换语言的应用程序,但这需要付出努力,而且会产生运行时性能成本。

在 QML 和 C++ 代码中使用翻译函数来标记用户可见的 UI 文本以进行翻译。Qt 会根据与之关联的翻译上下文对每个可翻译字符串进行索引。同一短语可能出现在多个上下文中,但不会发生冲突。如果一个短语在一个特定上下文中出现不止一次,它只会被翻译一次,并且翻译会应用到上下文中出现的每一次。

QML:使用 qsTr()

在 QML 中,您可以使用以下函数来标记用户可见字符串,以便在 .qml 文件中进行翻译:

通常,您使用qsTr() 函数:

Text {
    id: txt1
    text: qsTr("Back")
}

这段代码使Back成为翻译源 (TS) 文件中的关键条目。运行时,翻译系统会查找关键字Back,然后获取当前系统语言的相应翻译值。结果将返回text 属性,用户界面将显示Back在当前本地的相应翻译。如果找不到翻译,qsTr() 将返回原始字符串。

翻译上下文可通过以下方式设置:

pragma Translator: ChosenContext

pragma Translator: "Chosen::Context"

通过qsTranslate() 设置的上下文优先于通过pragma Translator 设置的上下文。在 QML 中,默认情况下,翻译上下文是文件名。

C++:使用 tr()

在 C++ 中,使用tr() 函数将文本标记为可翻译文本并显示翻译后的文本。翻译上下文是字符串使用的QObject 子类的名称。要为基于QObject 的新类定义翻译上下文,请在每个新类定义中使用Q_OBJECT 宏。

当调用tr() 时,它会使用QTranslator 对象查找可翻译的字符串,如启用翻译中所述,您必须在应用程序对象上安装该对象。

例如,假设LoginWidgetQWidget 的子类:

LoginWidget::LoginWidget()
{
    QLabel *label = new QLabel(tr("Password:"));
    ...
}

这占用户可能编写的可视字符串的 99%。有关标记可翻译字符串字面量的信息,请参阅标记可翻译数据文本字符串

如果引号文本不在QObject 子类的成员函数中,请使用适当类的tr() 函数,或直接使用QCoreApplication::translate() 函数:

void some_global_function(LoginWidget *logwid)
{
    QLabel *label = new QLabel(
                LoginWidget::tr("Password:"), logwid);
}

void same_global_function(LoginWidget *logwid)
{
    QLabel *label = new QLabel(
                QCoreApplication::translate("LoginWidget", "Password:"), logwid);
}

注意: 如果在编译应用程序时定义了宏QT_NO_CAST_FROM_ASCII ,从而禁用了const char *QString 的自动转换,则很可能会捕捉到丢失的任何字符串。更多信息请参见QString::fromUtf8() 和QString::fromLatin1()。

使用参数而不是连接字符串

不同的语言在短语、分句和句子中排列单词的方式不同,因此不要通过连接单词和数据来创建字符串。相反,可以使用% 在字符串中插入参数。

例如,在字符串After processing file %1, file %2 is next in line 中,%1%2 是编号参数。运行时,%1%2 将分别替换为第一个和第二个文件名。翻译中必须出现相同的编号参数,但顺序不一定相同。该字符串的德语翻译可能会颠倒短语。例如,Datei %2 wird bearbeitet, wenn Datei %1 fertig ist 。两个编号参数都会出现在译文中,但顺序相反。

QML:使用 .arg()

下面的 QML 代码段包含一个字符串,其中有两个数字参数%1%2 。这些参数与.arg() 函数一起插入。

Text {
    text: qsTr("File %1 of %2").arg(counter).arg(total)
}

%1 指的是第一个参数,而 指的是第二个参数,因此这段代码会产生类似的输出:%2 文件 2,共 3 个

避免使用带参数的模板字符串,因为生成的字符串是在运行时而不是编译时定义的。因此,翻译工具无法为模板字符串找到正确的翻译。

C++:使用 QString::arg()

在 C++ 中,使用QString::arg() 函数替换参数:

void FileCopier::showProgress(int done, int total,
                              const QString &currentFile)
{
    label.setText(tr("%1 of %2 files copied.\nCopying: %3")
                  .arg(done)
                  .arg(total)
                  .arg(currentFile));
}

这段代码会产生如下输出已复制 10 个文件中的 5 个。复制:somefile.txt

处理复数形式

您可以向翻译函数传递一个额外的整数参数(n),并在每个可翻译字符串中使用复数形式的特殊符号 (%n)。

根据n 的值,翻译函数将返回不同的译文,并为目标语言提供正确的语法编号。此外,%n 会被n 的值替换。

例如,字符串%n message(s) saved 的英语和法语翻译需要不同的复数形式。

n无翻译法语英语
0"保存了 0 条信息"保存了 0 条信息""保存了 0 条信息
1"保存了 1 条信息"保存了 1 条信息""保存了 1 条信息
2"保存了 2 条信息"2 条受保护信息""保存了 2 条信息
37"已保存 37 条信息"保存了 37 条信息""保存了 37 条信息

该成语也适用于有多种复数形式的目标语言,如复数形式。此外,对于法语等需要使用单数的语言,该成语还能正确处理n == 0 的情况。

Qt Linguistlrelease 用于翻译包含复数形式的字符串的规则摘要,请参阅复数形式的翻译规则

要处理母语中的复数形式,也要加载该语言的 TS 文件。使用lupdate 工具-pluralonly 命令行选项,创建只包含复数形式条目的 TS 文件。

或者,也可以使用lconvert 工具的-pluralonly 命令行选项,从现有 TS 文件中删除所有非复数形式。

QML 示例

以下 QML 代码片段将源代码文本转换为正确的复数形式,并将%n 替换为total 的值:

Text {
    text: qsTr("%n message(s) saved", "", total)
}

C++ 示例

以下 C++ 代码片段将%n 替换为count() 函数返回的值:

int n = messages.count();
showMessage(tr("%n message(s) saved", "", n));

使用区域编号设置

如果在指定参数时包含%L 修饰符,则会根据当前的地区设置对数字进行本地化。如果您设置了默认区域设置,转换将使用默认区域设置,否则将使用系统范围内的区域设置。

QML:使用 %L

例如,在下面的 QML 代码段中,%L1 根据当前所选区域(地理区域)的数字格式约定格式化第一个参数:

Text {
    text: qsTr("%L1").arg(total)
}

如果total 是数字4321.56,在英语地区设置(locale)下,输出结果是4,321.56,而在德语地区设置下,输出结果是4.321,56

C++:使用 %Ln

在 C++ 中,可以使用%Ln 来生成n 的本地化表示。使用QLocale::setDefault() 来设置默认本地化。

将日期、时间和货币国际化

使用本地首选格式显示日期、时间和货币。

QML:使用 QtQml 函数

QML 没有特殊的字符串内修饰符来格式化日期和时间。相反,您需要查询当前的 locale(地理区域),并使用Date 的方法来格式化字符串。

Qt.locale() 返回一个 对象,其中包含有关本地信息。其中, 属性包含当前语言和国家/地区的信息。您可以按原样使用该值,也可以对其进行解析,以确定适合当前本地语言的内容。Locale Locale.name

以下代码段通过Date() 获取当前日期和时间,然后将其转换为当前语言的字符串。然后将日期字符串插入%1 参数,以便进行适当的翻译。

Text {
    text: qsTr("Date %1").arg(Date().toLocaleString(Qt.locale()))
}

要本地化货币数字,请使用Number 类型。它具有与Date 类型类似的功能,可将数字转换为本地化的货币字符串。

C++:使用 QLocale 类

在 C++ 中,使用QLocale::timeFormat() 或QLocale::toString(QTime) 或toString(QDate)

QLabel *label = new QLabel(this);
label->setText(tr("Date %1").arg(QLocale().toString(QDate::currentDate()));

标记可翻译数据文本字符串

使用_NOOP 函数(在 QML 中)和_NOOP 宏(在 C++ 中)标记可翻译字符串字面,以便lupdate 工具提取。

QML:使用 _NOOP 函数

在 QML 中,使用以下函数标记可翻译的字符串字面量:

如果用户在未重启的情况下更改系统语言,根据系统的不同,数组、列表模型和其他数据结构中的字符串可能不会自动刷新。要在用户界面中显示文本时强制刷新文本,需要使用QT_TR_NOOP() 函数声明字符串。然后,在填充对象以进行显示时,需要明确检索每个文本的翻译。

例如

ListModel {
    id: myListModel

    ListElement {
        //: Capital city of Finland
        name: QT_TR_NOOP("Helsinki")
    }
}

...

Text {
    text: qsTr(myListModel.get(0).name)
    // Get the translation of the name property in element 0
}

C++:使用 _NOOP 宏

对于完全在函数之外的可翻译文本,可使用QT_TR_NOOP() 和QT_TRANSLATE_NOOP() 宏,它们仅扩展到文本而不包含上下文。

QT_TR_NOOP() 的示例

QString FriendlyConversation::greeting(int type)
{
    static const char *greeting_strings[] = {
        QT_TR_NOOP("Hello"),
        QT_TR_NOOP("Goodbye")
    };
    return tr(greeting_strings[type]);
}

QT_TRANSLATE_NOOP() 的示例:

static const char *greeting_strings[] = {
    QT_TRANSLATE_NOOP("FriendlyConversation", "Hello"),
    QT_TRANSLATE_NOOP("FriendlyConversation", "Goodbye")
};

QString FriendlyConversation::greeting(int type)
{
    return tr(greeting_strings[type]);
}

QString global_greeting(int type)
{
    return QCoreApplication::translate("FriendlyConversation",
                                       greeting_strings[type]);
}

为翻译添加注释

您可以在源代码中标记为可翻译的字符串前添加注释,以明确其目的。这些注释将包含在您提供给翻译人员的 TS 文件中。

注: TS 文件是 XML 文件,包含源代码和翻译文本。更新后的 TS 文件将转换为二进制翻译文件,并作为最终应用程序的一部分。

QML:使用 //: 和 //~

在下面的代码片段中,//: 行上的文本是翻译器的主要注释。

//~ 行上的文本是可选的额外信息。文本的第一个单词在 TS 文件的 XML 元素中用作附加标识符,因此要确保第一个单词不是句子的一部分。例如,注释Context Not related to back-stepping会在 TS 文件中转换为<extra-Context>Not related to back-stepping

Text {
    id: txt1;
    // This UI string is only used here
    //: The back of the object, not the front
    //~ Context Not related to back-stepping
    text: qsTr("Back");
}

C++:使用注释字符

要在 C++ 中添加注释,可使用//: 形式的注释或通过标记注释的开始和结束来注释代码中的tr() 调用。

在下面的示例中,注释与每次调用上下文中传递给tr() 的字符串相关联:

//: This name refers to a host name.
hostNameLabel->setText(tr("Name:"));

/*: This text refers to a C++ code example. */
QString example = tr("Example");

要添加可选注释,请使用

//~ <field name> <field contents>

字段名称应由域前缀(可能是字段所借鉴文件格式的常规文件扩展名)、连字符和以下划线分隔的实际字段名称组成。在 TS 文件中存储时,字段名和前缀extra- 将组成一个 XML 元素名。字段内容将被 XML 转义,但在其他方面与元素内容一模一样。您可以为每条信息添加任意数量的唯一字段。

例如

//: This is a comment for the translator.
//= qtn_foo_bar
//~ loc-layout_id foo_dialog
//~ loc-blank False
//~ magic-stuff This might mean something magic.
QString text = MyMagicClass::tr("Sim sala bim.");

在 C++ 中,您可以使用等号来添加唯一标识符:

//= <id>

对于翻译注释,可以使用关键字TRANSLATOR。出现在关键字 TRANSLATOR 前面的元数据适用于整个 TS 文件。

注意: 当在Qt Linguist 中打开 TS 文件时,//: 所注释的注释将显示在Qt Linguist 的信息编辑器中。而使用//~ 注释的文本是额外信息,仅在 TS 文件中生成。它们主要用于转换为其他格式,并隐藏在Qt Linguist 中。

消除相同文本的歧义

翻译系统会将用户界面文本字符串合并为唯一项目,以避免重复翻译相同文本。但是,一个文本可能看起来与另一个文本完全相同,但却有不同的含义。例如,在英语中,"back"既指后退一步,也指物体与前方相对的部分。您需要告诉翻译系统这两个不同的含义,这样译员就可以创建两个不同的译文。

QML:为 qsTr() 添加消歧义器

在 QML 中,添加一个消歧义字符串作为qsTr() 函数的第二个参数。

在下面的代码片段中,IDnot front 将此Back文本与后退的Back文本区分开来:

Text {
    id: txt1
    // This UI string is used only here
    //: The back of the object, not the front
    //~ Context Not related to back-stepping
    text: qsTr("Back", "not front")
}

C++:为 tr() 添加消歧义函数

在 C++ 中,在调用tr() 时传递一个消除歧义的字符串。

在下面的代码片段中,IDrecipient 将收件人姓名与发件人姓名区分开来:

MyWindow::MyWindow()
{
    QLabel *senderLabel = new QLabel(tr("Name:"));
    QLabel *recipientLabel = new QLabel(tr("Name:", "recipient"));
    ...

使键盘快捷键可翻译

在最常见的形式中,键盘快捷方式描述了按下组合键来执行某些操作。对于standard shortcuts ,使用标准键来请求与每个快捷键相关的特定平台按键序列。

对于自定义快捷方式,请使用人类可读字符串,如Ctrl+QAlt+F。您可以将它们翻译成适合不同语言使用者的快捷方式。

如果在应用程序中硬编码键盘快捷方式,翻译人员就无法覆盖它们。

在菜单项和按钮文本中使用键盘快捷方式时,一个助记符(用下划线标出)表示按下AltCtrl 键时,下划线字符将执行与单击菜单项或按下按钮相同的操作。

例如,在File 菜单中,应用程序通常使用F作为助记符,因此可以单击菜单项或按Alt+F打开菜单。要在可翻译字符串("文件")中定义助记符,请在其前加一个括号:"&File" 。该字符串的译文也应包含一个 "括号",最好在同一字符前。

QML 示例

在 QML 中

Menu {
    id: fileMenu
    title: qsTr("&File")

    MenuItem {
        objectName: "quitMenuItem"
        text: qsTr("E&xit")
        onTriggered: Qt.quit()
    }
}

C++:使用 QKeySequence 类

在 C++ 中,使用QActionQKeySequence 对象来指定触发操作的键盘快捷键:

exitAct = new QAction(tr("E&xit"), this);
exitAct->setShortcuts(QKeySequence::Quit);

键盘快捷键的翻译与QShortcut 上下文相关联。

使用本地化扩展本地化功能

您可能会发现不同的图形或音频更适合不同的地理区域。

一般来说,尽量避免本地化图像。创建适合全球的图标,而不是依赖本地双关语或捉襟见肘的比喻。不过,对于阿拉伯语和希伯来语地区,您可能需要反转左右箭头的图像。

本地化是默认的文件选择器之一,因此您可以根据系统的本地化情况,使用文件选择来显示作为资源提供的不同图像。

以下章节中的 QML 和 C++ 代码示例假定您在应用程序资源中提供以下文件,并使用语言和国家代码作为子文件夹名称:

images
├── language-icon.png
├── +en_GB
│   └── language-icon.png
└── +fi_FI
    └── language-icon.png

QML:设置图像源

下面的 QML 代码片段显示了如何根据当前语言选择图标源图像:

icon.source: "qrc:/images/language-icon.png"

C++:使用 QFileSelector

以下 C++ 代码片段使用QFileSelectorimages 文件夹中根据系统地域选择语言图标:

const QFileSelector selector;
const QIcon languageIcon(selector.select(":/images/language-icon.png"));

启用翻译

TS 文件名必须包含 ISO 语言和国家代码:

  • language是小写的ISO-639语言代码。
  • country是大写的ISO-3166双字母国家代码。

例如,qml_de.ts 设置目标语言为德语,qml_de_CH.ts 设置目标语言为德语,目标国家为瑞士。lrelease 工具会生成名为qml_de.qmqml_de_CH.qm 的 QM 文件,应用程序会根据系统地域加载这些文件。

QML:使用 QQmlApplicationEngine

在 QML 中,使用QQmlApplicationEngine 从包含 QML 主文件的目录中名为i18n 的子目录自动加载翻译文件。翻译文件名的前缀必须是qml_ 。例如,qml_en_US.qm 。请参阅以下 CMake 代码片段,了解如何设置多语言应用程序:

...
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick LinguistTools)
qt_standard_project_setup(REQUIRES 6.5 I18N_TRANSLATED_LANGUAGES ja_JP)

qt_add_qml_module(appmultilingual_demo
    URI multilingual_demo
    QML_FILES
        Main.qml
)

qt_add_translations(appmultilingual_demo
    TS_FILE_BASE qml
    TS_FILE_DIR i18n
    RESOURCE_PREFIX /qt/qml/multilingual_demo/i18n
)
...

QJSEngine::uiLanguageQt.uiLanguage 属性值发生变化时,应用程序会重新加载翻译文件。以下代码片段可在用户点击按钮时动态更改语言:

Button {
    anchors.centerIn: parent
    text: qsTr("Translate")
    onClicked: {
        Qt.uiLanguage = Qt.uiLanguage === "en" ? "ja" : "en"
    }
}

C++:使用 QTranslator

在 C++ 中,TS 文件名必须包含应用程序名称。例如,app_de_DE.ts

通常,您的 Qt C++ 应用程序的main() 函数将如下所示:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QTranslator myappTranslator;
    if (myappTranslator.load(QLocale::system(), u"myapp"_s, u"_"_s, u":/i18n"_s))
        app.installTranslator(&myappTranslator);

    return app.exec();
}

对于翻译感知应用程序,您需要创建一个QTranslator 对象,在运行时根据用户的 UI 显示区域创建load 翻译,并将翻译对象安装到应用程序中。

为动态语言变化做好准备

Qt WidgetsQt Quick 都使用Qt XML 的事件系统来通知类有关翻译的变化。

LanguageChange 当您使用 () 函数安装新的翻译时,就会发布事件。其他应用程序组件也可以通过发布 事件,强制源于 类型的部件或 QML 类型更新自己。QCoreApplication::installTranslator LanguageChange Item

默认情况下,LanguageChange 事件会传播到所有顶层窗口,然后再传播到整个部件树或从 Item 派生的 QML 类型。

Qt Widgets:覆盖 changeEvent

QWidget 子类的默认事件处理程序会响应QEvent::LanguageChange 事件,并在必要时调用changeEvent() 函数。

要让 Qt Widgets 知晓已安装的QTranslator 对象的变化,请重新实现 widget 的changeEvent() 函数,以检查该事件是否为LanguageChange 事件,并使用tr() 函数更新 widgets 显示的文本。例如

void MyWidget::changeEvent(QEvent *event)
{
    if (event->type() == QEvent::LanguageChange) {
        titleLabel->setText(tr("Document Title"));
        ...
        okPushButton->setText(tr("&OK"));
    } else
        QWidget::changeEvent(event);
}

当使用Qt Widgets Designer UI 文件 (.ui) 和uic 时,可以读取新的翻译文件并直接调用ui.retranslateUi(this)

void MyWidget::changeEvent(QEvent *event)
{
    if (event->type() == QEvent::LanguageChange) {
        ui.retranslateUi(this);
    } else
        QWidget::changeEvent(event);
}

要传递其他更改事件,请调用该函数的默认实现。

已安装的翻译列表可能会响应LocaleChange 事件而改变,或者应用程序可能会提供一个用户界面,允许用户更改当前的应用程序语言。

QML:从 Item 派生的类型的覆盖事件

对于没有任何自定义 C++ 注册类型的普通 QML 应用程序,使用 QQmlApplicationEngine就足以触发所有翻译绑定的更新。

但是,如果您注册了一个派生自QQuickItem 的类型,并且它的一个属性暴露了翻译文本(或以其他方式依赖于语言),请覆盖它的event method 并在其中发出属性变化信号(或在可绑定属性的情况下调用notify )。例如

class MyItem : public QQuickItem
{
    Q_OJBECT
    QML_ELEMENT

    Q_PROPERTY(QString greeting READ greeting NOTIFY greetingChanged)

public signals:
    void greetingChanged();
public:
    QString greeting() const
    {
        return tr("Hello World!");
    }

    bool event(QEvent *ev) override
    {
        if (ev->type() == QEvent::LanguageChange)
            emit greetingChanged();
        return QQuickItem::event(ev);
    }
};

这可确保在 QML 中使用该属性的任何绑定都会被重新评估,并将语言变化考虑在内。

通用 QObject 派生类:使用事件过滤器

有些类既不是从QWidget 派生的,也不是从QQuickItem 派生的,但仍可能需要处理语言变化事件。在这种情况下,请在QCoreApplication 上安装一个事件过滤器

class CustomObject : public QObject
{
    Q_OBJECT

public:
    QList<QQuickItem *> managedItems;

    CustomObject(QOject *parent = nullptr) : QObject(parent)
    {
        QCoreApplication::instance()->installEventFilter(this);
    }

    bool eventFilter(QObject *obj, QEvent *ev) override
    {
        if (obj == QCoreApplication::instance() && ev->type() == QEvent::LanguageChange) {
            for (auto item : std::as_const(managedItems))
                QCoreApplication::sendEvent(item, ev);
            // do any further work on reaction, e.g. emit changed signals
        }
        return false;
    }
};

当类提供的翻译字符串随后会显示在用户界面(例如自定义item model )中,或者当类作为 Widget 或快速项目的容器,因此负责将事件转发给它们时,可能需要这样做。

C++ 代码的其他注意事项

以下章节包含了在可翻译应用程序中使用 Qt C++ 类和函数的更多信息:

对所有用户可见文本使用 QString

QString 在内部使用Unicode编码,因此您可以使用熟悉的文本处理操作来透明地处理世界上的所有语言。此外,由于所有向用户展示文本的 Qt 函数都将 对象作为参数,因此没有 到 的转换开销。QString char * QString

定义翻译上下文

QObject 和每个QObject 子类的翻译上下文是类名本身。如果您对QObject 进行子类化,请使用类定义中的Q_OBJECT 宏覆盖翻译上下文。该宏将上下文设置为子类的名称。

例如,下面的类定义包含Q_OBJECT 宏,实现了一个使用MainWindow 上下文的新函数tr()

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow();
    ...

如果在类定义中不使用Q_OBJECT ,上下文将从基类继承。例如,由于 Qt 中所有基于QObject 的类都提供了上下文,因此如果调用其tr() 函数,定义的新QWidget 子类如果没有使用Q_OBJECT 宏,就会使用QWidget 上下文。

翻译非 Qt 类

对于未继承QObject 或未使用Q_OBJECT 宏的类,您必须为lupdate 提供有关字符串的额外信息。要为非 Qt 类添加翻译支持,可以使用Q_DECLARE_TR_FUNCTIONS() 宏。例如

class MyClass
{
    Q_DECLARE_TR_FUNCTIONS(MyClass)

public:
    MyClass();
    ...
};

这将为类提供tr() 函数,用于翻译与类相关的字符串,并使lupdate 能够在源代码中找到可翻译的字符串。

另外,您也可以使用lupdateQt Linguist 能够识别的特定上下文调用QCoreApplication::translate() 函数。

翻译 QObject 子类之外的文本

如果引用的文本不在QObject 子类的成员函数中,请使用适当类的tr() 函数或直接使用QCoreApplication::translate() 函数:

void some_global_function(LoginWidget *logwid)
{
    QLabel *label = new QLabel(
            LoginWidget::tr("Password:"), logwid);
}

void same_global_function(LoginWidget *logwid)
{
    QLabel *label = new QLabel(
            QCoreApplication::translate("LoginWidget", "Password:"),
            logwid);
}

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.