【问题标题】:How to translate default qsTr fields - e.g. MessageDialog Yes / No buttons如何翻译默认 qsTr 字段 - 例如MessageDialog 是/否按钮
【发布时间】:2015-10-21 22:36:22
【问题描述】:

我有一个使用 Qt Quick MessageDialog 的小应用程序。我用命令创建了翻译文件

lupdate-qt5 ../myapp.pro . 

在 myapp.pro 我指出:

lupdate_only {
    SOURCES +=  $$PWD/ui/*.qml
} 

TRANSLATIONS += \
   translations/i18n_nl.ts translations/i18n_fr.ts translations/i18n_en.ts

所有翻译均正确生成。但我不知道如何为MessageDialog 提供的标准按钮生成翻译。在以下示例中,将生成“警告”和“请选择是或否”的翻译。但我无法为“是”和“否”生成它们(这是StandardButtons 属性的文本值)

MessageDialog {
    title: qsTr("Warning")
    text: qsTr("Please select Yes or No")
    icon: StandardIcon.Warning
    standardButtons: StandardButton.Yes | StandardButton.No
    //.....
}

我检查了source code,它表明它们应该被翻译:

Button {
    id: yesButton
    text: qsTr("Yes")
    onClicked: root.click(StandardButton.Yes)
    visible: root.standardButtons & StandardButton.Yes
}

我也尝试手动添加条目YesNo,但这似乎没有帮助。

我找到了一个issue on stackoverflow,它谈到了将 qml 文件添加到 .pro 文件以使其工作,这是我已经在做的事情。我想添加内置的MessageDialog,但我不知道该怎么做。

最后一点:我知道在 Qt 5.3 中 qsTr 不在 MessageDialog 中。但从 Qt 5.4 开始,它们是。我目前使用的是 Qt 5.5

非常感谢任何帮助。

编辑

发布此消息后,我一直在寻找并找到遇到同样问题的人的interesting post。不幸的是,那里没有答案。

编辑 2

感谢 tynn 的回复。我已经尝试了这两种建议,但都没有成功。我也尝试过别的东西。我在我的代码中添加了一个 qDebug 以查看它是否会翻译。我希望 MessageDialog 也能使用相同的翻译,但不幸的是,情况似乎并非如此。

qDebug() << "Translate yes :" << tr("Yes"); //translates correctly, dialog doesn't

我还尝试从头开始构建一个与内置消息对话框相同的对话框,但目前我对 qml 的了解太有限,无法使其正常工作。

【问题讨论】:

  • 我也有同样的问题,问了之后找到解决办法了吗?

标签: qt qml qtquick2 qt5.5


【解决方案1】:

嗯,这可能有点棘手。

首先,Qt 小部件的本地化字符串可能位于 Qt 的 .qm 文件中。请记住,一般情况下,您将需要所有 Qt 的 .qm 文件来翻译您的语言环境。这是因为 Qt 可能会在可用的平台上使用原生 MessageDialogs,在这种情况下,相关代码将位于 qtbase 中,因此您不仅需要 qtquickcontrols_XX.qm 文件,还需要用于选定语言环境的 qtbase_XX.qm 文件.以此类推。

但是,在某些情况下,上述方法可能无济于事。您的语言环境的 Qt 本地化文件中可能只是缺少必需的字符串(这很常见),因此您需要自己为这些字符串制作 .ts 和 .qm 文件。在这种情况下,您需要研究 Qt 源代码以了解您感兴趣的那些小部件的内部结构。

请注意,以下示例取决于可能在未来 Qt 版本中更改的实现细节。

例如,用于 Android 和 iOS 的 QML MessageDialog 的 Qt 实现使用了QPlatformTheme,它可以进一步子类化以适用于不同的平台。在 QPlatformTheme 中,按钮标签的文本由 defaultStandardButtonText() 方法返回,如下所示:

QString QPlatformTheme::defaultStandardButtonText(int button)
{
    switch (button) {
    case QPlatformDialogHelper::Ok:
        return QCoreApplication::translate("QPlatformTheme", "OK");
    case QPlatformDialogHelper::Save:
        return QCoreApplication::translate("QPlatformTheme", "Save");
    case QPlatformDialogHelper::SaveAll:
        return QCoreApplication::translate("QPlatformTheme", "Save All");
    case QPlatformDialogHelper::Open:
        return QCoreApplication::translate("QPlatformTheme", "Open");
    case QPlatformDialogHelper::Yes:
        return QCoreApplication::translate("QPlatformTheme", "&Yes");
    case QPlatformDialogHelper::YesToAll:
        return QCoreApplication::translate("QPlatformTheme", "Yes to &All");
    case QPlatformDialogHelper::No:
        return QCoreApplication::translate("QPlatformTheme", "&No");
    case QPlatformDialogHelper::NoToAll:
        return QCoreApplication::translate("QPlatformTheme", "N&o to All");
    case QPlatformDialogHelper::Abort:
        return QCoreApplication::translate("QPlatformTheme", "Abort");
    case QPlatformDialogHelper::Retry:
        return QCoreApplication::translate("QPlatformTheme", "Retry");
    case QPlatformDialogHelper::Ignore:
        return QCoreApplication::translate("QPlatformTheme", "Ignore");
    case QPlatformDialogHelper::Close:
        return QCoreApplication::translate("QPlatformTheme", "Close");
    case QPlatformDialogHelper::Cancel:
        return QCoreApplication::translate("QPlatformTheme", "Cancel");
    case QPlatformDialogHelper::Discard:
        return QCoreApplication::translate("QPlatformTheme", "Discard");
    case QPlatformDialogHelper::Help:
        return QCoreApplication::translate("QPlatformTheme", "Help");
    case QPlatformDialogHelper::Apply:
        return QCoreApplication::translate("QPlatformTheme", "Apply");
    case QPlatformDialogHelper::Reset:
        return QCoreApplication::translate("QPlatformTheme", "Reset");
    case QPlatformDialogHelper::RestoreDefaults:
        return QCoreApplication::translate("QPlatformTheme", "Restore Defaults");
    default:
        break;
    }
    return QString();
}

因此,为了本地化是/否按钮,您需要在 .ts 文件中添加以下内容:

<context>
    <name>QPlatformTheme</name>
    <message>
        <source>&amp;Yes</source>
        <translation>[...]</translation>
    </message>
    <message>
        <source>&amp;No</source>
        <translation>[...]</translation>
    </message>
</context>

Android 有自己的子类平台主题 (QAndroidPlatformTheme),并覆盖了 defaultStandardButtonText(),因此对于 Android,您需要添加以下内容:

<context>
    <name>QAndroidPlatformTheme</name>
    <message>
        <source>Yes</source>
        <translation>[...]</translation>
    </message>
    <message>
        <source>No</source>
        <translation>[...]</translation>
    </message>
</context>

iOS 不会在其自己的 QPlatformTheme 子类中覆盖此方法,因此无需对其进行额外操作。

您可以查看one of my projects,它使用上述技术在 Android 和 iOS 上进行 QML MessageBox 本地化。

【讨论】:

  • 我想知道您如何防止 Qt 在我们每次更新它们时消失这些翻译?
【解决方案2】:

您需要的翻译应该在qtquickcontrols_*.qm 文件中找到。 Deploying Translations 声明与此有关

通常,应用程序都有 .qm 文件,如果使用了系统上未安装的 Qt 版本,则还需要部署 Qt 的 .qm 文件。

但是,您的应用程序可能无法找到合适的翻译文件。如果您只需要YesNo 的翻译,您也可以将它们添加到您的翻译文件中,并使用DefaultMessageDialog 的上下文

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
    <name>DefaultMessageDialog</name>
    <message>
        <source>Yes</source>
        <translation type="unfinished"></translation>
    </message>
    <message>
        <source>No</source>
        <translation type="unfinished"></translation>
    </message>
</context>
</TS>

添加内置 MessageDialog 也可以。或者,如果您愿意,您可以使用虚拟文件 DefaultMessageDialog.qml

Rectangle {
    Button {
        id: yesButton
        text: qsTr("Yes")
    }
    Button {
        id: noButton
        text: qsTr("No")
    }
}

然后添加这个。

【讨论】:

    【解决方案3】:

    在 Windows、macOS 和 Linux 等桌面平台上,QtQuick.Dialogs 中的大多数 Dialog 组件都使用 C++ 小部件组件。他们的源翻译包含在qtbase_{lang}.ts 文件中,他们的编译翻译包含在qtbase_{lang}.qmfiles 中。

    在 Qt5.13.1 中:

    • 请参阅C:\Qt\Qt5.13.1\5.13.1\Src\qttranslations\translations 获取源翻译
    • 编译后的翻译请参考C:\Qt\Qt5.13.1\5.13.1\mingw83_64\translations

    如果您发现 qtbase 的大小太大而无法满足您的喜好,您可以部署翻译文件的缩小版本。以下 Windows 批处理文件创建 qtbase 文件的法语、德语和日语子集:

    setlocal
    set QTDIR=C:\Qt\Qt5.13.1\5.13.1\msvc2017_64\
    set QTSRC=C:\Qt\Qt5.13.1\5.13.1\Src
    ECHO %QTSRC%\qtbase\src\widgets\dialogs\qmessagebox.cpp > %TEMP%\qtbase_min.lst
    ECHO %QTSRC%\qtbase\src\widgets\dialogs\qfiledialog.cpp >> %TEMP%\qtbase_min.lst
    ECHO %QTSRC%\qtbase\src\widgets\dialogs\qcolordialog.cpp >> %TEMP%\qtbase_min.lst
    ECHO %QTSRC%\qtbase\src\widgets\dialogs\qfontdialog.cpp >> %TEMP%\qtbase_min.lst
    ECHO %QTSRC%\qtbase\src\widgets\dialogs\qinputdialog.cpp >> %TEMP%\qtbase_min.lst
    ECHO %QTSRC%\qtbase\src\widgets\dialogs\qprogressdialog.cpp >> %TEMP%\qtbase_min.lst
    ECHO %QTSRC%\qtbase\src\widgets\dialogs\qwizard.cpp >> %TEMP%\qtbase_min.lst
    ECHO %QTSRC%\qtbase\src\gui\kernel\qplatformtheme.cpp >> %TEMP%\qtbase_min.lst
    ECHO %QTSRC%\qtbase\src\plugins\platforms\android\qandroidplatformtheme.cpp >> %TEMP%\qtbase_min.lst
    ECHO %QTSRC%\qtbase\src\platformsupport\themes\genericunix\qgenericunixthemes.cpp >> %TEMP%\qtbase_min.lst
    for /d %%F in (fr de ja en) do copy %QTSRC%\qttranslations\translations\qtbase_%%F.ts qtbase_min_%%F.ts
    %QTDIR%\bin\lupdate @%TEMP%/qtbase_min.lst -pluralonly -locations none -ts qtbase_min_en.ts
    for /d %%F in (fr de ja en) do if "%%F" neq "en" %QTDIR%\bin\lupdate.exe @%TEMP%/qtbase_min.lst -no-obsolete -locations none -ts qtbase_min_%%F.ts
    for /d %%F in (fr de ja en) do %QTDIR%\bin\lrelease qtbase_min_%%F.ts
    

    在 iOS 和 Android 等移动平台上,Dialog MessageDialog 组件的可翻译文本仍包含在qtbase_{lang}.ts 文件中。对于其他组件,例如 ColorDialog、FontDialog,它们在 QML 中作为 QtQuick 组件实现。翻译将在qtquickcontrols_{lang}.tsqtquickcontrols_{lang}.qm 文件中找到。

    以下演示如何为法语、德语和日语创建 qtquickcontrols_{lang}.tsqtquickcontrols_{lang}.qm 文件的缩小版本:

    setlocal
    set QTDIR=C:\Qt\Qt5.13.1\5.13.1\msvc2017_64\
    set QTSRC=C:\Qt\Qt5.13.1\5.13.1\Src
    ECHO %QTSRC%\qtquickcontrols\src\dialogs\DefaultMessageDialog.qml > %TEMP%\qtquickcontrols_min.lst
    ECHO %QTSRC%\qtquickcontrols\src\dialogs\DefaultColorDialog.qml >> %TEMP%\qtquickcontrols_min.lst
    ECHO %QTSRC%\qtquickcontrols\src\dialogs\DefaultFileDialog.qml >> %TEMP%\qtquickcontrols_min.lst
    ECHO %QTSRC%\qtquickcontrols\src\dialogs\DefaultFontDialog.qml >> %TEMP%\qtquickcontrols_min.lst
    ECHO %QTSRC%\qtquickcontrols\src\dialogs\DefaultDialogWrapper.qml >> %TEMP%\qtquickcontrols_min.lst
    for /d %%F in (fr de ja en) do copy %QTSRC%\qttranslations\translations\qtquickcontrols_%%F.ts qtquickcontrols_min_%%F.ts
    %QTDIR%\bin\lupdate @%TEMP%/qtquickcontrols_min.lst -pluralonly -locations none -ts qtquickcontrols_min_en.ts
    for /d %%F in (fr de ja en) do if "%%F" neq "en" %QTDIR%\bin\lupdate.exe @%TEMP%/qtquickcontrols_min.lst -no-obsolete -locations none -ts qtquickcontrols_min_%%F.ts
    for /d %%F in (fr de ja en) do %QTDIR%\bin\lrelease qtquickcontrols_min_%%F.ts
    

    目前,在 Qt5.13.1 中,有 22 种语言(包括英语)。如果您想要的语言不在此列表中(例如印度尼西亚语、越南语),那么您仍然可以使用上述脚本创建 qtbase/qtquickcontrols 的占位符缩小版本,但您必须自己填充 qtbase_min_{lang}.ts 文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-26
      • 2016-12-02
      • 2019-01-25
      • 2021-01-10
      • 2019-04-10
      • 1970-01-01
      • 2014-06-22
      相关资源
      最近更新 更多