【问题标题】:Translate String Representation of Enum Values Qt转换枚举值 Qt 的字符串表示
【发布时间】:2017-05-07 07:28:57
【问题描述】:

是否可以使用 Qt 的翻译系统翻译 enum 的字符串表示形式(即通过 QMetaEnum)?

我认为我需要的是某种方式让lupdate 获取枚举字符串进行翻译,或者通过发出一些 QT_TR_NOOP() 代码当且仅当文件正在由 lupdate 处理时,或者通过修改lupdate/moc 自己的行为。

例如,我的应用程序通过对话框向用户显示“设置”选项。所有设置都定义为Q_PROPERTY。使用enum 的选项显示为组合框,组合框的文本选项使用QMetaEnum::key() 作为显示文本。下面是一些用来说明问题的伪代码。

小部件将有一些 enum 属性定义如下:

class SomeWidget : public QWidget
{
    Q_OBJECT
    Q_ENUMS( Configuration );

    enum Configuration
    {
        Config_Blue = 0,
        Config_Green,
        Config_Invisible,
        Config_Backwards
    };

    Q_PROPERTY( Configuration READ Configuration WRITE SetConfiguration );
};

组合小部件的创建由单独的设置管理器完成,如下所示:

QWidget* SettingsItem::CreateWidget()
{
    const QMetaObject* pMetaObj = this->m_pWidget->metaObject();
    const QMetaProperty& rcProp = pMetaObj->property( this->m_iProp );

    QMetaEnum cEnum = rcProp.enumerator();
    if( cEnum.isValid() )
    {
        QComboBox* pRetWidget = new QComboBox;
        for( int i = 0; i < cEnum.keyCount(); ++i )
        {
            int iVal = cEnum.value( i );
            QString strKey = cEnum.key( i );  // Translate here?
            pRetWidget->addItem( strKey, iVal );
        }
    } 

    ...
    return pRetWidget;
}

设置对话框中的组合框显示“Config_Blue”、“Config_Green”等。我希望它只用当前语言显示“Blue”、“Green”等。

对于其余的代码,我们使用 Qt 的翻译系统和 linguist 实用程序,效果非常好。我希望我也可以为 enum 启用这种类型的翻译,而无需手动将字符串文字和 tr() 添加到代码中。基本上,翻译器需要的所有信息都已经存在于代码中,我只需要linguist 就能够将这些枚举值识别为可翻译的。然后我可以在组合框被填充时调用tr()

我认为我需要的是某种方式让lupdate 获取枚举字符串进行翻译,或者通过发出一些 QT_TR_NOOP() 代码当且仅当文件正在由 lupdate 处理时,或者通过修改lupdate/moc 自己的行为。

我在想也许宏会起作用,但可能不可能。也许需要修改一些 Qt 代码?

【问题讨论】:

  • 我最初想写一个回复,但我自己读到了:kalebpederson.com/index.php/2010/07/…
  • 这似乎只是描述了如何使用 QMetaEnum 将键值作为字符串获取。我相信这就是我已经在做的事情。我想我真正需要的是让 lupdate 拾取这些枚举字符串,以便可以翻译它们。也许我会修改我的问题以使其更清楚。

标签: c++ qt enums translation


【解决方案1】:

枚举标识符一开始不应该是用户可见的。这些标识符应该对开发人员有意义,而不是对用户有意义。将它们直接暴露给用户增加了代码内部设计和用户可见行为之间的强耦合。最好避免这种情况。

您需要在枚举值和用户可见字符串之间进行映射。地图中的值应进行翻译,并且地图应在重新翻译时重新填充。例如:

class Object : public QObject
{
    Q_OBJECT
    Q_ENUMS(Configuration);
    Q_PROPERTY(Configuration READ Configuration WRITE SetConfiguration);

    enum Configuration {
        Config_Blue, Config_Green, Config_Invisible, Config_Backwards
    };
public:
    static QString toString(Configuration c) {
      switch (c) {
      case Config_Blue: return tr("Blue", "Configuration");
      case Config_Green: return tr("Green", "Configuration");
      case Config_Invisible: return tr("Invisible", "Configuration");
      case Config_Backwards: return tr("Backwards", "Configuration");
      }
    }
};

您现在可以翻译配置值。

【讨论】:

  • 如果我有700个各种枚举形式的选项,我应该为它们都写这种类型的开关
  • 是的,您应该这样做,因为所有这些都是面向用户的字符串。 C++ 标识符对用户来说并不是真正有意义的东西。没有办法正确地标点它们等等。由于依赖于用户可见的标识符,您的设计几乎搞砸了。你必须解决你发现自己陷入的烂摊子。也许所有这一切都会让你意识到你让自己做了多少工作。你有 700 个可翻译的字符串。你确定你的配置系统是不是有点过火了?
  • 我实际上没有 700 个选项,我选择了一个数字。如何纠正我搞砸的这个设计?
  • 通过做我在答案中显示的而不是你在问题中所做的:)
【解决方案2】:

我在定义枚举的类中使用了一个专用函数。有帮助吗? (Qt5.13)。

我把它叫做 MyClass::toTrString(myEnumVal);

class MyClass : public QObject
{
    Q_OBJECT
public:
    explicit MyClass(QObject *parent = nullptr);
    enum MyEnum {
            myKey1,
            myKey2,
            ...
    };
    Q_ENUM(MyEnum)
    static QString toTrString(MyEnum t) {
        return tr(qPrintable(QVariant::fromValue(t).toString()));
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-25
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 2014-08-20
    • 2010-09-30
    • 2014-09-27
    相关资源
    最近更新 更多