Merge PR #138: Rework translation mechanism

This commit is contained in:
Jenkins 2019-04-12 13:42:30 +02:00
commit 6ac1d43739
38 changed files with 1729 additions and 1035 deletions

View File

@ -46,7 +46,7 @@ QJsonObject CloudNotifications::metaData() const
{ {
QVariantMap pluginMetaData; QVariantMap pluginMetaData;
pluginMetaData.insert("id", "ccc6dbc8-e352-48a1-8e87-3c89a4669fc2"); pluginMetaData.insert("id", "ccc6dbc8-e352-48a1-8e87-3c89a4669fc2");
pluginMetaData.insert("name", "cloudNotifications"); pluginMetaData.insert("name", "CloudNotifications");
pluginMetaData.insert("displayName", tr("Cloud Notifications")); pluginMetaData.insert("displayName", tr("Cloud Notifications"));
QVariantList interfaces; QVariantList interfaces;
@ -131,6 +131,10 @@ QJsonObject CloudNotifications::metaData() const
QVariantList vendors; QVariantList vendors;
vendors.append(guhVendor); vendors.append(guhVendor);
pluginMetaData.insert("vendors", vendors); pluginMetaData.insert("vendors", vendors);
// Mark this plugin as built-in
pluginMetaData.insert("builtIn", true);
return QJsonObject::fromVariantMap(pluginMetaData); return QJsonObject::fromVariantMap(pluginMetaData);
} }

View File

@ -100,7 +100,7 @@ JsonReply *ActionHandler::GetActionType(const QVariantMap &params) const
foreach (const ActionType &actionType, deviceClass.actionTypes()) { foreach (const ActionType &actionType, deviceClass.actionTypes()) {
if (actionType.id() == actionTypeId) { if (actionType.id() == actionTypeId) {
QVariantMap data = statusToReply(DeviceManager::DeviceErrorNoError); QVariantMap data = statusToReply(DeviceManager::DeviceErrorNoError);
data.insert("actionType", JsonTypes::packActionType(actionType)); data.insert("actionType", JsonTypes::packActionType(actionType, deviceClass.pluginId(), params.value("locale").toLocale()));
return createReply(data); return createReply(data);
} }
} }

View File

@ -75,7 +75,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
setReturns("GetTimeZones", returns); setReturns("GetTimeZones", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("GetAvailableLanguages", "Returns a list of locale codes available for the server. i.e. en_US, de_AT"); setDescription("GetAvailableLanguages", "DEPRECATED - Use the locale property in the Handshake message instead - Returns a list of locale codes available for the server. i.e. en_US, de_AT");
setParams("GetAvailableLanguages", params); setParams("GetAvailableLanguages", params);
returns.insert("languages", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("languages", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String));
setReturns("GetAvailableLanguages", returns); setReturns("GetAvailableLanguages", returns);
@ -122,7 +122,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
setReturns("SetTimeZone", returns); setReturns("SetTimeZone", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("SetLanguage", "Sets the server language to the given language. See also: \"GetAvailableLanguages\""); setDescription("SetLanguage", "DEPRECATED - Use the locale property in the Handshake message instead - Sets the server language to the given language. See also: \"GetAvailableLanguages\"");
params.insert("language", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("language", JsonTypes::basicTypeToString(JsonTypes::String));
setParams("SetLanguage", params); setParams("SetLanguage", params);
returns.insert("configurationError", JsonTypes::configurationErrorRef()); returns.insert("configurationError", JsonTypes::configurationErrorRef());
@ -295,7 +295,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::timeZoneChanged, this, &ConfigurationHandler::onBasicConfigurationChanged); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::timeZoneChanged, this, &ConfigurationHandler::onBasicConfigurationChanged);
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::localeChanged, this, &ConfigurationHandler::onBasicConfigurationChanged); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::localeChanged, this, &ConfigurationHandler::onBasicConfigurationChanged);
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::debugServerEnabledChanged, this, &ConfigurationHandler::onBasicConfigurationChanged); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::debugServerEnabledChanged, this, &ConfigurationHandler::onBasicConfigurationChanged);
connect(NymeaCore::instance()->deviceManager(), &DeviceManager::languageUpdated, this, &ConfigurationHandler::onLanguageChanged); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::localeChanged, this, &ConfigurationHandler::onLanguageChanged);
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::tcpServerConfigurationChanged, this, &ConfigurationHandler::onTcpServerConfigurationChanged); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::tcpServerConfigurationChanged, this, &ConfigurationHandler::onTcpServerConfigurationChanged);
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::tcpServerConfigurationRemoved, this, &ConfigurationHandler::onTcpServerConfigurationRemoved); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::tcpServerConfigurationRemoved, this, &ConfigurationHandler::onTcpServerConfigurationRemoved);
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::webServerConfigurationChanged, this, &ConfigurationHandler::onWebServerConfigurationChanged); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::webServerConfigurationChanged, this, &ConfigurationHandler::onWebServerConfigurationChanged);

View File

@ -60,6 +60,7 @@
#include "types/deviceclass.h" #include "types/deviceclass.h"
#include "plugin/device.h" #include "plugin/device.h"
#include "plugin/deviceplugin.h" #include "plugin/deviceplugin.h"
#include "translator.h"
#include <QDebug> #include <QDebug>
@ -319,14 +320,14 @@ JsonReply* DeviceHandler::GetSupportedVendors(const QVariantMap &params) const
Q_UNUSED(params) Q_UNUSED(params)
QVariantMap returns; QVariantMap returns;
returns.insert("vendors", JsonTypes::packSupportedVendors()); returns.insert("vendors", JsonTypes::packSupportedVendors(params.value("locale").toLocale()));
return createReply(returns); return createReply(returns);
} }
JsonReply* DeviceHandler::GetSupportedDevices(const QVariantMap &params) const JsonReply* DeviceHandler::GetSupportedDevices(const QVariantMap &params) const
{ {
QVariantMap returns; QVariantMap returns;
returns.insert("deviceClasses", JsonTypes::packSupportedDevices(VendorId(params.value("vendorId").toString()))); returns.insert("deviceClasses", JsonTypes::packSupportedDevices(VendorId(params.value("vendorId").toString()), params.value("locale").toLocale()));
return createReply(returns); return createReply(returns);
} }
@ -354,7 +355,7 @@ JsonReply* DeviceHandler::GetPlugins(const QVariantMap &params) const
Q_UNUSED(params) Q_UNUSED(params)
QVariantMap returns; QVariantMap returns;
returns.insert("plugins", JsonTypes::packPlugins()); returns.insert("plugins", JsonTypes::packPlugins(params.value("locale").toLocale()));
return createReply(returns); return createReply(returns);
} }
@ -437,7 +438,7 @@ JsonReply *DeviceHandler::PairDevice(const QVariantMap &params)
QVariantMap returns; QVariantMap returns;
returns.insert("deviceError", JsonTypes::deviceErrorToString(status)); returns.insert("deviceError", JsonTypes::deviceErrorToString(status));
if (status == DeviceManager::DeviceErrorNoError) { if (status == DeviceManager::DeviceErrorNoError) {
returns.insert("displayMessage", deviceClass.pairingInfo()); returns.insert("displayMessage", NymeaCore::instance()->deviceManager()->translator()->translate(deviceClass.pluginId(), deviceClass.pairingInfo(), params.value("locale").toLocale()));
returns.insert("pairingTransactionId", pairingTransactionId.toString()); returns.insert("pairingTransactionId", pairingTransactionId.toString());
returns.insert("setupMethod", JsonTypes::setupMethod().at(deviceClass.setupMethod())); returns.insert("setupMethod", JsonTypes::setupMethod().at(deviceClass.setupMethod()));
} }
@ -565,7 +566,7 @@ JsonReply* DeviceHandler::GetEventTypes(const QVariantMap &params) const
QVariantList eventList; QVariantList eventList;
DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString())); DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString()));
foreach (const EventType &eventType, deviceClass.eventTypes()) { foreach (const EventType &eventType, deviceClass.eventTypes()) {
eventList.append(JsonTypes::packEventType(eventType)); eventList.append(JsonTypes::packEventType(eventType, deviceClass.pluginId(), params.value("locale").toLocale()));
} }
returns.insert("eventTypes", eventList); returns.insert("eventTypes", eventList);
return createReply(returns); return createReply(returns);
@ -578,7 +579,7 @@ JsonReply* DeviceHandler::GetActionTypes(const QVariantMap &params) const
QVariantList actionList; QVariantList actionList;
DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString())); DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString()));
foreach (const ActionType &actionType, deviceClass.actionTypes()) { foreach (const ActionType &actionType, deviceClass.actionTypes()) {
actionList.append(JsonTypes::packActionType(actionType)); actionList.append(JsonTypes::packActionType(actionType, deviceClass.pluginId(), params.value("locale").toLocale()));
} }
returns.insert("actionTypes", actionList); returns.insert("actionTypes", actionList);
return createReply(returns); return createReply(returns);
@ -591,7 +592,7 @@ JsonReply* DeviceHandler::GetStateTypes(const QVariantMap &params) const
QVariantList stateList; QVariantList stateList;
DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString())); DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString()));
foreach (const StateType &stateType, deviceClass.stateTypes()) { foreach (const StateType &stateType, deviceClass.stateTypes()) {
stateList.append(JsonTypes::packStateType(stateType)); stateList.append(JsonTypes::packStateType(stateType, deviceClass.pluginId(), NymeaCore::instance()->configuration()->locale()));
} }
returns.insert("stateTypes", stateList); returns.insert("stateTypes", stateList);
return createReply(returns); return createReply(returns);

View File

@ -88,7 +88,7 @@ JsonReply* EventHandler::GetEventType(const QVariantMap &params) const
foreach (const EventType &eventType, deviceClass.eventTypes()) { foreach (const EventType &eventType, deviceClass.eventTypes()) {
if (eventType.id() == eventTypeId) { if (eventType.id() == eventTypeId) {
QVariantMap data = statusToReply(DeviceManager::DeviceErrorNoError); QVariantMap data = statusToReply(DeviceManager::DeviceErrorNoError);
data.insert("eventType", JsonTypes::packEventType(eventType)); data.insert("eventType", JsonTypes::packEventType(eventType, deviceClass.pluginId(), params.value("locale").toLocale()));
return createReply(data); return createReply(data);
} }
} }

View File

@ -75,7 +75,16 @@ JsonRPCServer::JsonRPCServer(const QSslConfiguration &sslConfiguration, QObject
QVariantMap params; QVariantMap params;
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("Hello", "Upon first connection, nymea will automatically send a welcome message containing information about the setup. If this message is lost for whatever reason (connections with multiple hops might drop this if nymea sends it too early), the exact same message can be retrieved multiple times by calling this Hello method. Note that the contents might change if the system changed its state in the meantime, e.g. initialSetupRequired might turn false if the initial setup has been performed in the meantime."); setDescription("Hello", "Initiates a connection. Use this method to perform an initial handshake of the "
"connection. Optionally, a parameter \"locale\" is can be passed to set up the used "
"locale for this connection. Strings such as DeviceClass displayNames etc will be "
"localized to this locale. If this parameter is omitted, the default system locale "
"(depending on the configuration) is used. The reply of this method contains information "
"about this core instance such as version information, uuid and its name. The locale value"
"indicates the locale used for this connection. Note: This method can be called multiple "
"times. The locale used in the last call for this connection will be used. Other values, "
"like initialSetupRequired might change if the setup has been performed in the meantime.");
params.insert("o:locale", JsonTypes::basicTypeToString(JsonTypes::String));
setParams("Hello", params); setParams("Hello", params);
returns.insert("id", JsonTypes::basicTypeToString(JsonTypes::Int)); returns.insert("id", JsonTypes::basicTypeToString(JsonTypes::Int));
returns.insert("server", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("server", JsonTypes::basicTypeToString(JsonTypes::String));
@ -83,6 +92,7 @@ JsonRPCServer::JsonRPCServer(const QSslConfiguration &sslConfiguration, QObject
returns.insert("version", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("version", JsonTypes::basicTypeToString(JsonTypes::String));
returns.insert("uuid", JsonTypes::basicTypeToString(JsonTypes::Uuid)); returns.insert("uuid", JsonTypes::basicTypeToString(JsonTypes::Uuid));
returns.insert("language", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("language", JsonTypes::basicTypeToString(JsonTypes::String));
returns.insert("locale", JsonTypes::basicTypeToString(JsonTypes::String));
returns.insert("protocol version", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("protocol version", JsonTypes::basicTypeToString(JsonTypes::String));
returns.insert("initialSetupRequired", JsonTypes::basicTypeToString(JsonTypes::Bool)); returns.insert("initialSetupRequired", JsonTypes::basicTypeToString(JsonTypes::Bool));
returns.insert("authenticationRequired", JsonTypes::basicTypeToString(JsonTypes::Bool)); returns.insert("authenticationRequired", JsonTypes::basicTypeToString(JsonTypes::Bool));
@ -225,11 +235,20 @@ QString JsonRPCServer::name() const
return QStringLiteral("JSONRPC"); return QStringLiteral("JSONRPC");
} }
JsonReply *JsonRPCServer::Hello(const QVariantMap &params) const JsonReply *JsonRPCServer::Hello(const QVariantMap &params)
{ {
Q_UNUSED(params); Q_UNUSED(params);
TransportInterface *interface = reinterpret_cast<TransportInterface*>(property("transportInterface").toLongLong()); TransportInterface *interface = reinterpret_cast<TransportInterface*>(property("transportInterface").toLongLong());
return createReply(createWelcomeMessage(interface));
qCDebug(dcJsonRpc()) << params;
QUuid clientId = this->property("clientId").toUuid();
if (params.contains("locale")) {
m_clientLocales.insert(clientId, QLocale(params.value("locale").toString()));
}
qCDebug(dcJsonRpc()) << "Client" << clientId << "initiated handshake." << m_clientLocales.value(clientId);
return createReply(createWelcomeMessage(interface, clientId));
} }
JsonReply* JsonRPCServer::Introspect(const QVariantMap &params) const JsonReply* JsonRPCServer::Introspect(const QVariantMap &params) const
@ -465,7 +484,7 @@ void JsonRPCServer::sendUnauthorizedResponse(TransportInterface *interface, cons
interface->sendData(clientId, data); interface->sendData(clientId, data);
} }
QVariantMap JsonRPCServer::createWelcomeMessage(TransportInterface *interface) const QVariantMap JsonRPCServer::createWelcomeMessage(TransportInterface *interface, const QUuid &clientId) const
{ {
QVariantMap handshake; QVariantMap handshake;
handshake.insert("id", 0); handshake.insert("id", 0);
@ -473,7 +492,9 @@ QVariantMap JsonRPCServer::createWelcomeMessage(TransportInterface *interface) c
handshake.insert("name", NymeaCore::instance()->configuration()->serverName()); handshake.insert("name", NymeaCore::instance()->configuration()->serverName());
handshake.insert("version", NYMEA_VERSION_STRING); handshake.insert("version", NYMEA_VERSION_STRING);
handshake.insert("uuid", NymeaCore::instance()->configuration()->serverUuid().toString()); handshake.insert("uuid", NymeaCore::instance()->configuration()->serverUuid().toString());
handshake.insert("language", NymeaCore::instance()->configuration()->locale().name()); // "language" is deprecated
handshake.insert("language", m_clientLocales.value(clientId).name());
handshake.insert("locale", m_clientLocales.value(clientId).name());
handshake.insert("protocol version", JSON_PROTOCOL_VERSION); handshake.insert("protocol version", JSON_PROTOCOL_VERSION);
handshake.insert("initialSetupRequired", (interface->configuration().authenticationEnabled ? NymeaCore::instance()->userManager()->initRequired() : false)); handshake.insert("initialSetupRequired", (interface->configuration().authenticationEnabled ? NymeaCore::instance()->userManager()->initRequired() : false));
handshake.insert("authenticationRequired", interface->configuration().authenticationEnabled); handshake.insert("authenticationRequired", interface->configuration().authenticationEnabled);
@ -601,6 +622,13 @@ void JsonRPCServer::processJsonPacket(TransportInterface *interface, const QUuid
qCDebug(dcJsonRpc()) << "Invoking method" << targetNamespace << method.toLatin1().data(); qCDebug(dcJsonRpc()) << "Invoking method" << targetNamespace << method.toLatin1().data();
if (targetNamespace != "JSONRPC" || method != "Hello") {
// Unless this is the Hello message, which allows setting the locale explicity, attach the locale
// for this connection
// If the client did request a locale in the Hello message, use that locale
params.insert("locale", m_clientLocales.value(clientId));
}
JsonReply *reply; JsonReply *reply;
QMetaObject::invokeMethod(handler, method.toLatin1().data(), Q_RETURN_ARG(JsonReply*, reply), Q_ARG(QVariantMap, params)); QMetaObject::invokeMethod(handler, method.toLatin1().data(), Q_RETURN_ARG(JsonReply*, reply), Q_ARG(QVariantMap, params));
if (reply->type() == JsonReply::TypeAsync) { if (reply->type() == JsonReply::TypeAsync) {
@ -736,7 +764,10 @@ void JsonRPCServer::clientConnected(const QUuid &clientId)
// If authentication is required, notifications are disabled by default. Clients must enable them with a valid token // If authentication is required, notifications are disabled by default. Clients must enable them with a valid token
m_clientNotifications.insert(clientId, !interface->configuration().authenticationEnabled); m_clientNotifications.insert(clientId, !interface->configuration().authenticationEnabled);
interface->sendData(clientId, QJsonDocument::fromVariant(createWelcomeMessage(interface)).toJson(QJsonDocument::Compact)); // Initialize the connection locale to the settings default
m_clientLocales.insert(clientId, NymeaCore::instance()->configuration()->locale());
interface->sendData(clientId, QJsonDocument::fromVariant(createWelcomeMessage(interface, clientId)).toJson(QJsonDocument::Compact));
} }
void JsonRPCServer::clientDisconnected(const QUuid &clientId) void JsonRPCServer::clientDisconnected(const QUuid &clientId)
@ -745,6 +776,7 @@ void JsonRPCServer::clientDisconnected(const QUuid &clientId)
m_clientTransports.remove(clientId); m_clientTransports.remove(clientId);
m_clientNotifications.remove(clientId); m_clientNotifications.remove(clientId);
m_clientBuffers.remove(clientId); m_clientBuffers.remove(clientId);
m_clientLocales.remove(clientId);
if (m_pushButtonTransactions.values().contains(clientId)) { if (m_pushButtonTransactions.values().contains(clientId)) {
NymeaCore::instance()->userManager()->cancelPushButtonAuth(m_pushButtonTransactions.key(clientId)); NymeaCore::instance()->userManager()->cancelPushButtonAuth(m_pushButtonTransactions.key(clientId));
} }

View File

@ -47,7 +47,7 @@ public:
// JsonHandler API implementation // JsonHandler API implementation
QString name() const; QString name() const;
Q_INVOKABLE JsonReply *Hello(const QVariantMap &params) const; Q_INVOKABLE JsonReply *Hello(const QVariantMap &params);
Q_INVOKABLE JsonReply *Introspect(const QVariantMap &params) const; Q_INVOKABLE JsonReply *Introspect(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *Version(const QVariantMap &params) const; Q_INVOKABLE JsonReply *Version(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *SetNotificationStatus(const QVariantMap &params); Q_INVOKABLE JsonReply *SetNotificationStatus(const QVariantMap &params);
@ -77,7 +77,7 @@ private:
void sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap &params = QVariantMap()); void sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap &params = QVariantMap());
void sendErrorResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QString &error); void sendErrorResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QString &error);
void sendUnauthorizedResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QString &error); void sendUnauthorizedResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QString &error);
QVariantMap createWelcomeMessage(TransportInterface *interface) const; QVariantMap createWelcomeMessage(TransportInterface *interface, const QUuid &clientId) const;
void processJsonPacket(TransportInterface *interface, const QUuid &clientId, const QByteArray &data); void processJsonPacket(TransportInterface *interface, const QUuid &clientId, const QByteArray &data);
@ -105,6 +105,7 @@ private:
QHash<QUuid, TransportInterface*> m_clientTransports; QHash<QUuid, TransportInterface*> m_clientTransports;
QHash<QUuid, QByteArray> m_clientBuffers; QHash<QUuid, QByteArray> m_clientBuffers;
QHash<QUuid, bool> m_clientNotifications; QHash<QUuid, bool> m_clientNotifications;
QHash<QUuid, QLocale> m_clientLocales;
QHash<int, QUuid> m_pushButtonTransactions; QHash<int, QUuid> m_pushButtonTransactions;
QHash<QString, JsonReply*> m_pairingRequests; QHash<QString, JsonReply*> m_pairingRequests;

View File

@ -56,6 +56,8 @@
#include "ruleengine.h" #include "ruleengine.h"
#include "loggingcategories.h" #include "loggingcategories.h"
#include "logging/logvaluetool.h" #include "logging/logvaluetool.h"
#include "translator.h"
#include "plugin/deviceplugin.h"
#include <QStringList> #include <QStringList>
#include <QJsonDocument> #include <QJsonDocument>
@ -498,12 +500,12 @@ QVariantMap JsonTypes::allTypes()
} }
/*! Returns a variant map of the given \a eventType. */ /*! Returns a variant map of the given \a eventType. */
QVariantMap JsonTypes::packEventType(const EventType &eventType) QVariantMap JsonTypes::packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale)
{ {
QVariantMap variant; QVariantMap variant;
variant.insert("id", eventType.id().toString()); variant.insert("id", eventType.id().toString());
variant.insert("name", eventType.name()); variant.insert("name", eventType.name());
variant.insert("displayName", eventType.displayName()); variant.insert("displayName", NymeaCore::instance()->deviceManager()->translator()->translate(pluginId, eventType.displayName(), locale));
variant.insert("index", eventType.index()); variant.insert("index", eventType.index());
if (!eventType.ruleRelevant()) if (!eventType.ruleRelevant())
variant.insert("ruleRelevant", false); variant.insert("ruleRelevant", false);
@ -513,7 +515,7 @@ QVariantMap JsonTypes::packEventType(const EventType &eventType)
QVariantList paramTypes; QVariantList paramTypes;
foreach (const ParamType &paramType, eventType.paramTypes()) foreach (const ParamType &paramType, eventType.paramTypes())
paramTypes.append(packParamType(paramType)); paramTypes.append(packParamType(paramType, pluginId, locale));
variant.insert("paramTypes", paramTypes); variant.insert("paramTypes", paramTypes);
return variant; return variant;
@ -553,16 +555,16 @@ QVariantMap JsonTypes::packEventDescriptor(const EventDescriptor &eventDescripto
} }
/*! Returns a variant map of the given \a actionType. */ /*! Returns a variant map of the given \a actionType. */
QVariantMap JsonTypes::packActionType(const ActionType &actionType) QVariantMap JsonTypes::packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale)
{ {
QVariantMap variantMap; QVariantMap variantMap;
variantMap.insert("id", actionType.id().toString()); variantMap.insert("id", actionType.id().toString());
variantMap.insert("name", actionType.name()); variantMap.insert("name", actionType.name());
variantMap.insert("displayName", actionType.displayName()); variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translator()->translate(pluginId, actionType.displayName(), locale));
variantMap.insert("index", actionType.index()); variantMap.insert("index", actionType.index());
QVariantList paramTypes; QVariantList paramTypes;
foreach (const ParamType &paramType, actionType.paramTypes()) foreach (const ParamType &paramType, actionType.paramTypes())
paramTypes.append(packParamType(paramType)); paramTypes.append(packParamType(paramType, pluginId, locale));
variantMap.insert("paramTypes", paramTypes); variantMap.insert("paramTypes", paramTypes);
return variantMap; return variantMap;
@ -630,12 +632,12 @@ QVariantMap JsonTypes::packState(const State &state)
} }
/*! Returns a variant map of the given \a stateType. */ /*! Returns a variant map of the given \a stateType. */
QVariantMap JsonTypes::packStateType(const StateType &stateType) QVariantMap JsonTypes::packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale)
{ {
QVariantMap variantMap; QVariantMap variantMap;
variantMap.insert("id", stateType.id().toString()); variantMap.insert("id", stateType.id().toString());
variantMap.insert("name", stateType.name()); variantMap.insert("name", stateType.name());
variantMap.insert("displayName", stateType.displayName()); variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translator()->translate(pluginId, stateType.displayName(), locale));
variantMap.insert("index", stateType.index()); variantMap.insert("index", stateType.index());
variantMap.insert("type", basicTypeToString(stateType.type())); variantMap.insert("type", basicTypeToString(stateType.type()));
variantMap.insert("defaultValue", stateType.defaultValue()); variantMap.insert("defaultValue", stateType.defaultValue());
@ -721,12 +723,12 @@ QVariantMap JsonTypes::packParamDescriptor(const ParamDescriptor &paramDescripto
} }
/*! Returns a variant map of the given \a paramType. */ /*! Returns a variant map of the given \a paramType. */
QVariantMap JsonTypes::packParamType(const ParamType &paramType) QVariantMap JsonTypes::packParamType(const ParamType &paramType, const PluginId &pluginId, const QLocale &locale)
{ {
QVariantMap variantMap; QVariantMap variantMap;
variantMap.insert("id", paramType.id().toString()); variantMap.insert("id", paramType.id().toString());
variantMap.insert("name", paramType.name()); variantMap.insert("name", paramType.name());
variantMap.insert("displayName", paramType.displayName()); variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translator()->translate(pluginId, paramType.displayName(), locale));
variantMap.insert("type", basicTypeToString(paramType.type())); variantMap.insert("type", basicTypeToString(paramType.type()));
variantMap.insert("index", paramType.index()); variantMap.insert("index", paramType.index());
@ -756,22 +758,28 @@ QVariantMap JsonTypes::packParamType(const ParamType &paramType)
} }
/*! Returns a variant map of the given \a vendor. */ /*! Returns a variant map of the given \a vendor. */
QVariantMap JsonTypes::packVendor(const Vendor &vendor) QVariantMap JsonTypes::packVendor(const Vendor &vendor, const QLocale &locale)
{ {
DevicePlugin *plugin = nullptr;
foreach (DevicePlugin *p, NymeaCore::instance()->deviceManager()->plugins()) {
if (p->supportedVendors().contains(vendor)) {
plugin = p;
}
}
QVariantMap variantMap; QVariantMap variantMap;
variantMap.insert("id", vendor.id().toString()); variantMap.insert("id", vendor.id().toString());
variantMap.insert("name", vendor.name()); variantMap.insert("name", vendor.name());
variantMap.insert("displayName", vendor.displayName()); variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translator()->translate(plugin->pluginId(), vendor.displayName(), locale));
return variantMap; return variantMap;
} }
/*! Returns a variant map of the given \a deviceClass. */ /*! Returns a variant map of the given \a deviceClass. */
QVariantMap JsonTypes::packDeviceClass(const DeviceClass &deviceClass) QVariantMap JsonTypes::packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale)
{ {
QVariantMap variant; QVariantMap variant;
variant.insert("id", deviceClass.id().toString()); variant.insert("id", deviceClass.id().toString());
variant.insert("name", deviceClass.name()); variant.insert("name", deviceClass.name());
variant.insert("displayName", deviceClass.displayName()); variant.insert("displayName", NymeaCore::instance()->deviceManager()->translator()->translate(deviceClass.pluginId(), deviceClass.displayName(), locale));
variant.insert("vendorId", deviceClass.vendorId().toString()); variant.insert("vendorId", deviceClass.vendorId().toString());
variant.insert("pluginId", deviceClass.pluginId().toString()); variant.insert("pluginId", deviceClass.pluginId().toString());
variant.insert("deviceIcon", s_deviceIcon.at(deviceClass.deviceIcon())); variant.insert("deviceIcon", s_deviceIcon.at(deviceClass.deviceIcon()));
@ -783,23 +791,23 @@ QVariantMap JsonTypes::packDeviceClass(const DeviceClass &deviceClass)
QVariantList stateTypes; QVariantList stateTypes;
foreach (const StateType &stateType, deviceClass.stateTypes()) foreach (const StateType &stateType, deviceClass.stateTypes())
stateTypes.append(packStateType(stateType)); stateTypes.append(packStateType(stateType, deviceClass.pluginId(), locale));
QVariantList eventTypes; QVariantList eventTypes;
foreach (const EventType &eventType, deviceClass.eventTypes()) foreach (const EventType &eventType, deviceClass.eventTypes())
eventTypes.append(packEventType(eventType)); eventTypes.append(packEventType(eventType, deviceClass.pluginId(), locale));
QVariantList actionTypes; QVariantList actionTypes;
foreach (const ActionType &actionType, deviceClass.actionTypes()) foreach (const ActionType &actionType, deviceClass.actionTypes())
actionTypes.append(packActionType(actionType)); actionTypes.append(packActionType(actionType, deviceClass.pluginId(), locale));
QVariantList paramTypes; QVariantList paramTypes;
foreach (const ParamType &paramType, deviceClass.paramTypes()) foreach (const ParamType &paramType, deviceClass.paramTypes())
paramTypes.append(packParamType(paramType)); paramTypes.append(packParamType(paramType, deviceClass.pluginId(), locale));
QVariantList discoveryParamTypes; QVariantList discoveryParamTypes;
foreach (const ParamType &paramType, deviceClass.discoveryParamTypes()) foreach (const ParamType &paramType, deviceClass.discoveryParamTypes())
discoveryParamTypes.append(packParamType(paramType)); discoveryParamTypes.append(packParamType(paramType, deviceClass.pluginId(), locale));
if (!deviceClass.criticalStateTypeId().isNull()) if (!deviceClass.criticalStateTypeId().isNull())
variant.insert("criticalStateTypeId", deviceClass.criticalStateTypeId().toString()); variant.insert("criticalStateTypeId", deviceClass.criticalStateTypeId().toString());
@ -822,16 +830,16 @@ QVariantMap JsonTypes::packDeviceClass(const DeviceClass &deviceClass)
} }
/*! Returns a variant map of the given \a plugin. */ /*! Returns a variant map of the given \a plugin. */
QVariantMap JsonTypes::packPlugin(DevicePlugin *plugin) QVariantMap JsonTypes::packPlugin(DevicePlugin *plugin, const QLocale &locale)
{ {
QVariantMap pluginMap; QVariantMap pluginMap;
pluginMap.insert("id", plugin->pluginId().toString()); pluginMap.insert("id", plugin->pluginId().toString());
pluginMap.insert("name", plugin->pluginName()); pluginMap.insert("name", plugin->pluginName());
pluginMap.insert("displayName", plugin->pluginDisplayName()); pluginMap.insert("displayName", NymeaCore::instance()->deviceManager()->translator()->translate(plugin->pluginId(), plugin->pluginDisplayName(), locale));
QVariantList params; QVariantList params;
foreach (const ParamType &param, plugin->configurationDescription()) foreach (const ParamType &param, plugin->configurationDescription())
params.append(packParamType(param)); params.append(packParamType(param, plugin->pluginId(), locale));
pluginMap.insert("paramTypes", params); pluginMap.insert("paramTypes", params);
return pluginMap; return pluginMap;
@ -1130,21 +1138,21 @@ QVariantMap JsonTypes::packWirelessNetworkDevice(WirelessNetworkDevice *networkD
} }
/*! Returns a variant list of the supported vendors. */ /*! Returns a variant list of the supported vendors. */
QVariantList JsonTypes::packSupportedVendors() QVariantList JsonTypes::packSupportedVendors(const QLocale &locale)
{ {
QVariantList supportedVendors; QVariantList supportedVendors;
foreach (const Vendor &vendor, NymeaCore::instance()->deviceManager()->supportedVendors()) foreach (const Vendor &vendor, NymeaCore::instance()->deviceManager()->supportedVendors())
supportedVendors.append(packVendor(vendor)); supportedVendors.append(packVendor(vendor, locale));
return supportedVendors; return supportedVendors;
} }
/*! Returns a variant list of the supported devices with the given \a vendorId. */ /*! Returns a variant list of the supported devices with the given \a vendorId. */
QVariantList JsonTypes::packSupportedDevices(const VendorId &vendorId) QVariantList JsonTypes::packSupportedDevices(const VendorId &vendorId, const QLocale &locale)
{ {
QVariantList supportedDeviceList; QVariantList supportedDeviceList;
foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices(vendorId)) foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices(vendorId))
supportedDeviceList.append(packDeviceClass(deviceClass)); supportedDeviceList.append(packDeviceClass(deviceClass, locale));
return supportedDeviceList; return supportedDeviceList;
} }
@ -1246,41 +1254,41 @@ QVariantList JsonTypes::packRuleDescriptions(const QList<Rule> &rules)
} }
/*! Returns a variant list of action types for the given \a deviceClass. */ /*! Returns a variant list of action types for the given \a deviceClass. */
QVariantList JsonTypes::packActionTypes(const DeviceClass &deviceClass) QVariantList JsonTypes::packActionTypes(const DeviceClass &deviceClass, const QLocale &locale)
{ {
QVariantList actionTypes; QVariantList actionTypes;
foreach (const ActionType &actionType, deviceClass.actionTypes()) foreach (const ActionType &actionType, deviceClass.actionTypes())
actionTypes.append(JsonTypes::packActionType(actionType)); actionTypes.append(JsonTypes::packActionType(actionType, deviceClass.pluginId(), locale));
return actionTypes; return actionTypes;
} }
/*! Returns a variant list of state types for the given \a deviceClass. */ /*! Returns a variant list of state types for the given \a deviceClass. */
QVariantList JsonTypes::packStateTypes(const DeviceClass &deviceClass) QVariantList JsonTypes::packStateTypes(const DeviceClass &deviceClass, const QLocale &locale)
{ {
QVariantList stateTypes; QVariantList stateTypes;
foreach (const StateType &stateType, deviceClass.stateTypes()) foreach (const StateType &stateType, deviceClass.stateTypes())
stateTypes.append(JsonTypes::packStateType(stateType)); stateTypes.append(JsonTypes::packStateType(stateType, deviceClass.pluginId(), locale));
return stateTypes; return stateTypes;
} }
/*! Returns a variant list of event types for the given \a deviceClass. */ /*! Returns a variant list of event types for the given \a deviceClass. */
QVariantList JsonTypes::packEventTypes(const DeviceClass &deviceClass) QVariantList JsonTypes::packEventTypes(const DeviceClass &deviceClass, const QLocale &locale)
{ {
QVariantList eventTypes; QVariantList eventTypes;
foreach (const EventType &eventType, deviceClass.eventTypes()) foreach (const EventType &eventType, deviceClass.eventTypes())
eventTypes.append(JsonTypes::packEventType(eventType)); eventTypes.append(JsonTypes::packEventType(eventType, deviceClass.pluginId(), locale));
return eventTypes; return eventTypes;
} }
/*! Returns a variant list containing all plugins. */ /*! Returns a variant list containing all plugins. */
QVariantList JsonTypes::packPlugins() QVariantList JsonTypes::packPlugins(const QLocale &locale)
{ {
QVariantList pluginsList; QVariantList pluginsList;
foreach (DevicePlugin *plugin, NymeaCore::instance()->deviceManager()->plugins()) { foreach (DevicePlugin *plugin, NymeaCore::instance()->deviceManager()->plugins()) {
QVariantMap pluginMap = packPlugin(plugin); QVariantMap pluginMap = packPlugin(plugin, locale);
pluginsList.append(pluginMap); pluginsList.append(pluginMap);
} }
return pluginsList; return pluginsList;

View File

@ -180,23 +180,23 @@ public:
DECLARE_OBJECT(mqttPolicy, "MqttPolicy") DECLARE_OBJECT(mqttPolicy, "MqttPolicy")
// pack types // pack types
static QVariantMap packEventType(const EventType &eventType); static QVariantMap packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale);
static QVariantMap packEvent(const Event &event); static QVariantMap packEvent(const Event &event);
static QVariantMap packEventDescriptor(const EventDescriptor &event); static QVariantMap packEventDescriptor(const EventDescriptor &event);
static QVariantMap packActionType(const ActionType &actionType); static QVariantMap packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale);
static QVariantMap packAction(const Action &action); static QVariantMap packAction(const Action &action);
static QVariantMap packRuleAction(const RuleAction &ruleAction); static QVariantMap packRuleAction(const RuleAction &ruleAction);
static QVariantMap packRuleActionParam(const RuleActionParam &ruleActionParam); static QVariantMap packRuleActionParam(const RuleActionParam &ruleActionParam);
static QVariantMap packState(const State &state); static QVariantMap packState(const State &state);
static QVariantMap packStateType(const StateType &stateType); static QVariantMap packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale);
static QVariantMap packStateDescriptor(const StateDescriptor &stateDescriptor); static QVariantMap packStateDescriptor(const StateDescriptor &stateDescriptor);
static QVariantMap packStateEvaluator(const StateEvaluator &stateEvaluator); static QVariantMap packStateEvaluator(const StateEvaluator &stateEvaluator);
static QVariantMap packParam(const Param &param); static QVariantMap packParam(const Param &param);
static QVariantMap packParamType(const ParamType &paramType); static QVariantMap packParamType(const ParamType &paramType, const PluginId &pluginId, const QLocale &locale);
static QVariantMap packParamDescriptor(const ParamDescriptor &paramDescriptor); static QVariantMap packParamDescriptor(const ParamDescriptor &paramDescriptor);
static QVariantMap packVendor(const Vendor &vendor); static QVariantMap packVendor(const Vendor &vendor, const QLocale &locale);
static QVariantMap packDeviceClass(const DeviceClass &deviceClass); static QVariantMap packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale);
static QVariantMap packPlugin(DevicePlugin *plugin); static QVariantMap packPlugin(DevicePlugin *pluginid, const QLocale &locale);
static QVariantMap packDevice(Device *device); static QVariantMap packDevice(Device *device);
static QVariantMap packDeviceDescriptor(const DeviceDescriptor &descriptor); static QVariantMap packDeviceDescriptor(const DeviceDescriptor &descriptor);
static QVariantMap packRule(const Rule &rule); static QVariantMap packRule(const Rule &rule);
@ -213,8 +213,8 @@ public:
static QVariantList packRules(const QList<Rule> rules); static QVariantList packRules(const QList<Rule> rules);
static QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods); static QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods);
static QVariantList packSupportedVendors(); static QVariantList packSupportedVendors(const QLocale &locale);
static QVariantList packSupportedDevices(const VendorId &vendorId); static QVariantList packSupportedDevices(const VendorId &vendorId, const QLocale &locale);
static QVariantList packConfiguredDevices(); static QVariantList packConfiguredDevices();
static QVariantList packDeviceStates(Device *device); static QVariantList packDeviceStates(Device *device);
static QVariantList packDeviceDescriptors(const QList<DeviceDescriptor> deviceDescriptors); static QVariantList packDeviceDescriptors(const QList<DeviceDescriptor> deviceDescriptors);
@ -227,10 +227,10 @@ public:
static QVariantList packRuleDescriptions(); static QVariantList packRuleDescriptions();
static QVariantList packRuleDescriptions(const QList<Rule> &rules); static QVariantList packRuleDescriptions(const QList<Rule> &rules);
static QVariantList packActionTypes(const DeviceClass &deviceClass); static QVariantList packActionTypes(const DeviceClass &deviceClass, const QLocale &locale);
static QVariantList packStateTypes(const DeviceClass &deviceClass); static QVariantList packStateTypes(const DeviceClass &deviceClass, const QLocale &locale);
static QVariantList packEventTypes(const DeviceClass &deviceClass); static QVariantList packEventTypes(const DeviceClass &deviceClass, const QLocale &locale);
static QVariantList packPlugins(); static QVariantList packPlugins(const QLocale &locale);
static QVariantMap packTokenInfo(const TokenInfo &tokenInfo); static QVariantMap packTokenInfo(const TokenInfo &tokenInfo);

View File

@ -68,7 +68,7 @@ JsonReply* StateHandler::GetStateType(const QVariantMap &params) const
foreach (const StateType &stateType, deviceClass.stateTypes()) { foreach (const StateType &stateType, deviceClass.stateTypes()) {
if (stateType.id() == stateTypeId) { if (stateType.id() == stateTypeId) {
QVariantMap data = statusToReply(DeviceManager::DeviceErrorNoError); QVariantMap data = statusToReply(DeviceManager::DeviceErrorNoError);
data.insert("stateType", JsonTypes::packStateType(stateType)); data.insert("stateType", JsonTypes::packStateType(stateType, deviceClass.pluginId(), params.value("locale").toLocale()));
return createReply(data); return createReply(data);
} }
} }

View File

@ -118,6 +118,7 @@
#include "cloud/cloudtransport.h" #include "cloud/cloudtransport.h"
#include <QDir> #include <QDir>
#include <QCoreApplication>
namespace nymeaserver { namespace nymeaserver {
@ -184,7 +185,6 @@ void NymeaCore::init() {
CloudTransport *cloudTransport = m_cloudManager->createTransportInterface(); CloudTransport *cloudTransport = m_cloudManager->createTransportInterface();
m_serverManager->jsonServer()->registerTransportInterface(cloudTransport, false); m_serverManager->jsonServer()->registerTransportInterface(cloudTransport, false);
connect(m_configuration, &NymeaConfiguration::localeChanged, this, &NymeaCore::onLocaleChanged);
connect(m_configuration, &NymeaConfiguration::serverNameChanged, m_serverManager, &ServerManager::setServerName); connect(m_configuration, &NymeaConfiguration::serverNameChanged, m_serverManager, &ServerManager::setServerName);
connect(m_deviceManager, &DeviceManager::pluginConfigChanged, this, &NymeaCore::pluginConfigChanged); connect(m_deviceManager, &DeviceManager::pluginConfigChanged, this, &NymeaCore::pluginConfigChanged);
@ -533,9 +533,20 @@ QStringList NymeaCore::getAvailableLanguages()
{ {
qCDebug(dcApplication()) << "Loading translations from" << NymeaSettings::translationsPath(); qCDebug(dcApplication()) << "Loading translations from" << NymeaSettings::translationsPath();
QDir translationDirectory(NymeaSettings::translationsPath()); QStringList searchPaths;
translationDirectory.setNameFilters(QStringList() << "*.qm"); searchPaths << QCoreApplication::applicationDirPath() + "/../translations";
QStringList translationFiles = translationDirectory.entryList(); searchPaths << NymeaSettings::translationsPath();
QStringList translationFiles;
foreach (const QString &path, searchPaths) {
QDir translationDirectory(path);
translationDirectory.setNameFilters(QStringList() << "*.qm");
translationFiles = translationDirectory.entryList();
qCDebug(dcTranslations()) << translationFiles.count() << "translations in" << path;
if (translationFiles.count() > 0) {
break;
}
}
QStringList availableLanguages; QStringList availableLanguages;
foreach (QString translationFile, translationFiles) { foreach (QString translationFile, translationFiles) {
@ -687,11 +698,6 @@ void NymeaCore::onDateTimeChanged(const QDateTime &dateTime)
executeRuleActions(actions); executeRuleActions(actions);
} }
void NymeaCore::onLocaleChanged()
{
m_deviceManager->setLocale(m_configuration->locale());
}
/*! Return the instance of the log engine */ /*! Return the instance of the log engine */
LogEngine* NymeaCore::logEngine() const LogEngine* NymeaCore::logEngine() const
{ {

View File

@ -136,7 +136,6 @@ private:
private slots: private slots:
void gotEvent(const Event &event); void gotEvent(const Event &event);
void onDateTimeChanged(const QDateTime &dateTime); void onDateTimeChanged(const QDateTime &dateTime);
void onLocaleChanged();
void actionExecutionFinished(const ActionId &id, DeviceManager::DeviceError status); void actionExecutionFinished(const ActionId &id, DeviceManager::DeviceError status);
void onDeviceDisappeared(const DeviceId &deviceId); void onDeviceDisappeared(const DeviceId &deviceId);
void deviceManagerLoaded(); void deviceManagerLoaded();

View File

@ -184,7 +184,7 @@ HttpReply *DeviceClassesResource::getDeviceClass()
qCDebug(dcRest) << "Get device class with id " << m_deviceClass.id(); qCDebug(dcRest) << "Get device class with id " << m_deviceClass.id();
HttpReply *reply = createSuccessReply(); HttpReply *reply = createSuccessReply();
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packDeviceClass(m_deviceClass)).toJson()); reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packDeviceClass(m_deviceClass, NymeaCore::instance()->configuration()->locale())).toJson());
return reply; return reply;
} }
@ -193,7 +193,7 @@ HttpReply *DeviceClassesResource::getActionTypes()
qCDebug(dcRest) << "Get action types for device class" << m_deviceClass.id(); qCDebug(dcRest) << "Get action types for device class" << m_deviceClass.id();
HttpReply *reply = createSuccessReply(); HttpReply *reply = createSuccessReply();
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packActionTypes(m_deviceClass)).toJson()); reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packActionTypes(m_deviceClass, NymeaCore::instance()->configuration()->locale())).toJson());
return reply; return reply;
} }
@ -205,7 +205,7 @@ HttpReply *DeviceClassesResource::getActionType(const ActionTypeId &actionTypeId
if (actionType.id() == actionTypeId) { if (actionType.id() == actionTypeId) {
HttpReply *reply = createSuccessReply(); HttpReply *reply = createSuccessReply();
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packActionType(actionType)).toJson()); reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packActionType(actionType, m_deviceClass.pluginId(), NymeaCore::instance()->configuration()->locale())).toJson());
return reply; return reply;
} }
} }
@ -217,7 +217,7 @@ HttpReply *DeviceClassesResource::getStateTypes()
qCDebug(dcRest) << "Get state types for device class" << m_deviceClass.id(); qCDebug(dcRest) << "Get state types for device class" << m_deviceClass.id();
HttpReply *reply = createSuccessReply(); HttpReply *reply = createSuccessReply();
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packStateTypes(m_deviceClass)).toJson()); reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packStateTypes(m_deviceClass, NymeaCore::instance()->configuration()->locale())).toJson());
return reply; return reply;
} }
@ -229,7 +229,7 @@ HttpReply *DeviceClassesResource::getStateType(const StateTypeId &stateTypeId)
if (stateType.id() == stateTypeId) { if (stateType.id() == stateTypeId) {
HttpReply *reply = createSuccessReply(); HttpReply *reply = createSuccessReply();
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packStateType(stateType)).toJson()); reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packStateType(stateType, m_deviceClass.pluginId(), NymeaCore::instance()->configuration()->locale())).toJson());
return reply; return reply;
} }
} }
@ -241,7 +241,7 @@ HttpReply *DeviceClassesResource::getEventTypes()
qCDebug(dcRest) << "Get event types for device class" << m_deviceClass.id(); qCDebug(dcRest) << "Get event types for device class" << m_deviceClass.id();
HttpReply *reply = createSuccessReply(); HttpReply *reply = createSuccessReply();
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packEventTypes(m_deviceClass)).toJson()); reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packEventTypes(m_deviceClass, NymeaCore::instance()->configuration()->locale())).toJson());
return reply; return reply;
} }
@ -253,7 +253,7 @@ HttpReply *DeviceClassesResource::getEventType(const EventTypeId &eventTypeId)
if (eventType.id() == eventTypeId) { if (eventType.id() == eventTypeId) {
HttpReply *reply = createSuccessReply(); HttpReply *reply = createSuccessReply();
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packEventType(eventType)).toJson()); reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packEventType(eventType, m_deviceClass.pluginId(), NymeaCore::instance()->configuration()->locale())).toJson());
return reply; return reply;
} }
} }
@ -307,7 +307,7 @@ HttpReply *DeviceClassesResource::getDeviceClasses(const VendorId &vendorId)
HttpReply *reply = createSuccessReply(); HttpReply *reply = createSuccessReply();
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packSupportedDevices(vendorId)).toJson()); reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packSupportedDevices(vendorId, NymeaCore::instance()->configuration()->locale())).toJson());
return reply; return reply;
} }

View File

@ -37,7 +37,7 @@ class DeviceClassesResource : public RestResource
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit DeviceClassesResource(QObject *parent = 0); explicit DeviceClassesResource(QObject *parent = nullptr);
QString name() const override; QString name() const override;

View File

@ -41,6 +41,7 @@
#include "servers/httprequest.h" #include "servers/httprequest.h"
#include "jsonrpc/jsontypes.h" #include "jsonrpc/jsontypes.h"
#include "nymeacore.h" #include "nymeacore.h"
#include "translator.h"
#include <QJsonDocument> #include <QJsonDocument>
@ -442,7 +443,7 @@ HttpReply *DevicesResource::pairDevice(const QByteArray &payload) const
return createDeviceErrorReply(HttpReply::BadRequest, status); return createDeviceErrorReply(HttpReply::BadRequest, status);
QVariantMap returns; QVariantMap returns;
returns.insert("displayMessage", deviceClass.pairingInfo()); returns.insert("displayMessage", NymeaCore::instance()->deviceManager()->translator()->translate(deviceClass.pluginId(), deviceClass.pairingInfo(), NymeaCore::instance()->configuration()->locale()));
returns.insert("pairingTransactionId", pairingTransactionId.toString()); returns.insert("pairingTransactionId", pairingTransactionId.toString());
returns.insert("setupMethod", JsonTypes::setupMethod().at(deviceClass.setupMethod())); returns.insert("setupMethod", JsonTypes::setupMethod().at(deviceClass.setupMethod()));
HttpReply *reply = createSuccessReply(); HttpReply *reply = createSuccessReply();

View File

@ -139,7 +139,7 @@ HttpReply *PluginsResource::getPlugins() const
qCDebug(dcRest) << "Get plugins"; qCDebug(dcRest) << "Get plugins";
HttpReply *reply = createSuccessReply(); HttpReply *reply = createSuccessReply();
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packPlugins()).toJson()); reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packPlugins(NymeaCore::instance()->configuration()->locale())).toJson());
return reply; return reply;
} }
@ -150,7 +150,7 @@ HttpReply *PluginsResource::getPlugin(const PluginId &pluginId) const
foreach (DevicePlugin *plugin, NymeaCore::instance()->deviceManager()->plugins()) { foreach (DevicePlugin *plugin, NymeaCore::instance()->deviceManager()->plugins()) {
if (plugin->pluginId() == pluginId) { if (plugin->pluginId() == pluginId) {
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packPlugin(plugin)).toJson()); reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packPlugin(plugin, NymeaCore::instance()->configuration()->locale())).toJson());
return reply; return reply;
} }
} }

View File

@ -111,7 +111,7 @@ HttpReply *VendorsResource::getVendors() const
QVariantList vendorsList; QVariantList vendorsList;
foreach (const Vendor &vendor, NymeaCore::instance()->deviceManager()->supportedVendors()) { foreach (const Vendor &vendor, NymeaCore::instance()->deviceManager()->supportedVendors()) {
vendorsList.append(JsonTypes::packVendor(vendor)); vendorsList.append(JsonTypes::packVendor(vendor, NymeaCore::instance()->configuration()->locale()));
} }
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(vendorsList).toJson()); reply->setPayload(QJsonDocument::fromVariant(vendorsList).toJson());
@ -125,7 +125,7 @@ HttpReply *VendorsResource::getVendor(const VendorId &vendorId) const
if (vendor.id() == vendorId) { if (vendor.id() == vendorId) {
HttpReply *reply = createSuccessReply(); HttpReply *reply = createSuccessReply();
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packVendor(vendor)).toJson()); reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packVendor(vendor, NymeaCore::instance()->configuration()->locale())).toJson());
return reply; return reply;
} }
} }

View File

@ -181,6 +181,7 @@
#include "typeutils.h" #include "typeutils.h"
#include "nymeasettings.h" #include "nymeasettings.h"
#include "unistd.h" #include "unistd.h"
#include "translator.h"
#include "plugintimer.h" #include "plugintimer.h"
@ -198,7 +199,8 @@
DeviceManager::DeviceManager(HardwareManager *hardwareManager, const QLocale &locale, QObject *parent) : DeviceManager::DeviceManager(HardwareManager *hardwareManager, const QLocale &locale, QObject *parent) :
QObject(parent), QObject(parent),
m_hardwareManager(hardwareManager), m_hardwareManager(hardwareManager),
m_locale(locale) m_locale(locale),
m_translator(new Translator(this))
{ {
qRegisterMetaType<DeviceClassId>(); qRegisterMetaType<DeviceClassId>();
qRegisterMetaType<DeviceDescriptor>(); qRegisterMetaType<DeviceDescriptor>();
@ -219,6 +221,8 @@ DeviceManager::DeviceManager(HardwareManager *hardwareManager, const QLocale &lo
/*! Destructor of the DeviceManager. Each loaded \l{DevicePlugin} will be deleted. */ /*! Destructor of the DeviceManager. Each loaded \l{DevicePlugin} will be deleted. */
DeviceManager::~DeviceManager() DeviceManager::~DeviceManager()
{ {
delete m_translator;
foreach (Device *device, m_configuredDevices) { foreach (Device *device, m_configuredDevices) {
storeDeviceStates(device); storeDeviceStates(device);
} }
@ -288,44 +292,6 @@ void DeviceManager::registerStaticPlugin(DevicePlugin *plugin, const QJsonObject
loadPlugin(plugin); loadPlugin(plugin);
} }
/*! Set the \a locale of all plugins and reload the translated strings. */
void DeviceManager::setLocale(const QLocale &locale)
{
qCDebug(dcDeviceManager()) << "Setting locale:" << locale;
m_locale = locale;
foreach (DevicePlugin *plugin, m_devicePlugins.values()) {
QCoreApplication::removeTranslator(plugin->translator());
plugin->setLocale(m_locale);
QCoreApplication::installTranslator(plugin->translator());
plugin->loadMetaData();
}
// Reload all plugin meta data
m_supportedVendors.clear();
m_supportedDevices.clear();
foreach (DevicePlugin *plugin, m_devicePlugins.values()) {
foreach (const Vendor &vendor, plugin->supportedVendors()) {
if (m_supportedVendors.contains(vendor.id()))
continue;
m_supportedVendors.insert(vendor.id(), vendor);
}
foreach (const DeviceClass &deviceClass, plugin->supportedDevices()) {
if (!m_supportedVendors.contains(deviceClass.vendorId())) {
qCWarning(dcDeviceManager) << "Vendor not found. Ignoring device. VendorId:" << deviceClass.vendorId() << "DeviceClass:" << deviceClass.name() << deviceClass.id();
continue;
}
m_supportedDevices.insert(deviceClass.id(), deviceClass);
}
}
emit languageUpdated();
}
/*! Returns the pointer to the \l{HardwareManager} of the system. /*! Returns the pointer to the \l{HardwareManager} of the system.
\sa HardwareManager \sa HardwareManager
@ -400,13 +366,15 @@ Interface DeviceManager::findInterface(const QString &name)
* Optionally filtered by \a vendorId. */ * Optionally filtered by \a vendorId. */
QList<DeviceClass> DeviceManager::supportedDevices(const VendorId &vendorId) const QList<DeviceClass> DeviceManager::supportedDevices(const VendorId &vendorId) const
{ {
QList<DeviceClass> ret;
if (vendorId.isNull()) { if (vendorId.isNull()) {
ret = m_supportedDevices.values(); return m_supportedDevices.values();
} else { }
foreach (const DeviceClassId &deviceClassId, m_vendorDeviceMap.value(vendorId)) { QList<DeviceClass> ret;
ret.append(m_supportedDevices.value(deviceClassId)); foreach (const DeviceClass &deviceClass, m_supportedDevices) {
if (!vendorId.isNull() && deviceClass.vendorId() != vendorId) {
continue;
} }
ret.append(deviceClass);
} }
return ret; return ret;
} }
@ -928,13 +896,13 @@ DeviceManager::DeviceError DeviceManager::verifyParam(const ParamType &paramType
return DeviceErrorInvalidParameter; return DeviceErrorInvalidParameter;
} }
if (!param.value().canConvert(paramType.type())) { if (!param.value().canConvert(static_cast<int>(paramType.type()))) {
qCWarning(dcDeviceManager) << "Wrong parameter type for param" << param.paramTypeId().toString() << " Got:" << param.value() << " Expected:" << QVariant::typeToName(paramType.type()); qCWarning(dcDeviceManager) << "Wrong parameter type for param" << param.paramTypeId().toString() << " Got:" << param.value() << " Expected:" << QVariant::typeToName(static_cast<int>(paramType.type()));
return DeviceErrorInvalidParameter; return DeviceErrorInvalidParameter;
} }
if (!param.value().convert(paramType.type())) { if (!param.value().convert(static_cast<int>(paramType.type()))) {
qCWarning(dcDeviceManager) << "Could not convert value of param" << param.paramTypeId().toString() << " to:" << QVariant::typeToName(paramType.type()) << " Got:" << param.value(); qCWarning(dcDeviceManager) << "Could not convert value of param" << param.paramTypeId().toString() << " to:" << QVariant::typeToName(static_cast<int>(paramType.type())) << " Got:" << param.value();
return DeviceErrorInvalidParameter; return DeviceErrorInvalidParameter;
} }
@ -993,6 +961,13 @@ DeviceManager::DeviceError DeviceManager::verifyParam(const ParamType &paramType
return DeviceErrorNoError; return DeviceErrorNoError;
} }
/*! Returns the translator. The translator can be used to translate plugin data.
* */
Translator *DeviceManager::translator() const
{
return m_translator;
}
/*! Execute the given \l{Action}. /*! Execute the given \l{Action}.
* This will find the \l{Device} \a action refers to the \l{Action}{deviceId()} and * This will find the \l{Device} \a action refers to the \l{Action}{deviceId()} and
* its \l{DevicePlugin}. Then will dispatch the execution to the \l{DevicePlugin}.*/ * its \l{DevicePlugin}. Then will dispatch the execution to the \l{DevicePlugin}.*/
@ -1079,9 +1054,6 @@ void DeviceManager::loadPlugins()
void DeviceManager::loadPlugin(DevicePlugin *pluginIface) void DeviceManager::loadPlugin(DevicePlugin *pluginIface)
{ {
pluginIface->setLocale(m_locale);
qApp->installTranslator(pluginIface->translator());
pluginIface->initPlugin(this); pluginIface->initPlugin(this);
qCDebug(dcDeviceManager) << "**** Loaded plugin" << pluginIface->pluginName(); qCDebug(dcDeviceManager) << "**** Loaded plugin" << pluginIface->pluginName();
@ -1141,6 +1113,7 @@ void DeviceManager::loadPlugin(DevicePlugin *pluginIface)
connect(pluginIface, &DevicePlugin::pairingFinished, this, &DeviceManager::slotPairingFinished); connect(pluginIface, &DevicePlugin::pairingFinished, this, &DeviceManager::slotPairingFinished);
connect(pluginIface, &DevicePlugin::autoDevicesAppeared, this, &DeviceManager::onAutoDevicesAppeared); connect(pluginIface, &DevicePlugin::autoDevicesAppeared, this, &DeviceManager::onAutoDevicesAppeared);
connect(pluginIface, &DevicePlugin::autoDeviceDisappeared, this, &DeviceManager::onAutoDeviceDisappeared); connect(pluginIface, &DevicePlugin::autoDeviceDisappeared, this, &DeviceManager::onAutoDeviceDisappeared);
} }
void DeviceManager::loadConfiguredDevices() void DeviceManager::loadConfiguredDevices()

View File

@ -39,6 +39,7 @@
#include <QTimer> #include <QTimer>
#include <QLocale> #include <QLocale>
#include <QPluginLoader> #include <QPluginLoader>
#include <QTranslator>
#include "hardwaremanager.h" #include "hardwaremanager.h"
@ -46,6 +47,7 @@ class Device;
class DevicePlugin; class DevicePlugin;
class DevicePairingInfo; class DevicePairingInfo;
class HardwareManager; class HardwareManager;
class Translator;
class LIBNYMEA_EXPORT DeviceManager : public QObject class LIBNYMEA_EXPORT DeviceManager : public QObject
{ {
@ -96,8 +98,6 @@ public:
static QList<QJsonObject> pluginsMetadata(); static QList<QJsonObject> pluginsMetadata();
void registerStaticPlugin(DevicePlugin* plugin, const QJsonObject &metaData); void registerStaticPlugin(DevicePlugin* plugin, const QJsonObject &metaData);
void setLocale(const QLocale &locale);
HardwareManager *hardwareManager() const; HardwareManager *hardwareManager() const;
QList<DevicePlugin*> plugins() const; QList<DevicePlugin*> plugins() const;
@ -136,9 +136,9 @@ public:
DeviceError verifyParam(const QList<ParamType> paramTypes, const Param &param); DeviceError verifyParam(const QList<ParamType> paramTypes, const Param &param);
DeviceError verifyParam(const ParamType &paramType, const Param &param); DeviceError verifyParam(const ParamType &paramType, const Param &param);
Translator* translator() const;
signals: signals:
void loaded(); void loaded();
void languageUpdated();
void pluginConfigChanged(const PluginId &id, const ParamList &config); void pluginConfigChanged(const PluginId &id, const ParamList &config);
void eventTriggered(const Event &event); void eventTriggered(const Event &event);
void deviceStateChanged(Device *device, const QUuid &stateTypeId, const QVariant &value); void deviceStateChanged(Device *device, const QUuid &stateTypeId, const QVariant &value);
@ -186,6 +186,7 @@ private:
HardwareManager *m_hardwareManager; HardwareManager *m_hardwareManager;
QLocale m_locale; QLocale m_locale;
Translator *m_translator = nullptr;
QHash<VendorId, Vendor> m_supportedVendors; QHash<VendorId, Vendor> m_supportedVendors;
QHash<QString, Interface> m_supportedInterfaces; QHash<QString, Interface> m_supportedInterfaces;
QHash<VendorId, QList<DeviceClassId> > m_vendorDeviceMap; QHash<VendorId, QList<DeviceClassId> > m_vendorDeviceMap;

View File

@ -73,7 +73,8 @@ HEADERS += devicemanager.h \
hardwaremanager.h \ hardwaremanager.h \
nymeadbusservice.h \ nymeadbusservice.h \
network/mqtt/mqttprovider.h \ network/mqtt/mqttprovider.h \
network/mqtt/mqttchannel.h network/mqtt/mqttchannel.h \
translator.h
SOURCES += devicemanager.cpp \ SOURCES += devicemanager.cpp \
loggingcategories.cpp \ loggingcategories.cpp \
@ -132,7 +133,8 @@ SOURCES += devicemanager.cpp \
hardwaremanager.cpp \ hardwaremanager.cpp \
nymeadbusservice.cpp \ nymeadbusservice.cpp \
network/mqtt/mqttprovider.cpp \ network/mqtt/mqttprovider.cpp \
network/mqtt/mqttchannel.cpp network/mqtt/mqttchannel.cpp \
translator.cpp
# install plugininfo python script for libnymea-dev # install plugininfo python script for libnymea-dev

View File

@ -53,3 +53,4 @@ Q_LOGGING_CATEGORY(dcAWSTraffic, "AWSTraffic")
Q_LOGGING_CATEGORY(dcBluetoothServer, "BluetoothServer") Q_LOGGING_CATEGORY(dcBluetoothServer, "BluetoothServer")
Q_LOGGING_CATEGORY(dcBluetoothServerTraffic, "BluetoothServerTraffic") Q_LOGGING_CATEGORY(dcBluetoothServerTraffic, "BluetoothServerTraffic")
Q_LOGGING_CATEGORY(dcMqtt, "Mqtt") Q_LOGGING_CATEGORY(dcMqtt, "Mqtt")
Q_LOGGING_CATEGORY(dcTranslations, "Translations")

View File

@ -61,5 +61,6 @@ Q_DECLARE_LOGGING_CATEGORY(dcAWSTraffic)
Q_DECLARE_LOGGING_CATEGORY(dcBluetoothServer) Q_DECLARE_LOGGING_CATEGORY(dcBluetoothServer)
Q_DECLARE_LOGGING_CATEGORY(dcBluetoothServerTraffic) Q_DECLARE_LOGGING_CATEGORY(dcBluetoothServerTraffic)
Q_DECLARE_LOGGING_CATEGORY(dcMqtt) Q_DECLARE_LOGGING_CATEGORY(dcMqtt)
Q_DECLARE_LOGGING_CATEGORY(dcTranslations)
#endif // LOGGINGCATEGORYS_H #endif // LOGGINGCATEGORYS_H

View File

@ -104,8 +104,7 @@
/*! DevicePlugin constructor. DevicePlugins will be instantiated by the DeviceManager, its \a parent. */ /*! DevicePlugin constructor. DevicePlugins will be instantiated by the DeviceManager, its \a parent. */
DevicePlugin::DevicePlugin(QObject *parent): DevicePlugin::DevicePlugin(QObject *parent):
QObject(parent), QObject(parent)
m_translator(new QTranslator(this))
{ {
} }
@ -124,7 +123,7 @@ QString DevicePlugin::pluginName() const
/*! Returns the displayName of this DevicePlugin, to be shown to the user, translated. */ /*! Returns the displayName of this DevicePlugin, to be shown to the user, translated. */
QString DevicePlugin::pluginDisplayName() const QString DevicePlugin::pluginDisplayName() const
{ {
return translateValue(m_metaData.value("name").toString(), m_metaData.value("displayName").toString()); return m_metaData.value("displayName").toString();
} }
/*! Returns the id of this DevicePlugin. /*! Returns the id of this DevicePlugin.
@ -141,7 +140,7 @@ QList<Vendor> DevicePlugin::supportedVendors() const
QList<Vendor> vendors; QList<Vendor> vendors;
foreach (const QJsonValue &vendorJson, m_metaData.value("vendors").toArray()) { foreach (const QJsonValue &vendorJson, m_metaData.value("vendors").toArray()) {
Vendor vendor(vendorJson.toObject().value("id").toString(), vendorJson.toObject().value("name").toString()); Vendor vendor(vendorJson.toObject().value("id").toString(), vendorJson.toObject().value("name").toString());
vendor.setDisplayName(translateValue(m_metaData.value("name").toString(), vendorJson.toObject().value("displayName").toString())); vendor.setDisplayName(vendorJson.toObject().value("displayName").toString());
vendors.append(vendor); vendors.append(vendor);
} }
return vendors; return vendors;
@ -155,33 +154,6 @@ QList<DeviceClass> DevicePlugin::supportedDevices() const
return m_supportedDevices; return m_supportedDevices;
} }
/*! Returns the translator of this \l{DevicePlugin}. */
QTranslator *DevicePlugin::translator()
{
return m_translator;
}
/*! Returns true if the given \a locale could be set for this \l{DevicePlugin}. */
bool DevicePlugin::setLocale(const QLocale &locale)
{
// check if there are local translations
if (m_translator->load(locale, m_metaData.value("id").toString(), "-", QDir(QCoreApplication::applicationDirPath() + "../../translations/").absolutePath(), ".qm")) {
qCDebug(dcDeviceManager()) << "* Load translation" << locale.name() << "for" << pluginName() << "from" << QDir(QCoreApplication::applicationDirPath() + "../../translations/").absolutePath() + "/" + m_metaData.value("id").toString() + "-" + locale.name() + ".qm";
return true;
}
// otherwise use the system translations
if (m_translator->load(locale, m_metaData.value("id").toString(), "-", NymeaSettings::translationsPath(), ".qm")) {
qCDebug(dcDeviceManager()) << "* Load translation" << locale.name() << "for" << pluginName() << "from" << NymeaSettings::translationsPath();
return true;
}
if (locale.name() != "en_US")
qCWarning(dcDeviceManager()) << "* Could not load translation" << locale.name() << "for plugin" << pluginName();
return false;
}
/*! Override this if your plugin supports Device with DeviceClass::CreationMethodAuto. /*! Override this if your plugin supports Device with DeviceClass::CreationMethodAuto.
This will be called at startup, after the configured devices have been loaded. This will be called at startup, after the configured devices have been loaded.
This is the earliest time you should start emitting autoDevicesAppeared(). If you This is the earliest time you should start emitting autoDevicesAppeared(). If you
@ -327,7 +299,7 @@ QPair<bool, QList<ParamType> > DevicePlugin::parseParamTypes(const QJsonArray &a
} }
ParamType paramType(ParamTypeId(pt.value("id").toString()), pt.value("name").toString(), t, pt.value("defaultValue").toVariant()); ParamType paramType(ParamTypeId(pt.value("id").toString()), pt.value("name").toString(), t, pt.value("defaultValue").toVariant());
paramType.setDisplayName(translateValue(m_metaData.value("name").toString(), pt.value("displayName").toString())); paramType.setDisplayName(pt.value("displayName").toString());
// Set allowed values // Set allowed values
@ -458,6 +430,11 @@ DeviceManager::DeviceError DevicePlugin::setConfigValue(const ParamTypeId &param
return DeviceManager::DeviceErrorNoError; return DeviceManager::DeviceErrorNoError;
} }
bool DevicePlugin::isBuiltIn() const
{
return m_metaData.value("builtIn").toBool();
}
/*! Returns a pointer to the \l{DeviceManager}. /*! Returns a pointer to the \l{DeviceManager}.
When implementing a plugin, use this to find the \l{Device}{Devices} you need. When implementing a plugin, use this to find the \l{Device}{Devices} you need.
*/ */
@ -529,7 +506,7 @@ void DevicePlugin::loadMetaData()
// Note: The DevicePlugin has no type class, so we define the json properties here // Note: The DevicePlugin has no type class, so we define the json properties here
QStringList pluginMandatoryJsonProperties = QStringList() << "id" << "name" << "displayName" << "vendors"; QStringList pluginMandatoryJsonProperties = QStringList() << "id" << "name" << "displayName" << "vendors";
QStringList pluginJsonProperties = QStringList() << "id" << "name" << "displayName" << "vendors" << "paramTypes"; QStringList pluginJsonProperties = QStringList() << "id" << "name" << "displayName" << "vendors" << "paramTypes" << "builtIn";
QPair<QStringList, QStringList> verificationResult = verifyFields(pluginJsonProperties, pluginMandatoryJsonProperties, m_metaData); QPair<QStringList, QStringList> verificationResult = verifyFields(pluginJsonProperties, pluginMandatoryJsonProperties, m_metaData);
@ -593,7 +570,7 @@ void DevicePlugin::loadMetaData()
DeviceClass deviceClass(pluginId(), vendorId, deviceClassObject.value("id").toString()); DeviceClass deviceClass(pluginId(), vendorId, deviceClassObject.value("id").toString());
deviceClass.setName(deviceClassObject.value("name").toString()); deviceClass.setName(deviceClassObject.value("name").toString());
deviceClass.setDisplayName(translateValue(m_metaData.value("name").toString(), deviceClassObject.value("displayName").toString())); deviceClass.setDisplayName(deviceClassObject.value("displayName").toString());
// Read create methods // Read create methods
DeviceClass::CreateMethods createMethods; DeviceClass::CreateMethods createMethods;
@ -665,7 +642,7 @@ void DevicePlugin::loadMetaData()
deviceClass.setSetupMethod(setupMethod); deviceClass.setSetupMethod(setupMethod);
// Read pairing info // Read pairing info
deviceClass.setPairingInfo(translateValue(m_metaData.value("name").toString(), deviceClassObject.value("pairingInfo").toString())); deviceClass.setPairingInfo(deviceClassObject.value("pairingInfo").toString());
// Read basic tags // Read basic tags
QList<DeviceClass::BasicTag> basicTags; QList<DeviceClass::BasicTag> basicTags;
@ -725,7 +702,7 @@ void DevicePlugin::loadMetaData()
StateType stateType(st.value("id").toString()); StateType stateType(st.value("id").toString());
stateType.setName(st.value("name").toString()); stateType.setName(st.value("name").toString());
stateType.setDisplayName(translateValue(m_metaData.value("name").toString(), st.value("displayName").toString())); stateType.setDisplayName(st.value("displayName").toString());
stateType.setIndex(index++); stateType.setIndex(index++);
stateType.setType(t); stateType.setType(t);
QPair<bool, Types::Unit> unitVerification = loadAndVerifyUnit(st.value("unit").toString()); QPair<bool, Types::Unit> unitVerification = loadAndVerifyUnit(st.value("unit").toString());
@ -775,9 +752,9 @@ void DevicePlugin::loadMetaData()
eventType.setRuleRelevant(st.value("eventRuleRelevant").toBool()); eventType.setRuleRelevant(st.value("eventRuleRelevant").toBool());
eventType.setName(st.value("name").toString()); eventType.setName(st.value("name").toString());
eventType.setDisplayName(translateValue(m_metaData.value("name").toString(), st.value("displayNameEvent").toString())); eventType.setDisplayName(st.value("displayNameEvent").toString());
ParamType paramType(ParamTypeId(stateType.id().toString()), st.value("name").toString(), stateType.type()); ParamType paramType(ParamTypeId(stateType.id().toString()), st.value("name").toString(), stateType.type());
paramType.setDisplayName(translateValue(m_metaData.value("name").toString(), st.value("displayName").toString())); paramType.setDisplayName(st.value("displayName").toString());
paramType.setAllowedValues(stateType.possibleValues()); paramType.setAllowedValues(stateType.possibleValues());
paramType.setDefaultValue(stateType.defaultValue()); paramType.setDefaultValue(stateType.defaultValue());
paramType.setMinValue(stateType.minValue()); paramType.setMinValue(stateType.minValue());
@ -791,7 +768,7 @@ void DevicePlugin::loadMetaData()
if (writableState) { if (writableState) {
ActionType actionType(ActionTypeId(stateType.id().toString())); ActionType actionType(ActionTypeId(stateType.id().toString()));
actionType.setName(stateType.name()); actionType.setName(stateType.name());
actionType.setDisplayName(translateValue(m_metaData.value("name").toString(), st.value("displayNameAction").toString())); actionType.setDisplayName(st.value("displayNameAction").toString());
actionType.setIndex(stateType.index()); actionType.setIndex(stateType.index());
actionType.setParamTypes(QList<ParamType>() << paramType); actionType.setParamTypes(QList<ParamType>() << paramType);
actionTypes.append(actionType); actionTypes.append(actionType);
@ -821,7 +798,7 @@ void DevicePlugin::loadMetaData()
ActionType actionType(at.value("id").toString()); ActionType actionType(at.value("id").toString());
actionType.setName(at.value("name").toString()); actionType.setName(at.value("name").toString());
actionType.setDisplayName(translateValue(m_metaData.value("name").toString(), at.value("displayName").toString())); actionType.setDisplayName(at.value("displayName").toString());
actionType.setIndex(index++); actionType.setIndex(index++);
QPair<bool, QList<ParamType> > paramVerification = parseParamTypes(at.value("paramTypes").toArray()); QPair<bool, QList<ParamType> > paramVerification = parseParamTypes(at.value("paramTypes").toArray());
@ -859,7 +836,7 @@ void DevicePlugin::loadMetaData()
EventType eventType(et.value("id").toString()); EventType eventType(et.value("id").toString());
eventType.setName(et.value("name").toString()); eventType.setName(et.value("name").toString());
eventType.setDisplayName(translateValue(m_metaData.value("name").toString(), et.value("displayName").toString())); eventType.setDisplayName(et.value("displayName").toString());
eventType.setIndex(index++); eventType.setIndex(index++);
if (et.contains("ruleRelevant")) if (et.contains("ruleRelevant"))
eventType.setRuleRelevant(et.value("ruleRelevant").toBool()); eventType.setRuleRelevant(et.value("ruleRelevant").toBool());
@ -1024,15 +1001,6 @@ void DevicePlugin::loadMetaData()
} }
} }
QString DevicePlugin::translateValue(const QString &context, const QString &string) const
{
QString translation = m_translator->translate(context.toUtf8().constData(), string.toUtf8().constData());
if (translation.isEmpty())
translation = string;
return translation;
}
QPair<bool, Types::Unit> DevicePlugin::loadAndVerifyUnit(const QString &unitString) const QPair<bool, Types::Unit> DevicePlugin::loadAndVerifyUnit(const QString &unitString) const
{ {
if (unitString.isEmpty()) if (unitString.isEmpty())

View File

@ -63,9 +63,6 @@ public:
QList<Vendor> supportedVendors() const; QList<Vendor> supportedVendors() const;
QList<DeviceClass> supportedDevices() const; QList<DeviceClass> supportedDevices() const;
QTranslator *translator();
bool setLocale(const QLocale &locale);
virtual void startMonitoringAutoDevices(); virtual void startMonitoringAutoDevices();
virtual DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params); virtual DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params);
@ -85,6 +82,8 @@ public:
QVariant configValue(const ParamTypeId &paramTypeId) const; QVariant configValue(const ParamTypeId &paramTypeId) const;
DeviceManager::DeviceError setConfigValue(const ParamTypeId &paramTypeId, const QVariant &value); DeviceManager::DeviceError setConfigValue(const ParamTypeId &paramTypeId, const QVariant &value);
bool isBuiltIn() const;
signals: signals:
void emitEvent(const Event &event); void emitEvent(const Event &event);
void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &deviceDescriptors); void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &deviceDescriptors);
@ -111,8 +110,6 @@ private:
// Returns <missingFields, unknownFields> // Returns <missingFields, unknownFields>
QPair<QStringList, QStringList> verifyFields(const QStringList &possibleFields, const QStringList &mandatoryFields, const QJsonObject &value) const; QPair<QStringList, QStringList> verifyFields(const QStringList &possibleFields, const QStringList &mandatoryFields, const QJsonObject &value) const;
QString translateValue(const QString &context, const QString &string) const;
// load and verify enum values // load and verify enum values
QPair<bool, Types::Unit> loadAndVerifyUnit(const QString &unitString) const; QPair<bool, Types::Unit> loadAndVerifyUnit(const QString &unitString) const;
QPair<bool, Types::InputType> loadAndVerifyInputType(const QString &inputType) const; QPair<bool, Types::InputType> loadAndVerifyInputType(const QString &inputType) const;
@ -127,7 +124,6 @@ private:
static Interface mergeInterfaces(const Interface &iface1, const Interface &iface2); static Interface mergeInterfaces(const Interface &iface1, const Interface &iface2);
static QStringList generateInterfaceParentList(const QString &interface); static QStringList generateInterfaceParentList(const QString &interface);
QTranslator *m_translator = nullptr;
DeviceManager *m_deviceManager = nullptr; DeviceManager *m_deviceManager = nullptr;
QList<ParamType> m_configurationDescription; QList<ParamType> m_configurationDescription;

134
libnymea/translator.cpp Normal file
View File

@ -0,0 +1,134 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
* *
* This file is part of nymea. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; If not, see *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "translator.h"
#include "nymeasettings.h"
#include "loggingcategories.h"
#include "plugin/deviceplugin.h"
#include <QCoreApplication>
#include <QDir>
Translator::Translator(DeviceManager *deviceManager):
m_deviceManager(deviceManager)
{
}
Translator::~Translator()
{
foreach (const TranslatorContext &ctx, m_translatorContexts) {
foreach (QTranslator *t, ctx.translators) {
t->deleteLater();
}
}
m_translatorContexts.clear();
}
QString Translator::translate(const PluginId &pluginId, const QString &string, const QLocale &locale)
{
DevicePlugin *plugin = m_deviceManager->plugin(pluginId);
if (!m_translatorContexts.contains(plugin->pluginId()) || !m_translatorContexts.value(plugin->pluginId()).translators.contains(locale.name())) {
loadTranslator(plugin, locale);
}
QTranslator* translator = m_translatorContexts.value(plugin->pluginId()).translators.value(locale.name());
QString translatedString = translator->translate(plugin->pluginName().toUtf8(), string.toUtf8());
return translatedString.isEmpty() ? string : translatedString;
}
void Translator::loadTranslator(DevicePlugin *plugin, const QLocale &locale)
{
if (!m_translatorContexts.contains(plugin->pluginId())) {
// Create default translator for this plugin
TranslatorContext defaultCtx;
defaultCtx.pluginId = plugin->pluginId();
defaultCtx.translators.insert("en_US", new QTranslator());
m_translatorContexts.insert(plugin->pluginId(), defaultCtx);
if (locale == QLocale("en_US")) {
return;
}
}
bool loaded = false;
// check if there are local translations
QTranslator* translator = new QTranslator();
if (plugin->isBuiltIn()) {
if (translator->load(locale, QCoreApplication::instance()->applicationName(), "-", QDir(QCoreApplication::applicationDirPath() + "../../translations/").absolutePath(), ".qm")) {
qCDebug(dcTranslations()) << "* Loaded translation" << locale.name() << "for plugin" << plugin->pluginName() << "from" << QDir(QCoreApplication::applicationDirPath() + "../../translations/").absolutePath() + "/" + QCoreApplication::applicationName() + "-[" + locale.name() + "].qm";
loaded = true;
} else if (translator->load(locale, QCoreApplication::instance()->applicationName(), "-", NymeaSettings::translationsPath(), ".qm")) {
qCDebug(dcTranslations()) << "* Loaded translation" << locale.name() << "for plugin" << plugin->pluginName() << "from" << NymeaSettings::translationsPath()+ "/" + QCoreApplication::applicationName() + "-[" + locale.name() + "].qm";
loaded = true;
}
} else {
QString pluginId = plugin->pluginId().toString().remove(QRegExp("[{}]"));
QStringList searchDirs = QString(qgetenv("NYMEA_PLUGINS_PATH")).split(':');
searchDirs << QCoreApplication::applicationDirPath() + "/../lib/nymea/plugins";
searchDirs << QCoreApplication::applicationDirPath() + "/../plugins/";
searchDirs << QCoreApplication::applicationDirPath() + "/../../../plugins/";
foreach (const QString &pluginPath, searchDirs) {
if (translator->load(locale, pluginId, "-", QDir(pluginPath + "/translations/").absolutePath(), ".qm")) {
qCDebug(dcTranslations()) << "* Loaded translation" << locale.name() << "for plugin" << plugin->pluginName() << "from" << QDir(pluginPath + "/translations/").absolutePath();
loaded = true;
break;
}
foreach (const QString &subdir, QDir(pluginPath).entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
if (translator->load(locale, pluginId, "-", QDir(pluginPath + "/" + subdir + "/translations/").absolutePath(), ".qm")) {
qCDebug(dcTranslations()) << "* Loaded translation" << locale.name() << "for plugin" << plugin->pluginName() << "from" << QDir(pluginPath + "/" + subdir + "/translations/").absolutePath() + "/" + pluginId + "-[" + locale.name() + "].qm";
loaded = true;
break;
}
}
if (loaded) {
break;
}
}
// otherwise use the system translations
if (!loaded && translator->load(locale, pluginId, "-", NymeaSettings::translationsPath(), ".qm")) {
qCDebug(dcTranslations()) << "* Load translation" << locale.name() << "for" << plugin->pluginName() << "from" << NymeaSettings::translationsPath() + "/" + pluginId + "-[" + locale.name() + "].qm";
loaded = true;
}
if (!loaded && locale.name() != "en_US") {
qCWarning(dcTranslations()) << "* Could not load translation" << locale.name() << "for plugin" << plugin->pluginName() << "(" << pluginId << ")";
}
}
if (!loaded) {
translator = m_translatorContexts.value(plugin->pluginId()).translators.value("en_US");
}
if (!m_translatorContexts.contains(plugin->pluginId())) {
TranslatorContext ctx;
ctx.pluginId = plugin->pluginId();
m_translatorContexts.insert(plugin->pluginId(), ctx);
}
m_translatorContexts[plugin->pluginId()].translators.insert(locale.name(), translator);
}

55
libnymea/translator.h Normal file
View File

@ -0,0 +1,55 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
* *
* This file is part of nymea. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; If not, see *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef TRANSLATOR_H
#define TRANSLATOR_H
#include "typeutils.h"
#include "types/deviceclass.h"
#include <QTranslator>
class DevicePlugin;
class DeviceManager;
class Translator
{
public:
Translator(DeviceManager *deviceManager);
~Translator();
QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale);
private:
void loadTranslator(DevicePlugin *plugin, const QLocale &locale);
private:
DeviceManager *m_deviceManager = nullptr;
struct TranslatorContext {
PluginId pluginId;
QHash<QString, QTranslator*> translators;
};
QHash<PluginId, TranslatorContext> m_translatorContexts;
};
#endif // TRANSLATOR_H

View File

@ -485,3 +485,9 @@ QStringList DeviceClass::mandatoryTypeProperties()
{ {
return QStringList() << "id" << "name" << "displayName"; return QStringList() << "id" << "name" << "displayName";
} }
QDebug operator<<(QDebug &dbg, const DeviceClass &deviceClass)
{
dbg << "DeviceClass ID:" << deviceClass.id() << "Name:" << deviceClass.name();
return dbg;
}

View File

@ -207,4 +207,6 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(DeviceClass::CreateMethods) Q_DECLARE_OPERATORS_FOR_FLAGS(DeviceClass::CreateMethods)
QDebug operator<<(QDebug &dbg, const DeviceClass &deviceClass);
#endif #endif

View File

@ -74,3 +74,8 @@ void Vendor::setDisplayName(const QString &displayName)
{ {
m_displayName = displayName; m_displayName = displayName;
} }
bool Vendor::operator==(const Vendor &other) const
{
return m_id == other.id();
}

View File

@ -43,6 +43,8 @@ public:
QString displayName() const; QString displayName() const;
void setDisplayName(const QString &displayName); void setDisplayName(const QString &displayName);
bool operator==(const Vendor &other) const;
private: private:
VendorId m_id; VendorId m_id;
QString m_name; QString m_name;

View File

@ -6,7 +6,7 @@ NYMEA_PLUGINS_PATH=/usr/lib/$$system('dpkg-architecture -q DEB_HOST_MULTIARCH')/
# define protocol versions # define protocol versions
JSON_PROTOCOL_VERSION_MAJOR=1 JSON_PROTOCOL_VERSION_MAJOR=1
JSON_PROTOCOL_VERSION_MINOR=13 JSON_PROTOCOL_VERSION_MINOR=14
REST_API_VERSION=1 REST_API_VERSION=1
COPYRIGHT_YEAR_FROM=2013 COPYRIGHT_YEAR_FROM=2013

View File

@ -23,19 +23,22 @@ test.commands = LD_LIBRARY_PATH=$$top_builddir/libnymea-core:$$top_builddir/libn
# Translations: # Translations:
# make lupdate to update .ts files # make lupdate to update .ts files
TRANSLATIONS += $$files(translations/*.ts, true) CORE_TRANSLATIONS += $$files($${top_srcdir}/translations/*.ts, true)
TRANSLATIONS += $$files(plugins/mock/translations/*.ts, true) lupdate.commands = lupdate -recursive -no-obsolete $${top_srcdir} -ts $${CORE_TRANSLATIONS};
PLUGIN_TRANSLATIONS += $$files($${top_srcdir}/plugins/mock/translations/*.ts, true)
lupdate.commands += lupdate -recursive -no-obsolete $${top_builddir}/plugins/mock/ -ts $${PLUGIN_TRANSLATIONS};
lupdate.depends = FORCE lupdate.depends = FORCE
lupdate.commands = lupdate -recursive -no-obsolete $$_FILE_; TRANSLATIONS = $${CORE_TRANSLATIONS} $${PLUGIN_TRANSLATIONS}
# make lrelease to compile .ts to .qm # make lrelease to compile .ts to .qm
lrelease.depends = FORCE lrelease.depends = FORCE
lrelease.commands = lrelease $$_FILE_; \ lrelease.commands = lrelease $$_FILE_; \
rsync -a $$top_srcdir/translations/*.qm $$top_builddir/translations/; rsync -a $$top_srcdir/translations/*.qm $$top_builddir/translations/; \
rsync -a $$top_srcdir/plugins/mock/translations/*.qm $$top_builddir/plugins/mock/translations/;
first.depends = $(first) lrelease
# Install translation files # Install translation files
translations.path = /usr/share/nymea/translations translations.path = /usr/share/nymea/translations
translations.files = $$[QT_SOURCE_TREE]/translations/*.qm
translations.depends = lrelease translations.depends = lrelease
INSTALLS += translations INSTALLS += translations

View File

@ -3,7 +3,7 @@ include(../nymea.pri)
TEMPLATE = lib TEMPLATE = lib
CONFIG += plugin CONFIG += plugin
QT += network bluetooth QT += network
INCLUDEPATH += $$top_srcdir/libnymea INCLUDEPATH += $$top_srcdir/libnymea
LIBS += -L../../libnymea -lnymea LIBS += -L../../libnymea -lnymea

View File

@ -131,7 +131,8 @@ int main(int argc, char *argv[])
"AWSTraffic", "AWSTraffic",
"BluetoothServer", "BluetoothServer",
"BluetoothServerTraffic", "BluetoothServerTraffic",
"Mqtt" "Mqtt",
"Translations"
}; };
QStringList loggingFiltersPlugins; QStringList loggingFiltersPlugins;
@ -145,7 +146,7 @@ int main(int argc, char *argv[])
// check if there are local translations // check if there are local translations
if (!translator.load(QLocale::system(), application.applicationName(), "-", QDir(QCoreApplication::applicationDirPath() + "../../translations/").absolutePath(), ".qm")) if (!translator.load(QLocale::system(), application.applicationName(), "-", QDir(QCoreApplication::applicationDirPath() + "../../translations/").absolutePath(), ".qm"))
if (!translator.load(QLocale::system(), application.applicationName(), "-", NymeaSettings::translationsPath(), ".qm")) if (!translator.load(QLocale::system(), application.applicationName(), "-", NymeaSettings::translationsPath(), ".qm"))
qWarning(dcApplication()) << "Could not find nymead translations for" << QLocale::system().name() << endl << (QDir(QCoreApplication::applicationDirPath() + "../../translations/").absolutePath()) << endl << NymeaSettings::translationsPath(); qWarning(dcTranslations()) << "Could not find nymead translations for" << QLocale::system().name() << endl << (QDir(QCoreApplication::applicationDirPath() + "../../translations/").absolutePath()) << endl << NymeaSettings::translationsPath();

View File

@ -1,4 +1,4 @@
1.13 1.14
{ {
"methods": { "methods": {
"Actions.ExecuteAction": { "Actions.ExecuteAction": {
@ -78,7 +78,7 @@
} }
}, },
"Configuration.GetAvailableLanguages": { "Configuration.GetAvailableLanguages": {
"description": "Returns a list of locale codes available for the server. i.e. en_US, de_AT", "description": "DEPRECATED - Use the locale property in the Handshake message instead - Returns a list of locale codes available for the server. i.e. en_US, de_AT",
"params": { "params": {
}, },
"returns": { "returns": {
@ -163,7 +163,7 @@
} }
}, },
"Configuration.SetLanguage": { "Configuration.SetLanguage": {
"description": "Sets the server language to the given language. See also: \"GetAvailableLanguages\"", "description": "DEPRECATED - Use the locale property in the Handshake message instead - Sets the server language to the given language. See also: \"GetAvailableLanguages\"",
"params": { "params": {
"language": "String" "language": "String"
}, },
@ -492,14 +492,16 @@
} }
}, },
"JSONRPC.Hello": { "JSONRPC.Hello": {
"description": "Upon first connection, nymea will automatically send a welcome message containing information about the setup. If this message is lost for whatever reason (connections with multiple hops might drop this if nymea sends it too early), the exact same message can be retrieved multiple times by calling this Hello method. Note that the contents might change if the system changed its state in the meantime, e.g. initialSetupRequired might turn false if the initial setup has been performed in the meantime.", "description": "Initiates a connection. Use this method to perform an initial handshake of the connection. Optionally, a parameter \"locale\" is can be passed to set up the used locale for this connection. Strings such as DeviceClass displayNames etc will be localized to this locale. If this parameter is omitted, the default system locale (depending on the configuration) is used. The reply of this method contains information about this core instance such as version information, uuid and its name. The locale valueindicates the locale used for this connection. Note: This method can be called multiple times. The locale used in the last call for this connection will be used. Other values, like initialSetupRequired might change if the setup has been performed in the meantime.",
"params": { "params": {
"o:locale": "String"
}, },
"returns": { "returns": {
"authenticationRequired": "Bool", "authenticationRequired": "Bool",
"id": "Int", "id": "Int",
"initialSetupRequired": "Bool", "initialSetupRequired": "Bool",
"language": "String", "language": "String",
"locale": "String",
"name": "String", "name": "String",
"protocol version": "String", "protocol version": "String",
"pushButtonAuthAvailable": "Bool", "pushButtonAuthAvailable": "Bool",

View File

@ -35,6 +35,8 @@ private slots:
void testHandshake(); void testHandshake();
void testHandshakeLocale();
void testInitialSetup(); void testInitialSetup();
void testRevokeToken(); void testRevokeToken();
@ -131,7 +133,9 @@ void TestJSONRPC::initTestCase()
{ {
NymeaTestBase::initTestCase(); NymeaTestBase::initTestCase();
QLoggingCategory::setFilterRules("*.debug=false\n" QLoggingCategory::setFilterRules("*.debug=false\n"
"JsonRpc*.debug=true"); // "JsonRpc*.debug=true\n"
"Translations.debug=true\n"
"Tests.debug=true");
} }
void TestJSONRPC::testHandshake() void TestJSONRPC::testHandshake()
@ -170,6 +174,42 @@ void TestJSONRPC::testHandshake()
QCOMPARE(handShake.value("params").toMap().value("version").toString(), nymeaVersionString); QCOMPARE(handShake.value("params").toMap().value("version").toString(), nymeaVersionString);
} }
void TestJSONRPC::testHandshakeLocale()
{
// first test if the handshake message is auto-sent upon connecting
QSignalSpy spy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray)));
// Test withouth locale data
QVariantMap handShake = injectAndWait("JSONRPC.Hello").toMap();
QCOMPARE(handShake.value("params").toMap().value("locale").toString(), QString("en_US"));
QVariantMap supportedDevices = injectAndWait("Devices.GetSupportedDevices").toMap();
bool found = false;
foreach (const QVariant &dcMap, supportedDevices.value("params").toMap().value("deviceClasses").toList()) {
if (dcMap.toMap().value("id").toUuid() == mockDeviceAutoClassId) {
QCOMPARE(dcMap.toMap().value("displayName").toString(), QString("Mock Device (Auto created)"));
found = true;
}
}
QVERIFY(found);
// And now with locale info
QVariantMap params;
params.insert("locale", "de_DE");
handShake = injectAndWait("JSONRPC.Hello", params).toMap();
QCOMPARE(handShake.value("params").toMap().value("locale").toString(), QString("de_DE"));
supportedDevices = injectAndWait("Devices.GetSupportedDevices").toMap();
found = false;
foreach (const QVariant &dcMap, supportedDevices.value("params").toMap().value("deviceClasses").toList()) {
if (dcMap.toMap().value("id").toUuid() == mockDeviceAutoClassId) {
QCOMPARE(dcMap.toMap().value("displayName").toString(), QString("Mock Gerät (Automatisch erzeugt)"));
found = true;
}
}
QVERIFY(found);
}
void TestJSONRPC::testInitialSetup() void TestJSONRPC::testInitialSetup()
{ {
foreach (const QString &user, NymeaCore::instance()->userManager()->users()) { foreach (const QString &user, NymeaCore::instance()->userManager()->users()) {