Merge PR #138: Rework translation mechanism

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

View File

@ -100,7 +100,7 @@ JsonReply *ActionHandler::GetActionType(const QVariantMap &params) const
foreach (const ActionType &actionType, deviceClass.actionTypes()) {
if (actionType.id() == actionTypeId) {
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);
}
}

View File

@ -75,7 +75,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
setReturns("GetTimeZones", returns);
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);
returns.insert("languages", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String));
setReturns("GetAvailableLanguages", returns);
@ -122,7 +122,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
setReturns("SetTimeZone", returns);
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));
setParams("SetLanguage", params);
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::localeChanged, 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::tcpServerConfigurationRemoved, this, &ConfigurationHandler::onTcpServerConfigurationRemoved);
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::webServerConfigurationChanged, this, &ConfigurationHandler::onWebServerConfigurationChanged);

View File

@ -60,6 +60,7 @@
#include "types/deviceclass.h"
#include "plugin/device.h"
#include "plugin/deviceplugin.h"
#include "translator.h"
#include <QDebug>
@ -319,14 +320,14 @@ JsonReply* DeviceHandler::GetSupportedVendors(const QVariantMap &params) const
Q_UNUSED(params)
QVariantMap returns;
returns.insert("vendors", JsonTypes::packSupportedVendors());
returns.insert("vendors", JsonTypes::packSupportedVendors(params.value("locale").toLocale()));
return createReply(returns);
}
JsonReply* DeviceHandler::GetSupportedDevices(const QVariantMap &params) const
{
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);
}
@ -354,7 +355,7 @@ JsonReply* DeviceHandler::GetPlugins(const QVariantMap &params) const
Q_UNUSED(params)
QVariantMap returns;
returns.insert("plugins", JsonTypes::packPlugins());
returns.insert("plugins", JsonTypes::packPlugins(params.value("locale").toLocale()));
return createReply(returns);
}
@ -437,7 +438,7 @@ JsonReply *DeviceHandler::PairDevice(const QVariantMap &params)
QVariantMap returns;
returns.insert("deviceError", JsonTypes::deviceErrorToString(status));
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("setupMethod", JsonTypes::setupMethod().at(deviceClass.setupMethod()));
}
@ -565,7 +566,7 @@ JsonReply* DeviceHandler::GetEventTypes(const QVariantMap &params) const
QVariantList eventList;
DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString()));
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);
return createReply(returns);
@ -578,7 +579,7 @@ JsonReply* DeviceHandler::GetActionTypes(const QVariantMap &params) const
QVariantList actionList;
DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString()));
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);
return createReply(returns);
@ -591,7 +592,7 @@ JsonReply* DeviceHandler::GetStateTypes(const QVariantMap &params) const
QVariantList stateList;
DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString()));
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);
return createReply(returns);

View File

@ -88,7 +88,7 @@ JsonReply* EventHandler::GetEventType(const QVariantMap &params) const
foreach (const EventType &eventType, deviceClass.eventTypes()) {
if (eventType.id() == eventTypeId) {
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);
}
}

View File

@ -75,7 +75,16 @@ JsonRPCServer::JsonRPCServer(const QSslConfiguration &sslConfiguration, QObject
QVariantMap params;
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);
returns.insert("id", JsonTypes::basicTypeToString(JsonTypes::Int));
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("uuid", JsonTypes::basicTypeToString(JsonTypes::Uuid));
returns.insert("language", JsonTypes::basicTypeToString(JsonTypes::String));
returns.insert("locale", JsonTypes::basicTypeToString(JsonTypes::String));
returns.insert("protocol version", JsonTypes::basicTypeToString(JsonTypes::String));
returns.insert("initialSetupRequired", JsonTypes::basicTypeToString(JsonTypes::Bool));
returns.insert("authenticationRequired", JsonTypes::basicTypeToString(JsonTypes::Bool));
@ -225,11 +235,20 @@ QString JsonRPCServer::name() const
return QStringLiteral("JSONRPC");
}
JsonReply *JsonRPCServer::Hello(const QVariantMap &params) const
JsonReply *JsonRPCServer::Hello(const QVariantMap &params)
{
Q_UNUSED(params);
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
@ -465,7 +484,7 @@ void JsonRPCServer::sendUnauthorizedResponse(TransportInterface *interface, cons
interface->sendData(clientId, data);
}
QVariantMap JsonRPCServer::createWelcomeMessage(TransportInterface *interface) const
QVariantMap JsonRPCServer::createWelcomeMessage(TransportInterface *interface, const QUuid &clientId) const
{
QVariantMap handshake;
handshake.insert("id", 0);
@ -473,7 +492,9 @@ QVariantMap JsonRPCServer::createWelcomeMessage(TransportInterface *interface) c
handshake.insert("name", NymeaCore::instance()->configuration()->serverName());
handshake.insert("version", NYMEA_VERSION_STRING);
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("initialSetupRequired", (interface->configuration().authenticationEnabled ? NymeaCore::instance()->userManager()->initRequired() : false));
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();
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;
QMetaObject::invokeMethod(handler, method.toLatin1().data(), Q_RETURN_ARG(JsonReply*, reply), Q_ARG(QVariantMap, params));
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
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)
@ -745,6 +776,7 @@ void JsonRPCServer::clientDisconnected(const QUuid &clientId)
m_clientTransports.remove(clientId);
m_clientNotifications.remove(clientId);
m_clientBuffers.remove(clientId);
m_clientLocales.remove(clientId);
if (m_pushButtonTransactions.values().contains(clientId)) {
NymeaCore::instance()->userManager()->cancelPushButtonAuth(m_pushButtonTransactions.key(clientId));
}

View File

@ -47,7 +47,7 @@ public:
// JsonHandler API implementation
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 *Version(const QVariantMap &params) const;
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 sendErrorResponse(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);
@ -105,6 +105,7 @@ private:
QHash<QUuid, TransportInterface*> m_clientTransports;
QHash<QUuid, QByteArray> m_clientBuffers;
QHash<QUuid, bool> m_clientNotifications;
QHash<QUuid, QLocale> m_clientLocales;
QHash<int, QUuid> m_pushButtonTransactions;
QHash<QString, JsonReply*> m_pairingRequests;

View File

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

View File

@ -180,23 +180,23 @@ public:
DECLARE_OBJECT(mqttPolicy, "MqttPolicy")
// 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 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 packRuleAction(const RuleAction &ruleAction);
static QVariantMap packRuleActionParam(const RuleActionParam &ruleActionParam);
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 packStateEvaluator(const StateEvaluator &stateEvaluator);
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 packVendor(const Vendor &vendor);
static QVariantMap packDeviceClass(const DeviceClass &deviceClass);
static QVariantMap packPlugin(DevicePlugin *plugin);
static QVariantMap packVendor(const Vendor &vendor, const QLocale &locale);
static QVariantMap packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale);
static QVariantMap packPlugin(DevicePlugin *pluginid, const QLocale &locale);
static QVariantMap packDevice(Device *device);
static QVariantMap packDeviceDescriptor(const DeviceDescriptor &descriptor);
static QVariantMap packRule(const Rule &rule);
@ -213,8 +213,8 @@ public:
static QVariantList packRules(const QList<Rule> rules);
static QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods);
static QVariantList packSupportedVendors();
static QVariantList packSupportedDevices(const VendorId &vendorId);
static QVariantList packSupportedVendors(const QLocale &locale);
static QVariantList packSupportedDevices(const VendorId &vendorId, const QLocale &locale);
static QVariantList packConfiguredDevices();
static QVariantList packDeviceStates(Device *device);
static QVariantList packDeviceDescriptors(const QList<DeviceDescriptor> deviceDescriptors);
@ -227,10 +227,10 @@ public:
static QVariantList packRuleDescriptions();
static QVariantList packRuleDescriptions(const QList<Rule> &rules);
static QVariantList packActionTypes(const DeviceClass &deviceClass);
static QVariantList packStateTypes(const DeviceClass &deviceClass);
static QVariantList packEventTypes(const DeviceClass &deviceClass);
static QVariantList packPlugins();
static QVariantList packActionTypes(const DeviceClass &deviceClass, const QLocale &locale);
static QVariantList packStateTypes(const DeviceClass &deviceClass, const QLocale &locale);
static QVariantList packEventTypes(const DeviceClass &deviceClass, const QLocale &locale);
static QVariantList packPlugins(const QLocale &locale);
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()) {
if (stateType.id() == stateTypeId) {
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);
}
}

View File

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

View File

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

View File

@ -184,7 +184,7 @@ HttpReply *DeviceClassesResource::getDeviceClass()
qCDebug(dcRest) << "Get device class with id " << m_deviceClass.id();
HttpReply *reply = createSuccessReply();
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;
}
@ -193,7 +193,7 @@ HttpReply *DeviceClassesResource::getActionTypes()
qCDebug(dcRest) << "Get action types for device class" << m_deviceClass.id();
HttpReply *reply = createSuccessReply();
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;
}
@ -205,7 +205,7 @@ HttpReply *DeviceClassesResource::getActionType(const ActionTypeId &actionTypeId
if (actionType.id() == actionTypeId) {
HttpReply *reply = createSuccessReply();
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;
}
}
@ -217,7 +217,7 @@ HttpReply *DeviceClassesResource::getStateTypes()
qCDebug(dcRest) << "Get state types for device class" << m_deviceClass.id();
HttpReply *reply = createSuccessReply();
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;
}
@ -229,7 +229,7 @@ HttpReply *DeviceClassesResource::getStateType(const StateTypeId &stateTypeId)
if (stateType.id() == stateTypeId) {
HttpReply *reply = createSuccessReply();
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;
}
}
@ -241,7 +241,7 @@ HttpReply *DeviceClassesResource::getEventTypes()
qCDebug(dcRest) << "Get event types for device class" << m_deviceClass.id();
HttpReply *reply = createSuccessReply();
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;
}
@ -253,7 +253,7 @@ HttpReply *DeviceClassesResource::getEventType(const EventTypeId &eventTypeId)
if (eventType.id() == eventTypeId) {
HttpReply *reply = createSuccessReply();
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;
}
}
@ -307,7 +307,7 @@ HttpReply *DeviceClassesResource::getDeviceClasses(const VendorId &vendorId)
HttpReply *reply = createSuccessReply();
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;
}

View File

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

View File

@ -41,6 +41,7 @@
#include "servers/httprequest.h"
#include "jsonrpc/jsontypes.h"
#include "nymeacore.h"
#include "translator.h"
#include <QJsonDocument>
@ -442,7 +443,7 @@ HttpReply *DevicesResource::pairDevice(const QByteArray &payload) const
return createDeviceErrorReply(HttpReply::BadRequest, status);
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("setupMethod", JsonTypes::setupMethod().at(deviceClass.setupMethod()));
HttpReply *reply = createSuccessReply();

View File

@ -139,7 +139,7 @@ HttpReply *PluginsResource::getPlugins() const
qCDebug(dcRest) << "Get plugins";
HttpReply *reply = createSuccessReply();
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;
}
@ -150,7 +150,7 @@ HttpReply *PluginsResource::getPlugin(const PluginId &pluginId) const
foreach (DevicePlugin *plugin, NymeaCore::instance()->deviceManager()->plugins()) {
if (plugin->pluginId() == pluginId) {
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;
}
}

View File

@ -111,7 +111,7 @@ HttpReply *VendorsResource::getVendors() const
QVariantList vendorsList;
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->setPayload(QJsonDocument::fromVariant(vendorsList).toJson());
@ -125,7 +125,7 @@ HttpReply *VendorsResource::getVendor(const VendorId &vendorId) const
if (vendor.id() == vendorId) {
HttpReply *reply = createSuccessReply();
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;
}
}

View File

@ -181,6 +181,7 @@
#include "typeutils.h"
#include "nymeasettings.h"
#include "unistd.h"
#include "translator.h"
#include "plugintimer.h"
@ -198,7 +199,8 @@
DeviceManager::DeviceManager(HardwareManager *hardwareManager, const QLocale &locale, QObject *parent) :
QObject(parent),
m_hardwareManager(hardwareManager),
m_locale(locale)
m_locale(locale),
m_translator(new Translator(this))
{
qRegisterMetaType<DeviceClassId>();
qRegisterMetaType<DeviceDescriptor>();
@ -219,6 +221,8 @@ DeviceManager::DeviceManager(HardwareManager *hardwareManager, const QLocale &lo
/*! Destructor of the DeviceManager. Each loaded \l{DevicePlugin} will be deleted. */
DeviceManager::~DeviceManager()
{
delete m_translator;
foreach (Device *device, m_configuredDevices) {
storeDeviceStates(device);
}
@ -288,44 +292,6 @@ void DeviceManager::registerStaticPlugin(DevicePlugin *plugin, const QJsonObject
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.
\sa HardwareManager
@ -400,13 +366,15 @@ Interface DeviceManager::findInterface(const QString &name)
* Optionally filtered by \a vendorId. */
QList<DeviceClass> DeviceManager::supportedDevices(const VendorId &vendorId) const
{
QList<DeviceClass> ret;
if (vendorId.isNull()) {
ret = m_supportedDevices.values();
} else {
foreach (const DeviceClassId &deviceClassId, m_vendorDeviceMap.value(vendorId)) {
ret.append(m_supportedDevices.value(deviceClassId));
return m_supportedDevices.values();
}
QList<DeviceClass> ret;
foreach (const DeviceClass &deviceClass, m_supportedDevices) {
if (!vendorId.isNull() && deviceClass.vendorId() != vendorId) {
continue;
}
ret.append(deviceClass);
}
return ret;
}
@ -928,13 +896,13 @@ DeviceManager::DeviceError DeviceManager::verifyParam(const ParamType &paramType
return DeviceErrorInvalidParameter;
}
if (!param.value().canConvert(paramType.type())) {
qCWarning(dcDeviceManager) << "Wrong parameter type for param" << param.paramTypeId().toString() << " Got:" << param.value() << " Expected:" << QVariant::typeToName(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(static_cast<int>(paramType.type()));
return DeviceErrorInvalidParameter;
}
if (!param.value().convert(paramType.type())) {
qCWarning(dcDeviceManager) << "Could not convert value of param" << param.paramTypeId().toString() << " to:" << QVariant::typeToName(paramType.type()) << " Got:" << param.value();
if (!param.value().convert(static_cast<int>(paramType.type()))) {
qCWarning(dcDeviceManager) << "Could not convert value of param" << param.paramTypeId().toString() << " to:" << QVariant::typeToName(static_cast<int>(paramType.type())) << " Got:" << param.value();
return DeviceErrorInvalidParameter;
}
@ -993,6 +961,13 @@ DeviceManager::DeviceError DeviceManager::verifyParam(const ParamType &paramType
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}.
* 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}.*/
@ -1079,9 +1054,6 @@ void DeviceManager::loadPlugins()
void DeviceManager::loadPlugin(DevicePlugin *pluginIface)
{
pluginIface->setLocale(m_locale);
qApp->installTranslator(pluginIface->translator());
pluginIface->initPlugin(this);
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::autoDevicesAppeared, this, &DeviceManager::onAutoDevicesAppeared);
connect(pluginIface, &DevicePlugin::autoDeviceDisappeared, this, &DeviceManager::onAutoDeviceDisappeared);
}
void DeviceManager::loadConfiguredDevices()

View File

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

View File

@ -73,7 +73,8 @@ HEADERS += devicemanager.h \
hardwaremanager.h \
nymeadbusservice.h \
network/mqtt/mqttprovider.h \
network/mqtt/mqttchannel.h
network/mqtt/mqttchannel.h \
translator.h
SOURCES += devicemanager.cpp \
loggingcategories.cpp \
@ -132,7 +133,8 @@ SOURCES += devicemanager.cpp \
hardwaremanager.cpp \
nymeadbusservice.cpp \
network/mqtt/mqttprovider.cpp \
network/mqtt/mqttchannel.cpp
network/mqtt/mqttchannel.cpp \
translator.cpp
# 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(dcBluetoothServerTraffic, "BluetoothServerTraffic")
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(dcBluetoothServerTraffic)
Q_DECLARE_LOGGING_CATEGORY(dcMqtt)
Q_DECLARE_LOGGING_CATEGORY(dcTranslations)
#endif // LOGGINGCATEGORYS_H

View File

@ -104,8 +104,7 @@
/*! DevicePlugin constructor. DevicePlugins will be instantiated by the DeviceManager, its \a parent. */
DevicePlugin::DevicePlugin(QObject *parent):
QObject(parent),
m_translator(new QTranslator(this))
QObject(parent)
{
}
@ -124,7 +123,7 @@ QString DevicePlugin::pluginName() const
/*! Returns the displayName of this DevicePlugin, to be shown to the user, translated. */
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.
@ -141,7 +140,7 @@ QList<Vendor> DevicePlugin::supportedVendors() const
QList<Vendor> vendors;
foreach (const QJsonValue &vendorJson, m_metaData.value("vendors").toArray()) {
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);
}
return vendors;
@ -155,33 +154,6 @@ QList<DeviceClass> DevicePlugin::supportedDevices() const
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.
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
@ -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.setDisplayName(translateValue(m_metaData.value("name").toString(), pt.value("displayName").toString()));
paramType.setDisplayName(pt.value("displayName").toString());
// Set allowed values
@ -458,6 +430,11 @@ DeviceManager::DeviceError DevicePlugin::setConfigValue(const ParamTypeId &param
return DeviceManager::DeviceErrorNoError;
}
bool DevicePlugin::isBuiltIn() const
{
return m_metaData.value("builtIn").toBool();
}
/*! Returns a pointer to the \l{DeviceManager}.
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
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);
@ -593,7 +570,7 @@ void DevicePlugin::loadMetaData()
DeviceClass deviceClass(pluginId(), vendorId, deviceClassObject.value("id").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
DeviceClass::CreateMethods createMethods;
@ -665,7 +642,7 @@ void DevicePlugin::loadMetaData()
deviceClass.setSetupMethod(setupMethod);
// Read pairing info
deviceClass.setPairingInfo(translateValue(m_metaData.value("name").toString(), deviceClassObject.value("pairingInfo").toString()));
deviceClass.setPairingInfo(deviceClassObject.value("pairingInfo").toString());
// Read basic tags
QList<DeviceClass::BasicTag> basicTags;
@ -725,7 +702,7 @@ void DevicePlugin::loadMetaData()
StateType stateType(st.value("id").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.setType(t);
QPair<bool, Types::Unit> unitVerification = loadAndVerifyUnit(st.value("unit").toString());
@ -775,9 +752,9 @@ void DevicePlugin::loadMetaData()
eventType.setRuleRelevant(st.value("eventRuleRelevant").toBool());
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.setDisplayName(translateValue(m_metaData.value("name").toString(), st.value("displayName").toString()));
paramType.setDisplayName(st.value("displayName").toString());
paramType.setAllowedValues(stateType.possibleValues());
paramType.setDefaultValue(stateType.defaultValue());
paramType.setMinValue(stateType.minValue());
@ -791,7 +768,7 @@ void DevicePlugin::loadMetaData()
if (writableState) {
ActionType actionType(ActionTypeId(stateType.id().toString()));
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.setParamTypes(QList<ParamType>() << paramType);
actionTypes.append(actionType);
@ -821,7 +798,7 @@ void DevicePlugin::loadMetaData()
ActionType actionType(at.value("id").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++);
QPair<bool, QList<ParamType> > paramVerification = parseParamTypes(at.value("paramTypes").toArray());
@ -859,7 +836,7 @@ void DevicePlugin::loadMetaData()
EventType eventType(et.value("id").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++);
if (et.contains("ruleRelevant"))
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
{
if (unitString.isEmpty())

View File

@ -63,9 +63,6 @@ public:
QList<Vendor> supportedVendors() const;
QList<DeviceClass> supportedDevices() const;
QTranslator *translator();
bool setLocale(const QLocale &locale);
virtual void startMonitoringAutoDevices();
virtual DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params);
@ -85,6 +82,8 @@ public:
QVariant configValue(const ParamTypeId &paramTypeId) const;
DeviceManager::DeviceError setConfigValue(const ParamTypeId &paramTypeId, const QVariant &value);
bool isBuiltIn() const;
signals:
void emitEvent(const Event &event);
void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &deviceDescriptors);
@ -111,8 +110,6 @@ private:
// Returns <missingFields, unknownFields>
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
QPair<bool, Types::Unit> loadAndVerifyUnit(const QString &unitString) 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 QStringList generateInterfaceParentList(const QString &interface);
QTranslator *m_translator = nullptr;
DeviceManager *m_deviceManager = nullptr;
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";
}
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)
QDebug operator<<(QDebug &dbg, const DeviceClass &deviceClass);
#endif

View File

@ -74,3 +74,8 @@ void Vendor::setDisplayName(const QString &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;
void setDisplayName(const QString &displayName);
bool operator==(const Vendor &other) const;
private:
VendorId m_id;
QString m_name;

View File

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

View File

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

View File

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

View File

@ -131,7 +131,8 @@ int main(int argc, char *argv[])
"AWSTraffic",
"BluetoothServer",
"BluetoothServerTraffic",
"Mqtt"
"Mqtt",
"Translations"
};
QStringList loggingFiltersPlugins;
@ -145,7 +146,7 @@ int main(int argc, char *argv[])
// 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(), "-", 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": {
"Actions.ExecuteAction": {
@ -78,7 +78,7 @@
}
},
"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": {
},
"returns": {
@ -163,7 +163,7 @@
}
},
"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": {
"language": "String"
},
@ -492,14 +492,16 @@
}
},
"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": {
"o:locale": "String"
},
"returns": {
"authenticationRequired": "Bool",
"id": "Int",
"initialSetupRequired": "Bool",
"language": "String",
"locale": "String",
"name": "String",
"protocol version": "String",
"pushButtonAuthAvailable": "Bool",

View File

@ -35,6 +35,8 @@ private slots:
void testHandshake();
void testHandshakeLocale();
void testInitialSetup();
void testRevokeToken();
@ -131,7 +133,9 @@ void TestJSONRPC::initTestCase()
{
NymeaTestBase::initTestCase();
QLoggingCategory::setFilterRules("*.debug=false\n"
"JsonRpc*.debug=true");
// "JsonRpc*.debug=true\n"
"Translations.debug=true\n"
"Tests.debug=true");
}
void TestJSONRPC::testHandshake()
@ -170,6 +174,42 @@ void TestJSONRPC::testHandshake()
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()
{
foreach (const QString &user, NymeaCore::instance()->userManager()->users()) {