diff --git a/application/src/main/java/org/thingsboard/server/actors/shared/rulechain/RuleChainManager.java b/application/src/main/java/org/thingsboard/server/actors/shared/rulechain/RuleChainManager.java index 11ed5a3363..d349fec71d 100644 --- a/application/src/main/java/org/thingsboard/server/actors/shared/rulechain/RuleChainManager.java +++ b/application/src/main/java/org/thingsboard/server/actors/shared/rulechain/RuleChainManager.java @@ -50,7 +50,7 @@ public abstract class RuleChainManager extends EntityActorsManager featureType = getFeatureType(exchange.advanced().getRequest()); if (!featureType.isPresent()) { log.trace("Missing feature type parameter"); @@ -108,12 +102,6 @@ public class CoapTransportResource extends CoapResource { @Override public void handlePOST(CoapExchange exchange) { - if (transportContext.getQuotaService().isQuotaExceeded(exchange.getSourceAddress().getHostAddress())) { - log.warn("CoAP Quota exceeded for [{}:{}] . Disconnect", exchange.getSourceAddress().getHostAddress(), exchange.getSourcePort()); - exchange.respond(ResponseCode.BAD_REQUEST); - return; - } - Optional featureType = getFeatureType(exchange.advanced().getRequest()); if (!featureType.isPresent()) { log.trace("Missing feature type parameter"); diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java index 278ca6d8c5..c0bd7f9c1b 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java @@ -27,8 +27,6 @@ import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; import org.thingsboard.server.common.transport.SessionMsgProcessor; import org.thingsboard.server.common.transport.auth.DeviceAuthService; -import org.thingsboard.server.common.transport.quota.QuotaService; -import org.thingsboard.server.common.transport.quota.host.HostRequestsQuotaService; import org.thingsboard.server.transport.coap.adaptors.CoapTransportAdaptor; import javax.annotation.PostConstruct; diff --git a/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java b/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java index b40fbc194f..18458d13ad 100644 --- a/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java +++ b/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java @@ -75,9 +75,6 @@ public class DeviceApiController { @RequestParam(value = "sharedKeys", required = false, defaultValue = "") String sharedKeys, HttpServletRequest httpRequest) { DeferredResult responseWriter = new DeferredResult<>(); - if (quotaExceeded(httpRequest, responseWriter)) { - return responseWriter; - } transportContext.getTransportService().process(ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), new DeviceAuthCallback(transportContext, responseWriter, sessionInfo -> { GetAttributeRequestMsg.Builder request = GetAttributeRequestMsg.newBuilder().setRequestId(0); @@ -100,9 +97,6 @@ public class DeviceApiController { public DeferredResult postDeviceAttributes(@PathVariable("deviceToken") String deviceToken, @RequestBody String json, HttpServletRequest request) { DeferredResult responseWriter = new DeferredResult<>(); - if (quotaExceeded(request, responseWriter)) { - return responseWriter; - } transportContext.getTransportService().process(ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), new DeviceAuthCallback(transportContext, responseWriter, sessionInfo -> { TransportService transportService = transportContext.getTransportService(); @@ -116,9 +110,6 @@ public class DeviceApiController { public DeferredResult postTelemetry(@PathVariable("deviceToken") String deviceToken, @RequestBody String json, HttpServletRequest request) { DeferredResult responseWriter = new DeferredResult(); - if (quotaExceeded(request, responseWriter)) { - return responseWriter; - } transportContext.getTransportService().process(ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), new DeviceAuthCallback(transportContext, responseWriter, sessionInfo -> { TransportService transportService = transportContext.getTransportService(); @@ -133,9 +124,6 @@ public class DeviceApiController { @RequestParam(value = "timeout", required = false, defaultValue = "0") long timeout, HttpServletRequest httpRequest) { DeferredResult responseWriter = new DeferredResult<>(); - if (quotaExceeded(httpRequest, responseWriter)) { - return responseWriter; - } transportContext.getTransportService().process(ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), new DeviceAuthCallback(transportContext, responseWriter, sessionInfo -> { TransportService transportService = transportContext.getTransportService(); @@ -153,9 +141,6 @@ public class DeviceApiController { @PathVariable("requestId") Integer requestId, @RequestBody String json, HttpServletRequest request) { DeferredResult responseWriter = new DeferredResult(); - if (quotaExceeded(request, responseWriter)) { - return responseWriter; - } transportContext.getTransportService().process(ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), new DeviceAuthCallback(transportContext, responseWriter, sessionInfo -> { TransportService transportService = transportContext.getTransportService(); @@ -168,9 +153,6 @@ public class DeviceApiController { public DeferredResult postRpcRequest(@PathVariable("deviceToken") String deviceToken, @RequestBody String json, HttpServletRequest httpRequest) { DeferredResult responseWriter = new DeferredResult(); - if (quotaExceeded(httpRequest, responseWriter)) { - return responseWriter; - } transportContext.getTransportService().process(ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), new DeviceAuthCallback(transportContext, responseWriter, sessionInfo -> { JsonObject request = new JsonParser().parse(json).getAsJsonObject(); @@ -189,9 +171,6 @@ public class DeviceApiController { @RequestParam(value = "timeout", required = false, defaultValue = "0") long timeout, HttpServletRequest httpRequest) { DeferredResult responseWriter = new DeferredResult<>(); - if (quotaExceeded(httpRequest, responseWriter)) { - return responseWriter; - } transportContext.getTransportService().process(ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), new DeviceAuthCallback(transportContext, responseWriter, sessionInfo -> { TransportService transportService = transportContext.getTransportService(); @@ -204,16 +183,6 @@ public class DeviceApiController { return responseWriter; } - private boolean quotaExceeded(HttpServletRequest request, DeferredResult responseWriter) { - if (transportContext.getQuotaService().isQuotaExceeded(request.getRemoteAddr())) { - log.warn("REST Quota exceeded for [{}] . Disconnect", request.getRemoteAddr()); - responseWriter.setResult(new ResponseEntity<>(HttpStatus.BANDWIDTH_LIMIT_EXCEEDED)); - return true; - } else { - return false; - } - } - private static class DeviceAuthCallback implements TransportServiceCallback { private final TransportContext transportContext; private final DeferredResult responseWriter; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportContext.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportContext.java index 538daa1f9c..184ac49c25 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportContext.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportContext.java @@ -28,7 +28,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; import org.thingsboard.server.common.transport.TransportContext; import org.thingsboard.server.common.transport.TransportService; -import org.thingsboard.server.common.transport.quota.host.HostRequestsQuotaService; import org.thingsboard.server.kafka.TbNodeIdProvider; import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java index 46a890f19e..da8b3a62ca 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java @@ -42,7 +42,6 @@ import org.thingsboard.server.common.transport.SessionMsgListener; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportServiceCallback; import org.thingsboard.server.common.transport.adaptor.AdaptorException; -import org.thingsboard.server.common.transport.quota.QuotaService; import org.thingsboard.server.common.msg.EncryptionUtil; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto; @@ -92,7 +91,6 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement private final MqttTransportContext context; private final MqttTransportAdaptor adaptor; private final TransportService transportService; - private final QuotaService quotaService; private final SslHandler sslHandler; private final ConcurrentMap mqttQoSMap; @@ -106,7 +104,6 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement this.context = context; this.transportService = context.getTransportService(); this.adaptor = context.getAdaptor(); - this.quotaService = context.getQuotaService(); this.sslHandler = context.getSslHandler(); this.mqttQoSMap = new ConcurrentHashMap<>(); this.deviceSessionCtx = new DeviceSessionCtx(sessionId, mqttQoSMap); @@ -129,13 +126,6 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement processDisconnect(ctx); return; } - - if (quotaService.isQuotaExceeded(address.getHostName())) { - log.warn("MQTT Quota exceeded for [{}:{}] . Disconnect", address.getHostName(), address.getPort()); - processDisconnect(ctx); - return; - } - deviceSessionCtx.setChannel(ctx); switch (msg.fixedHeader().messageType()) { case CONNECT: diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportContext.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportContext.java index ab429829e4..58aaa78989 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportContext.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportContext.java @@ -20,7 +20,6 @@ import lombok.Data; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.thingsboard.server.common.transport.quota.host.HostRequestsQuotaService; import org.thingsboard.server.kafka.TbNodeIdProvider; import javax.annotation.PostConstruct; @@ -43,9 +42,6 @@ public class TransportContext { @Autowired private TbNodeIdProvider nodeIdProvider; - @Autowired(required = false) - private HostRequestsQuotaService quotaService; - @Getter private ExecutorService executor; diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/AbstractQuotaService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/AbstractQuotaService.java deleted file mode 100644 index 9d7bd1720c..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/AbstractQuotaService.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota; - -import org.thingsboard.server.common.transport.quota.inmemory.IntervalRegistryCleaner; -import org.thingsboard.server.common.transport.quota.inmemory.IntervalRegistryLogger; -import org.thingsboard.server.common.transport.quota.inmemory.KeyBasedIntervalRegistry; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - -public class AbstractQuotaService implements QuotaService { - - private final KeyBasedIntervalRegistry requestRegistry; - private final RequestLimitPolicy requestsPolicy; - private final IntervalRegistryCleaner registryCleaner; - private final IntervalRegistryLogger registryLogger; - private final boolean enabled; - - public AbstractQuotaService(KeyBasedIntervalRegistry requestRegistry, RequestLimitPolicy requestsPolicy, - IntervalRegistryCleaner registryCleaner, IntervalRegistryLogger registryLogger, - boolean enabled) { - this.requestRegistry = requestRegistry; - this.requestsPolicy = requestsPolicy; - this.registryCleaner = registryCleaner; - this.registryLogger = registryLogger; - this.enabled = enabled; - } - - @PostConstruct - public void init() { - if (enabled) { - registryCleaner.schedule(); - registryLogger.schedule(); - } - } - - @PreDestroy - public void close() { - if (enabled) { - registryCleaner.stop(); - registryLogger.stop(); - } - } - - @Override - public boolean isQuotaExceeded(String key) { - if (enabled) { - long count = requestRegistry.tick(key); - return !requestsPolicy.isValid(count); - } - return false; - } -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/Clock.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/Clock.java deleted file mode 100644 index dcc2d2306c..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/Clock.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota; - -/** - * @author Vitaliy Paromskiy - * @version 1.0 - */ -public final class Clock { - - private static long time = 0L; - - private Clock() { - } - - - public static long millis() { - return time == 0 ? System.currentTimeMillis() : time; - } - - public static void setMillis(long millis) { - time = millis; - } - - public static void shift(long delta) { - time += delta; - } - - public static void reset() { - time = 0; - } -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/QuotaService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/QuotaService.java deleted file mode 100644 index f841749049..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/QuotaService.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota; - -/** - * @author Vitaliy Paromskiy - * @version 1.0 - */ -public interface QuotaService { - - boolean isQuotaExceeded(String key); -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/RequestLimitPolicy.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/RequestLimitPolicy.java deleted file mode 100644 index 0ff1230b1c..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/RequestLimitPolicy.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota; - - -public abstract class RequestLimitPolicy { - - private final long limit; - - public RequestLimitPolicy(long limit) { - this.limit = limit; - } - - public boolean isValid(long currentValue) { - return currentValue <= limit; - } -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/host/HostIntervalRegistryCleaner.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/host/HostIntervalRegistryCleaner.java deleted file mode 100644 index ea75f5dc09..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/host/HostIntervalRegistryCleaner.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.host; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import org.thingsboard.server.common.transport.quota.inmemory.IntervalRegistryCleaner; - -@Component -public class HostIntervalRegistryCleaner extends IntervalRegistryCleaner { - - public HostIntervalRegistryCleaner(HostRequestIntervalRegistry intervalRegistry, - @Value("${quota.host.cleanPeriodMs}") long cleanPeriodMs) { - super(intervalRegistry, cleanPeriodMs); - } -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/host/HostIntervalRegistryLogger.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/host/HostIntervalRegistryLogger.java deleted file mode 100644 index 65767f1648..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/host/HostIntervalRegistryLogger.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.host; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import org.thingsboard.server.common.transport.quota.inmemory.IntervalRegistryLogger; - -import java.util.Map; -import java.util.concurrent.TimeUnit; - -@Component -@Slf4j -public class HostIntervalRegistryLogger extends IntervalRegistryLogger { - - private final long logIntervalMin; - - public HostIntervalRegistryLogger(@Value("${quota.host.log.topSize}") int topSize, - @Value("${quota.host.log.intervalMin}") long logIntervalMin, - HostRequestIntervalRegistry intervalRegistry) { - super(topSize, logIntervalMin, intervalRegistry); - this.logIntervalMin = logIntervalMin; - } - - protected void log(Map top, int uniqHosts, long requestsCount) { - long rps = requestsCount / TimeUnit.MINUTES.toSeconds(logIntervalMin); - StringBuilder builder = new StringBuilder("Quota Statistic : "); - builder.append("uniqHosts : ").append(uniqHosts).append("; "); - builder.append("requestsCount : ").append(requestsCount).append("; "); - builder.append("RPS : ").append(rps).append(" "); - builder.append("top -> "); - for (Map.Entry host : top.entrySet()) { - builder.append(host.getKey()).append(" : ").append(host.getValue()).append("; "); - } - - log.info(builder.toString()); - } -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/host/HostRequestIntervalRegistry.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/host/HostRequestIntervalRegistry.java deleted file mode 100644 index 9b3b4614e4..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/host/HostRequestIntervalRegistry.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.host; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import org.thingsboard.server.common.transport.quota.inmemory.KeyBasedIntervalRegistry; - -/** - * @author Vitaliy Paromskiy - * @version 1.0 - */ -@Component -@Slf4j -public class HostRequestIntervalRegistry extends KeyBasedIntervalRegistry { - - public HostRequestIntervalRegistry(@Value("${quota.host.intervalMs}") long intervalDurationMs, - @Value("${quota.host.ttlMs}") long ttlMs, - @Value("${quota.host.whitelist}") String whiteList, - @Value("${quota.host.blacklist}") String blackList) { - super(intervalDurationMs, ttlMs, whiteList, blackList, "host"); - } -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/host/HostRequestLimitPolicy.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/host/HostRequestLimitPolicy.java deleted file mode 100644 index eeef9247e6..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/host/HostRequestLimitPolicy.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.host; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import org.thingsboard.server.common.transport.quota.RequestLimitPolicy; - -/** - * @author Vitaliy Paromskiy - * @version 1.0 - */ -@Component -public class HostRequestLimitPolicy extends RequestLimitPolicy { - - public HostRequestLimitPolicy(@Value("${quota.host.limit}") long limit) { - super(limit); - } - -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/host/HostRequestsQuotaService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/host/HostRequestsQuotaService.java deleted file mode 100644 index 69342b538b..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/host/HostRequestsQuotaService.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.host; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import org.thingsboard.server.common.transport.quota.AbstractQuotaService; - -/** - * @author Vitaliy Paromskiy - * @version 1.0 - */ -@Service -@Slf4j -public class HostRequestsQuotaService extends AbstractQuotaService { - - public HostRequestsQuotaService(HostRequestIntervalRegistry requestRegistry, HostRequestLimitPolicy requestsPolicy, - HostIntervalRegistryCleaner registryCleaner, HostIntervalRegistryLogger registryLogger, - @Value("${quota.host.enabled}") boolean enabled) { - super(requestRegistry, requestsPolicy, registryCleaner, registryLogger, enabled); - } - -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalCount.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalCount.java deleted file mode 100644 index 0ac6c9b5e2..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalCount.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.inmemory; - - -import org.thingsboard.server.common.transport.quota.Clock; - -import java.util.concurrent.atomic.LongAdder; - -/** - * @author Vitaliy Paromskiy - * @version 1.0 - */ -public class IntervalCount { - - private final LongAdder adder = new LongAdder(); - private final long intervalDurationMs; - private volatile long startTime; - private volatile long lastTickTime; - - public IntervalCount(long intervalDurationMs) { - this.intervalDurationMs = intervalDurationMs; - startTime = Clock.millis(); - } - - public long resetIfExpiredAndTick() { - if (isExpired()) { - reset(); - } - tick(); - return adder.sum(); - } - - public long silenceDuration() { - return Clock.millis() - lastTickTime; - } - - public long getCount() { - return adder.sum(); - } - - private void tick() { - adder.add(1); - lastTickTime = Clock.millis(); - } - - private void reset() { - adder.reset(); - startTime = Clock.millis(); - } - - private boolean isExpired() { - return (Clock.millis() - startTime) > intervalDurationMs; - } -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalRegistryCleaner.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalRegistryCleaner.java deleted file mode 100644 index 0c510ff815..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalRegistryCleaner.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.inmemory; - -import lombok.extern.slf4j.Slf4j; - -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -/** - * @author Vitaliy Paromskiy - * @version 1.0 - */ -@Slf4j -public abstract class IntervalRegistryCleaner { - - private final KeyBasedIntervalRegistry intervalRegistry; - private final long cleanPeriodMs; - private ScheduledExecutorService executor; - - public IntervalRegistryCleaner(KeyBasedIntervalRegistry intervalRegistry, long cleanPeriodMs) { - this.intervalRegistry = intervalRegistry; - this.cleanPeriodMs = cleanPeriodMs; - } - - public void schedule() { - if (executor != null) { - throw new IllegalStateException("Registry Cleaner already scheduled"); - } - executor = Executors.newSingleThreadScheduledExecutor(); - executor.scheduleAtFixedRate(this::clean, cleanPeriodMs, cleanPeriodMs, TimeUnit.MILLISECONDS); - } - - public void stop() { - if (executor != null) { - executor.shutdown(); - } - } - - public void clean() { - try { - intervalRegistry.clean(); - } catch (RuntimeException ex) { - log.error("Could not clear Interval Registry", ex); - } - } - -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalRegistryLogger.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalRegistryLogger.java deleted file mode 100644 index 30399a140f..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalRegistryLogger.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.inmemory; - -import com.google.common.collect.MinMaxPriorityQueue; -import lombok.extern.slf4j.Slf4j; - -import java.util.Comparator; -import java.util.Map; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * @author Vitaliy Paromskiy - * @version 1.0 - */ -@Slf4j -public abstract class IntervalRegistryLogger { - - private final int topSize; - private final KeyBasedIntervalRegistry intervalRegistry; - private final long logIntervalMin; - private ScheduledExecutorService executor; - - public IntervalRegistryLogger(int topSize, long logIntervalMin, KeyBasedIntervalRegistry intervalRegistry) { - this.topSize = topSize; - this.logIntervalMin = logIntervalMin; - this.intervalRegistry = intervalRegistry; - } - - public void schedule() { - if (executor != null) { - throw new IllegalStateException("Registry Cleaner already scheduled"); - } - executor = Executors.newSingleThreadScheduledExecutor(); - executor.scheduleAtFixedRate(this::logStatistic, logIntervalMin, logIntervalMin, TimeUnit.MINUTES); - } - - public void stop() { - if (executor != null) { - executor.shutdown(); - } - } - - public void logStatistic() { - Map registryContent = intervalRegistry.getContent(); - int uniqHosts = registryContent.size(); - long requestsCount = registryContent.values().stream().mapToLong(i -> i).sum(); - Map top = getTopElements(registryContent); - log(top, uniqHosts, requestsCount); - } - - protected Map getTopElements(Map countMap) { - MinMaxPriorityQueue> topQueue = MinMaxPriorityQueue - .orderedBy(Comparator.comparing((Function, Long>) Map.Entry::getValue).reversed()) - .maximumSize(topSize) - .create(countMap.entrySet()); - - return topQueue.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - } - - protected abstract void log(Map top, int uniqHosts, long requestsCount); -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/KeyBasedIntervalRegistry.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/KeyBasedIntervalRegistry.java deleted file mode 100644 index 0b0fef85e5..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/KeyBasedIntervalRegistry.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.inmemory; - -import com.google.common.collect.Sets; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; - -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -@Slf4j -public abstract class KeyBasedIntervalRegistry { - - private final Map hostCounts = new ConcurrentHashMap<>(); - private final long intervalDurationMs; - private final long ttlMs; - private final Set whiteList; - private final Set blackList; - - public KeyBasedIntervalRegistry(long intervalDurationMs, long ttlMs, String whiteList, String blackList, String name) { - this.intervalDurationMs = intervalDurationMs; - this.ttlMs = ttlMs; - this.whiteList = Sets.newHashSet(StringUtils.split(whiteList, ',')); - this.blackList = Sets.newHashSet(StringUtils.split(blackList, ',')); - validate(name); - } - - private void validate(String name) { - if (ttlMs < intervalDurationMs) { - log.warn("TTL for {} IntervalRegistry [{}] smaller than interval duration [{}]", name, ttlMs, intervalDurationMs); - } - log.info("Start {} KeyBasedIntervalRegistry with whitelist {}", name, whiteList); - log.info("Start {} KeyBasedIntervalRegistry with blacklist {}", name, blackList); - } - - public long tick(String clientHostId) { - IntervalCount intervalCount = hostCounts.computeIfAbsent(clientHostId, s -> new IntervalCount(intervalDurationMs)); - long currentCount = intervalCount.resetIfExpiredAndTick(); - if (whiteList.contains(clientHostId)) { - return 0; - } else if (blackList.contains(clientHostId)) { - return Long.MAX_VALUE; - } - return currentCount; - } - - public void clean() { - hostCounts.entrySet().removeIf(entry -> entry.getValue().silenceDuration() > ttlMs); - } - - public Map getContent() { - return hostCounts.entrySet().stream() - .collect(Collectors.toMap( - Map.Entry::getKey, - interval -> interval.getValue().getCount())); - } -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/tenant/TenantIntervalRegistryCleaner.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/tenant/TenantIntervalRegistryCleaner.java deleted file mode 100644 index 47b427840a..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/tenant/TenantIntervalRegistryCleaner.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.tenant; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.stereotype.Component; -import org.thingsboard.server.common.transport.quota.inmemory.IntervalRegistryCleaner; - -@Component -@ConditionalOnProperty(prefix = "quota.rule.tenant", value = "enabled", havingValue = "true", matchIfMissing = false) -public class TenantIntervalRegistryCleaner extends IntervalRegistryCleaner { - - public TenantIntervalRegistryCleaner(TenantMsgsIntervalRegistry intervalRegistry, - @Value("${quota.rule.tenant.cleanPeriodMs}") long cleanPeriodMs) { - super(intervalRegistry, cleanPeriodMs); - } -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/tenant/TenantIntervalRegistryLogger.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/tenant/TenantIntervalRegistryLogger.java deleted file mode 100644 index 3bdcf93d07..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/tenant/TenantIntervalRegistryLogger.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.tenant; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.stereotype.Component; -import org.thingsboard.server.common.transport.quota.inmemory.IntervalRegistryLogger; - -import java.util.Map; -import java.util.concurrent.TimeUnit; - -@Slf4j -@Component -@ConditionalOnProperty(prefix = "quota.rule.tenant", value = "enabled", havingValue = "true", matchIfMissing = false) -public class TenantIntervalRegistryLogger extends IntervalRegistryLogger { - - private final long logIntervalMin; - - public TenantIntervalRegistryLogger(@Value("${quota.rule.tenant.log.topSize}") int topSize, - @Value("${quota.rule.tenant.log.intervalMin}") long logIntervalMin, - TenantMsgsIntervalRegistry intervalRegistry) { - super(topSize, logIntervalMin, intervalRegistry); - this.logIntervalMin = logIntervalMin; - } - - protected void log(Map top, int uniqHosts, long requestsCount) { - long rps = requestsCount / TimeUnit.MINUTES.toSeconds(logIntervalMin); - StringBuilder builder = new StringBuilder("Tenant Quota Statistic : "); - builder.append("uniqTenants : ").append(uniqHosts).append("; "); - builder.append("requestsCount : ").append(requestsCount).append("; "); - builder.append("RPS : ").append(rps).append(" "); - builder.append("top -> "); - for (Map.Entry host : top.entrySet()) { - builder.append(host.getKey()).append(" : ").append(host.getValue()).append("; "); - } - - log.info(builder.toString()); - } -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/tenant/TenantMsgsIntervalRegistry.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/tenant/TenantMsgsIntervalRegistry.java deleted file mode 100644 index 3402e62472..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/tenant/TenantMsgsIntervalRegistry.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.tenant; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.stereotype.Component; -import org.thingsboard.server.common.transport.quota.inmemory.KeyBasedIntervalRegistry; - -@Component -@ConditionalOnProperty(prefix = "quota.rule.tenant", value = "enabled", havingValue = "true", matchIfMissing = false) -public class TenantMsgsIntervalRegistry extends KeyBasedIntervalRegistry { - - public TenantMsgsIntervalRegistry(@Value("${quota.rule.tenant.intervalMs}") long intervalDurationMs, - @Value("${quota.rule.tenant.ttlMs}") long ttlMs, - @Value("${quota.rule.tenant.whitelist}") String whiteList, - @Value("${quota.rule.tenant.blacklist}") String blackList) { - super(intervalDurationMs, ttlMs, whiteList, blackList, "Rule Tenant"); - } -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/tenant/TenantQuotaService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/tenant/TenantQuotaService.java deleted file mode 100644 index 875a666a28..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/tenant/TenantQuotaService.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.tenant; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.stereotype.Component; -import org.thingsboard.server.common.transport.quota.AbstractQuotaService; - -@Component -@ConditionalOnProperty(prefix = "quota.rule.tenant", value = "enabled", havingValue = "true", matchIfMissing = false) -public class TenantQuotaService extends AbstractQuotaService { - - public TenantQuotaService(TenantMsgsIntervalRegistry requestRegistry, TenantRequestLimitPolicy requestsPolicy, - TenantIntervalRegistryCleaner registryCleaner, TenantIntervalRegistryLogger registryLogger, - @Value("${quota.rule.tenant.enabled}") boolean enabled) { - super(requestRegistry, requestsPolicy, registryCleaner, registryLogger, enabled); - } -} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/tenant/TenantRequestLimitPolicy.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/tenant/TenantRequestLimitPolicy.java deleted file mode 100644 index c5dfc40480..0000000000 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/quota/tenant/TenantRequestLimitPolicy.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.tenant; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.stereotype.Component; -import org.thingsboard.server.common.transport.quota.RequestLimitPolicy; - -@Component -@ConditionalOnProperty(prefix = "quota.rule.tenant", value = "enabled", havingValue = "true", matchIfMissing = false) -public class TenantRequestLimitPolicy extends RequestLimitPolicy { - - public TenantRequestLimitPolicy(@Value("${quota.rule.tenant.limit}") long limit) { - super(limit); - } -} diff --git a/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/ClockTest.java b/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/ClockTest.java deleted file mode 100644 index 403bdc65b3..0000000000 --- a/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/ClockTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * @author Vitaliy Paromskiy - * @version 1.0 - */ -public class ClockTest { - - @Before - public void init() { - Clock.reset(); - } - - @After - public void clear() { - Clock.reset(); - } - - @Test - public void defaultClockUseSystemTime() { - assertFalse(Clock.millis() > System.currentTimeMillis()); - } - - @Test - public void timeCanBeSet() { - Clock.setMillis(100L); - assertEquals(100L, Clock.millis()); - } - - @Test - public void clockCanBeReseted() { - Clock.setMillis(100L); - assertEquals(100L, Clock.millis()); - Clock.reset(); - assertFalse(Clock.millis() > System.currentTimeMillis()); - } - - @Test - public void timeIsShifted() { - Clock.setMillis(100L); - Clock.shift(50L); - assertEquals(150L, Clock.millis()); - } - -} \ No newline at end of file diff --git a/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/HostRequestLimitPolicyTest.java b/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/HostRequestLimitPolicyTest.java deleted file mode 100644 index 07e03ef0ac..0000000000 --- a/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/HostRequestLimitPolicyTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota; - -import org.junit.Test; -import org.thingsboard.server.common.transport.quota.host.HostRequestLimitPolicy; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * @author Vitaliy Paromskiy - * @version 1.0 - */ -public class HostRequestLimitPolicyTest { - - private HostRequestLimitPolicy limitPolicy = new HostRequestLimitPolicy(10L); - - @Test - public void ifCurrentValueLessThenLimitItIsValid() { - assertTrue(limitPolicy.isValid(9)); - } - - @Test - public void ifCurrentValueEqualsToLimitItIsValid() { - assertTrue(limitPolicy.isValid(10)); - } - - @Test - public void ifCurrentValueGreaterThenLimitItIsValid() { - assertFalse(limitPolicy.isValid(11)); - } - -} \ No newline at end of file diff --git a/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/HostRequestsQuotaServiceTest.java b/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/HostRequestsQuotaServiceTest.java deleted file mode 100644 index 37441e9d41..0000000000 --- a/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/HostRequestsQuotaServiceTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota; - -import org.junit.Before; -import org.junit.Test; -import org.thingsboard.server.common.transport.quota.host.HostIntervalRegistryCleaner; -import org.thingsboard.server.common.transport.quota.host.HostIntervalRegistryLogger; -import org.thingsboard.server.common.transport.quota.host.HostRequestIntervalRegistry; -import org.thingsboard.server.common.transport.quota.host.HostRequestLimitPolicy; -import org.thingsboard.server.common.transport.quota.host.HostRequestsQuotaService; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.*; - -/** - * @author Vitaliy Paromskiy - * @version 1.0 - */ -public class HostRequestsQuotaServiceTest { - - private HostRequestsQuotaService quotaService; - - private HostRequestIntervalRegistry requestRegistry = mock(HostRequestIntervalRegistry.class); - private HostRequestLimitPolicy requestsPolicy = mock(HostRequestLimitPolicy.class); - private HostIntervalRegistryCleaner registryCleaner = mock(HostIntervalRegistryCleaner.class); - private HostIntervalRegistryLogger registryLogger = mock(HostIntervalRegistryLogger.class); - - @Before - public void init() { - quotaService = new HostRequestsQuotaService(requestRegistry, requestsPolicy, registryCleaner, registryLogger, true); - } - - @Test - public void quotaExceededIfRequestCountBiggerThanAllowed() { - when(requestRegistry.tick("key")).thenReturn(10L); - when(requestsPolicy.isValid(10L)).thenReturn(false); - - assertTrue(quotaService.isQuotaExceeded("key")); - - verify(requestRegistry).tick("key"); - verify(requestsPolicy).isValid(10L); - verifyNoMoreInteractions(requestRegistry, requestsPolicy); - } - - @Test - public void quotaNotExceededIfRequestCountLessThanAllowed() { - when(requestRegistry.tick("key")).thenReturn(10L); - when(requestsPolicy.isValid(10L)).thenReturn(true); - - assertFalse(quotaService.isQuotaExceeded("key")); - - verify(requestRegistry).tick("key"); - verify(requestsPolicy).isValid(10L); - verifyNoMoreInteractions(requestRegistry, requestsPolicy); - } - - @Test - public void serviceCanBeDisabled() { - quotaService = new HostRequestsQuotaService(requestRegistry, requestsPolicy, registryCleaner, registryLogger, false); - assertFalse(quotaService.isQuotaExceeded("key")); - verifyNoMoreInteractions(requestRegistry, requestsPolicy); - } -} \ No newline at end of file diff --git a/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/inmemory/HostRequestIntervalRegistryTest.java b/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/inmemory/HostRequestIntervalRegistryTest.java deleted file mode 100644 index b49dd00bc9..0000000000 --- a/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/inmemory/HostRequestIntervalRegistryTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.inmemory; - -import org.junit.Before; -import org.junit.Test; -import org.thingsboard.server.common.transport.quota.host.HostRequestIntervalRegistry; - -import static org.junit.Assert.assertEquals; - -/** - * @author Vitaliy Paromskiy - * @version 1.0 - */ -public class HostRequestIntervalRegistryTest { - - private HostRequestIntervalRegistry registry; - - @Before - public void init() { - registry = new HostRequestIntervalRegistry(10000L, 100L,"g1,g2", "b1"); - } - - @Test - public void newHostCreateNewInterval() { - assertEquals(1L, registry.tick("host1")); - } - - @Test - public void existingHostUpdated() { - registry.tick("aaa"); - assertEquals(1L, registry.tick("bbb")); - assertEquals(2L, registry.tick("aaa")); - } - - @Test - public void expiredIntervalsCleaned() throws InterruptedException { - registry.tick("aaa"); - Thread.sleep(150L); - registry.tick("bbb"); - registry.clean(); - assertEquals(1L, registry.tick("aaa")); - assertEquals(2L, registry.tick("bbb")); - } - - @Test - public void domainFromWhitelistNotCounted(){ - assertEquals(0L, registry.tick("g1")); - assertEquals(0L, registry.tick("g1")); - assertEquals(0L, registry.tick("g2")); - } - - @Test - public void domainFromBlackListReturnMaxValue(){ - assertEquals(Long.MAX_VALUE, registry.tick("b1")); - assertEquals(Long.MAX_VALUE, registry.tick("b1")); - } - - @Test - public void emptyWhitelistParsedOk(){ - registry = new HostRequestIntervalRegistry(10000L, 100L,"", "b1"); - assertEquals(1L, registry.tick("aaa")); - } - - @Test - public void emptyBlacklistParsedOk(){ - registry = new HostRequestIntervalRegistry(10000L, 100L,"", ""); - assertEquals(1L, registry.tick("aaa")); - } -} \ No newline at end of file diff --git a/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalCountTest.java b/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalCountTest.java deleted file mode 100644 index 4fdce61fd3..0000000000 --- a/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalCountTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.inmemory; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.thingsboard.server.common.transport.quota.Clock; - -import static org.junit.Assert.assertEquals; - -/** - * @author Vitaliy Paromskiy - * @version 1.0 - */ -public class IntervalCountTest { - - @Before - public void init() { - Clock.setMillis(1000L); - } - - @After - public void clear() { - Clock.reset(); - } - - @Test - public void ticksInSameIntervalAreSummed() { - IntervalCount intervalCount = new IntervalCount(100L); - assertEquals(1L, intervalCount.resetIfExpiredAndTick()); - Clock.shift(100); - assertEquals(2L, intervalCount.resetIfExpiredAndTick()); - } - - @Test - public void oldDataCleanedWhenIntervalExpired() { - IntervalCount intervalCount = new IntervalCount(100L); - assertEquals(1L, intervalCount.resetIfExpiredAndTick()); - Clock.shift(101); - assertEquals(1L, intervalCount.resetIfExpiredAndTick()); - } - - @Test - public void silenceDurationCalculatedFromLastTick() { - IntervalCount intervalCount = new IntervalCount(100L); - assertEquals(1L, intervalCount.resetIfExpiredAndTick()); - Clock.shift(10L); - assertEquals(10L, intervalCount.silenceDuration()); - } - -} \ No newline at end of file diff --git a/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalRegistryLoggerTest.java b/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalRegistryLoggerTest.java deleted file mode 100644 index 6e51420cd5..0000000000 --- a/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalRegistryLoggerTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright © 2016-2018 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.transport.quota.inmemory; - -import com.google.common.collect.ImmutableMap; -import org.junit.Before; -import org.junit.Test; -import org.thingsboard.server.common.transport.quota.host.HostIntervalRegistryLogger; -import org.thingsboard.server.common.transport.quota.host.HostRequestIntervalRegistry; - -import java.util.Collections; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; - -/** - * @author Vitaliy Paromskiy - * @version 1.0 - */ -public class IntervalRegistryLoggerTest { - - private IntervalRegistryLogger logger; - - private HostRequestIntervalRegistry requestRegistry = mock(HostRequestIntervalRegistry.class); - - @Before - public void init() { - logger = new HostIntervalRegistryLogger(3, 10, requestRegistry); - } - - @Test - public void onlyMaxHostsCollected() { - Map map = ImmutableMap.of("a", 8L, "b", 3L, "c", 1L, "d", 3L); - Map actual = logger.getTopElements(map); - Map expected = ImmutableMap.of("a", 8L, "b", 3L, "d", 3L); - - assertEquals(expected, actual); - } - - @Test - public void emptyMapProcessedCorrectly() { - Map map = Collections.emptyMap(); - Map actual = logger.getTopElements(map); - Map expected = Collections.emptyMap(); - - assertEquals(expected, actual); - } - -} \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsServiceImpl.java index 4b25f2b38a..101bff2bdd 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsServiceImpl.java @@ -62,15 +62,15 @@ public class DeviceCredentialsServiceImpl implements DeviceCredentialsService { @Override @CacheEvict(cacheNames = DEVICE_CREDENTIALS_CACHE, keyGenerator="previousDeviceCredentialsId", beforeInvocation = true) public DeviceCredentials updateDeviceCredentials(DeviceCredentials deviceCredentials) { - return saveOrUpdare(deviceCredentials); + return saveOrUpdate(deviceCredentials); } @Override public DeviceCredentials createDeviceCredentials(DeviceCredentials deviceCredentials) { - return saveOrUpdare(deviceCredentials); + return saveOrUpdate(deviceCredentials); } - private DeviceCredentials saveOrUpdare(DeviceCredentials deviceCredentials) { + private DeviceCredentials saveOrUpdate(DeviceCredentials deviceCredentials) { if (deviceCredentials.getCredentialsType() == DeviceCredentialsType.X509_CERTIFICATE) { formatCertData(deviceCredentials); } diff --git a/msa/docker/.env b/msa/docker/.env index 3d8faeb355..afcd91ced5 100644 --- a/msa/docker/.env +++ b/msa/docker/.env @@ -10,4 +10,4 @@ COAP_TRANSPORT_DOCKER_NAME=tb-coap-transport TB_VERSION=2.2.0-SNAPSHOT -KAFKA_TOPICS=js.eval.requests:100:1:delete --config=retention.ms=60000 --config=retention.bytes=1073741824,tb.transport.api.requests:30:1:delete --config=retention.ms=60000 --config=retention.bytes=1073741824,tb.rule-engine:30:1 +KAFKA_TOPICS=js.eval.requests:100:1:delete --config=retention.ms=60000 --config=segment.bytes=26214400 --config=retention.bytes=104857600,tb.transport.api.requests:30:1:delete --config=retention.ms=60000 --config=segment.bytes=26214400 --config=retention.bytes=104857600,tb.rule-engine:30:1 diff --git a/msa/docker/docker-compose.yml b/msa/docker/docker-compose.yml index e3b56ae425..5410533822 100644 --- a/msa/docker/docker-compose.yml +++ b/msa/docker/docker-compose.yml @@ -37,6 +37,7 @@ services: KAFKA_CREATE_TOPICS: "${KAFKA_TOPICS}" KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'false' KAFKA_LOG_RETENTION_BYTES: 1073741824 + KAFKA_LOG_SEGMENT_BYTES: 268435456 KAFKA_LOG_RETENTION_MS: 300000 KAFKA_LOG_CLEANUP_POLICY: delete depends_on: diff --git a/pom.xml b/pom.xml index 387e0eda42..00c9c28567 100755 --- a/pom.xml +++ b/pom.xml @@ -66,7 +66,7 @@ 1.1.0 4.1.22.Final 1.5.0 - 3.6.5 + 4.8.0 2.19.1 3.0.2 2.6.1 diff --git a/transport/coap/src/main/resources/tb-coap-transport.yml b/transport/coap/src/main/resources/tb-coap-transport.yml index 1790d822d2..30351b0bfa 100644 --- a/transport/coap/src/main/resources/tb-coap-transport.yml +++ b/transport/coap/src/main/resources/tb-coap-transport.yml @@ -23,27 +23,10 @@ transport: bind_address: "${COAP_BIND_ADDRESS:0.0.0.0}" bind_port: "${COAP_BIND_PORT:5683}" timeout: "${COAP_TIMEOUT:10000}" - -#Quota parameters -quota: - host: - # Max allowed number of API requests in interval for single host - limit: "${QUOTA_HOST_LIMIT:10000}" - # Interval duration - intervalMs: "${QUOTA_HOST_INTERVAL_MS:60000}" - # Maximum silence duration for host after which Host removed from QuotaService. Must be bigger than intervalMs - ttlMs: "${QUOTA_HOST_TTL_MS:60000}" - # Interval for scheduled task that cleans expired records. TTL is used for expiring - cleanPeriodMs: "${QUOTA_HOST_CLEAN_PERIOD_MS:300000}" - # Enable Host API Limits - enabled: "${QUOTA_HOST_ENABLED:true}" - # Array of whitelist hosts - whitelist: "${QUOTA_HOST_WHITELIST:localhost,127.0.0.1}" - # Array of blacklist hosts - blacklist: "${QUOTA_HOST_BLACKLIST:}" - log: - topSize: 10 - intervalMin: 2 + rate_limits: + enabled: "${TB_TRANSPORT_RATE_LIMITS_ENABLED:false}" + tenant: "${TB_TRANSPORT_RATE_LIMITS_TENANT:1000:1,20000:60}" + device: "${TB_TRANSPORT_RATE_LIMITS_DEVICE:10:1,300:60}" kafka: enabled: true diff --git a/transport/http/src/main/resources/tb-http-transport.yml b/transport/http/src/main/resources/tb-http-transport.yml index 65a1ad93a0..001e08abdc 100644 --- a/transport/http/src/main/resources/tb-http-transport.yml +++ b/transport/http/src/main/resources/tb-http-transport.yml @@ -24,27 +24,10 @@ server: transport: http: request_timeout: "${HTTP_REQUEST_TIMEOUT:60000}" - -#Quota parameters -quota: - host: - # Max allowed number of API requests in interval for single host - limit: "${QUOTA_HOST_LIMIT:10000}" - # Interval duration - intervalMs: "${QUOTA_HOST_INTERVAL_MS:60000}" - # Maximum silence duration for host after which Host removed from QuotaService. Must be bigger than intervalMs - ttlMs: "${QUOTA_HOST_TTL_MS:60000}" - # Interval for scheduled task that cleans expired records. TTL is used for expiring - cleanPeriodMs: "${QUOTA_HOST_CLEAN_PERIOD_MS:300000}" - # Enable Host API Limits - enabled: "${QUOTA_HOST_ENABLED:true}" - # Array of whitelist hosts - whitelist: "${QUOTA_HOST_WHITELIST:localhost,127.0.0.1}" - # Array of blacklist hosts - blacklist: "${QUOTA_HOST_BLACKLIST:}" - log: - topSize: 10 - intervalMin: 2 + rate_limits: + enabled: "${TB_TRANSPORT_RATE_LIMITS_ENABLED:false}" + tenant: "${TB_TRANSPORT_RATE_LIMITS_TENANT:1000:1,20000:60}" + device: "${TB_TRANSPORT_RATE_LIMITS_DEVICE:10:1,300:60}" kafka: enabled: true diff --git a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml index a0e86bb1c2..e37d14e874 100644 --- a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml +++ b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml @@ -51,27 +51,6 @@ transport: tenant: "${TB_TRANSPORT_RATE_LIMITS_TENANT:1000:1,20000:60}" device: "${TB_TRANSPORT_RATE_LIMITS_DEVICE:10:1,300:60}" -#Quota parameters -quota: - host: - # Max allowed number of API requests in interval for single host - limit: "${QUOTA_HOST_LIMIT:10000}" - # Interval duration - intervalMs: "${QUOTA_HOST_INTERVAL_MS:60000}" - # Maximum silence duration for host after which Host removed from QuotaService. Must be bigger than intervalMs - ttlMs: "${QUOTA_HOST_TTL_MS:60000}" - # Interval for scheduled task that cleans expired records. TTL is used for expiring - cleanPeriodMs: "${QUOTA_HOST_CLEAN_PERIOD_MS:300000}" - # Enable Host API Limits - enabled: "${QUOTA_HOST_ENABLED:true}" - # Array of whitelist hosts - whitelist: "${QUOTA_HOST_WHITELIST:localhost,127.0.0.1}" - # Array of blacklist hosts - blacklist: "${QUOTA_HOST_BLACKLIST:}" - log: - topSize: 10 - intervalMin: 2 - kafka: enabled: true bootstrap.servers: "${TB_KAFKA_SERVERS:localhost:9092}" diff --git a/ui/src/app/api/datasource.service.js b/ui/src/app/api/datasource.service.js index dd1a34f516..27921518b7 100644 --- a/ui/src/app/api/datasource.service.js +++ b/ui/src/app/api/datasource.service.js @@ -104,6 +104,7 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic var listeners = []; var datasourceType = datasourceSubscription.datasourceType; var datasourceData = {}; + var dataSourceOrigData = {}; var dataKeys = {}; var subscribers = []; var history = datasourceSubscription.subscriptionTimewindow && @@ -140,7 +141,7 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic } } else { if (dataKey.postFuncBody && !dataKey.postFunc) { - dataKey.postFunc = new Function("time", "value", "prevValue", dataKey.postFuncBody); + dataKey.postFunc = new Function("time", "value", "prevValue", "timePrev", "prevOrigValue", dataKey.postFuncBody); } } if (datasourceType === types.datasourceType.entity || datasourceSubscription.type === types.widgetType.timeseries.value) { @@ -165,6 +166,7 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic }; dataKeys[key] = dataKey; } + dataSourceOrigData = angular.copy(datasourceData); dataKey.key = key; } if (datasourceType === types.datasourceType.function) { @@ -678,27 +680,36 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic var dataKey = dataKeyList[keyIndex]; var data = []; var prevSeries; + var prevOrigSeries; var datasourceKeyData; + var datasourceOrigKeyData; var update = false; if (realtime) { datasourceKeyData = []; + datasourceOrigKeyData = []; } else { datasourceKeyData = datasourceData[datasourceKey].data; + datasourceOrigKeyData = dataSourceOrigData[datasourceKey].data; } if (datasourceKeyData.length > 0) { prevSeries = datasourceKeyData[datasourceKeyData.length - 1]; + prevOrigSeries = datasourceOrigKeyData[datasourceOrigKeyData.length -1]; } else { prevSeries = [0, 0]; + prevOrigSeries = [0, 0]; } + dataSourceOrigData[datasourceKey].data = []; if (datasourceSubscription.type === types.widgetType.timeseries.value) { var series, time, value; for (var i = 0; i < keyData.length; i++) { series = keyData[i]; time = series[0]; + dataSourceOrigData[datasourceKey].data.push(series); value = convertValue(series[1]); if (dataKey.postFunc) { - value = dataKey.postFunc(time, value, prevSeries[1]); + value = dataKey.postFunc(time, value, prevSeries[1], prevOrigSeries[0], prevOrigSeries[1]); } + prevOrigSeries = series; series = [time, value]; data.push(series); prevSeries = series; @@ -708,9 +719,10 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic if (keyData.length > 0) { series = keyData[0]; time = series[0]; + dataSourceOrigData[datasourceKey].data.push(series); value = convertValue(series[1]); if (dataKey.postFunc) { - value = dataKey.postFunc(time, value, prevSeries[1]); + value = dataKey.postFunc(time, value, prevSeries[1], prevOrigSeries[0], prevOrigSeries[1]); } series = [time, value]; data.push(series); diff --git a/ui/src/app/components/datakey-config.tpl.html b/ui/src/app/components/datakey-config.tpl.html index f9126e6f82..ff94f1a955 100644 --- a/ui/src/app/components/datakey-config.tpl.html +++ b/ui/src/app/components/datakey-config.tpl.html @@ -75,9 +75,16 @@ + \ No newline at end of file diff --git a/ui/src/app/locale/locale.constant-TR.json b/ui/src/app/locale/locale.constant-TR.json index 04575fbc90..de88116fe5 100644 --- a/ui/src/app/locale/locale.constant-TR.json +++ b/ui/src/app/locale/locale.constant-TR.json @@ -1,899 +1,899 @@ { "access": { "unauthorized": "Yetkisiz", - "unauthorized-access": "Yetkisiz Eriþim", - "unauthorized-access-text": "Bu kaynaða eriþmek için giriþ yapmalýsýnýz!", - "access-forbidden": "Eriþim Yasaklandý", - "access-forbidden-text": "Bu yere eriþim haklarýna sahip deðilsiniz!
Bu konuma eriþmek istiyorsanýz yine de farklý kullanýcýlarla giriþ yapmayý deneyin.", + "unauthorized-access": "Yetkisiz Erişim", + "unauthorized-access-text": "Bu kaynağa erişmek için giriş yapmalısınız!", + "access-forbidden": "Erişim Yasaklandı", + "access-forbidden-text": "Bu konuma erişim haklarınız yok!
Bu yere hala erişmek istiyorsanız farklı kullanıcılarla oturum açmayı deneyin.", "refresh-token-expired": "Oturum süresi doldu", - "refresh-token-failed": "Seans yenilenemiyor" + "refresh-token-failed": "Oturum yenilenemiyor" }, "action": { - "activate": "Aktive Et", - "suspend": "Askýya Alma", - "save": "Kayýt etmek", - "saveAs": "Farklý kaydet", - "cancel": "Ýptal etmek", - "ok": "TAMAM", + "activate": "Etkinleştir", + "suspend": "Askıya al", + "save": "Kaydet", + "saveAs": "Farklı Kaydet", + "cancel": "İptal", + "ok": "Tamam", "delete": "Sil", - "add": "Eklemek", + "add": "Ekle", "yes": "Evet", - "no": "Yok hayýr", - "update": "Güncelleþtirme", - "remove": "Kaldýr", - "search": "Arama", - "clear-search": "Aramayý Temizle", - "assign": "Atamak", - "unassign": "Atamayý kaldýrma", - "share": "Pay", + "no": "Hayır", + "update": "Güncelle", + "remove": "Kaldır", + "search": "Ara", + "clear-search": "Aramayı Temizle", + "assign": "Ata", + "unassign": "Atamayı kaldır", + "share": "Paylaş", "make-private": "Özel yap", - "apply": "Uygulamak", - "apply-changes": "Deðiþiklikleri uygula", - "edit-mode": "Düzenleme modu", - "enter-edit-mode": "Düzenleme moduna girin", - "decline-changes": "Deðiþiklikleri reddet", + "apply": "Uygula", + "apply-changes": "Değişiklikleri Uygula", + "edit-mode": "Düzenleme Modu", + "enter-edit-mode": "Düzenleme moduna gir", + "decline-changes": "Değişiklikleri reddet", "close": "Kapat", "back": "Geri", - "run": "Koþmak", - "sign-in": "Oturum aç!", + "run": "Çalıştır", + "sign-in": "Giriş yap!", "edit": "Düzenle", - "view": "Görünüm", - "create": "Yaratmak", - "drag": "Sürüklemek", + "view": "Görüntüle", + "create": "Oluştur", + "drag": "Sürükle", "refresh": "Yenile", - "undo": "Geri alma", + "undo": "Geri al", "copy": "Kopyala", - "paste": "Yapýþtýrmak", - "copy-reference": "Referansý kopyala", - "paste-reference": "Referansý yapýþtýr", - "import": "Ýthalat", - "export": "Ýhracat", - "share-via": "{{Provider}} aracýlýðýyla paylaþ" + "paste": "Yapıştır", + "copy-reference": "Referansı kopyala", + "paste-reference": "Referansı yapıştır", + "import": "İçe aktar", + "export": "Dışa aktar", + "share-via": "{{provider}} ile paylaş" }, "aggregation": { "aggregation": "Toplama", - "function": "Veri toplama iþlevi", - "limit": "Maksimum deðerler", - "group-interval": "Gruplama aralýðý", + "function": "Veri toplama işlevi", + "limit": "Maksimum değerler", + "group-interval": "Gruplama aralığı", "min": "Min", - "max": "Max", + "max": "Maks", "avg": "Ortalama", - "sum": "Sum", - "count": "Sayý", + "sum": "Toplam", + "count": "Sayı", "none": "Yok" }, "admin": { "general": "Genel", "general-settings": "Genel Ayarlar", - "outgoing-mail": "Giden posta", - "outgoing-mail-settings": "Giden Posta Ayarlarý", - "system-settings": "Sistem ayarlarý", - "test-mail-sent": "Test postasý baþarýyla gönderildi!", + "outgoing-mail": "Giden Posta", + "outgoing-mail-settings": "Giden Posta Ayarları", + "system-settings": "Sistem Ayarları", + "test-mail-sent": "Test e-postası başarıyla gönderildi!", "base-url": "Temel URL", "base-url-required": "Temel URL gerekli.", - "mail-from": "Mail þu kiþiden geldi", - "mail-from-required": "Mail From gereklidir.", + "mail-from": "Gönderen Kişi", + "mail-from-required": "Gönderen Kişi gerekli.", "smtp-protocol": "SMTP protokolü", - "smtp-host": "SMTP ana bilgisayarý", - "smtp-host-required": "SMTP ana bilgisayarý gerekli.", + "smtp-host": "SMTP sunucusu", + "smtp-host-required": "SMTP sunucusu gerekli.", "smtp-port": "SMTP portu", - "smtp-port-required": "Bir smtp portu saðlamalýsýnýz.", - "smtp-port-invalid": "Bu geçerli bir smtp portuna benzemiyor.", - "timeout-msec": "Zaman aþýmý (msn)", - "timeout-required": "Zaman aþýmý gerekli.", - "timeout-invalid": "Bu geçerli bir zaman aþýmý gibi görünmüyor.", - "enable-tls": "TLS'yi etkinleþtir", - "send-test-mail": "Test postasý gönder" + "smtp-port-required": "Bir SMTP portu sağlamalısınız.", + "smtp-port-invalid": "Bu geçerli bir smtp portu gibi görünmüyor.", + "timeout-msec": "Zaman aşımı (milisaniye)", + "timeout-required": "Zaman aşımı değeri gerekli.", + "timeout-invalid": "Bu geçerli bir zaman aşımı gibi görünmüyor.", + "enable-tls": "TLS'i etkinleştir.", + "send-test-mail": "Test e-postası gönder" }, "alarm": { "alarm": "Alarm", "alarms": "Alarmlar", - "select-alarm": "Alarmý seç", - "no-alarms-matching": " '{{Entity}}' ile eþleþen hiçbir alarm bulunamadý. ", + "select-alarm": "Alarm seç", + "no-alarms-matching": "'{{entity}}' ile eşleşen alarm bulunamadı.", "alarm-required": "Alarm gerekli", "alarm-status": "Alarm durumu", "search-status": { "ANY": "Herhangi biri", "ACTIVE": "Aktif", "CLEARED": "Temizlendi", - "ACK": "Kabul edilen", - "UNACK": "Unacknowledged" + "ACK": "Onaylandı", + "UNACK": "Onaylanmadı" }, "display-status": { - "ACTIVE_UNACK": "Aktif Olmamýþ", - "ACTIVE_ACK": "Aktif Kabul", - "CLEARED_UNACK": "Onaylanmamýþ Onaylandý", - "CLEARED_ACK": "Onaylandý onaylandý" + "ACTIVE_UNACK": "Aktif Onaylanmadı", + "ACTIVE_ACK": "Aktif Onaylandı", + "CLEARED_UNACK": "Temizlendi Onaylanmadı", + "CLEARED_ACK": "Temizlendi Onaylandı" }, - "no-alarms-prompt": "Alarm bulunamadý", - "created-time": "Zaman yaratýldý", - "type": "Tür", - "severity": "Önem", - "originator": "Originator", - "originator-type": "Gönderen türü", - "details": "Ayrýntýlar", + "no-alarms-prompt": "Alarm bulunamadı", + "created-time": "Oluşma zamanı", + "type": "Tip", + "severity": "Şiddet", + "originator": "Kaynak", + "originator-type": "Kaynak tipi", + "details": "Detaylar", "status": "Durum", - "alarm-details": "Alarm detaylarý", - "start-time": "Baþlama zamaný", - "end-time": "Bitiþ zamaný", - "ack-time": "Onaylanmýþ zaman", - "clear-time": "Temizlenmiþ zaman", + "alarm-details": "Alarm detayları", + "start-time": "Başlangıç zamanı", + "end-time": "Bitiş zamanı", + "ack-time": "Onaylanma zamanı", + "clear-time": "Temizlenme zamanı", "severity-critical": "Kritik", - "severity-major": "Majör", - "severity-minor": "Minör", - "severity-warning": "Uyarý", + "severity-major": "Birincil", + "severity-minor": "İkincil", + "severity-warning": "Uyarı", "severity-indeterminate": "Belirsiz", - "acknowledge": "Onay", - "clear": "Açýk", - "search": "Arama alarmlarý", - "selected-alarms": "{count, çoðul, 1 {1 alarm} diðer {# alarm}} seçildi", - "no-data": "Gösterilecek bilgi yok", - "polling-interval": "Alarmlar sorgulama aralýðý (sn)", - "polling-interval-required": "Alarmlar sorgulama aralýðý gerekli.", - "min-polling-interval-message": "En az 1 san yoklama aralýðýna izin verilir.", - "aknowledge-alarms-title": "Kabul et { count, plural, 1 {1 alarm} other {# alarms}} selected ", - "aknowledge-alarms-text": "{Count, plural, 1 {1 alarm} dother {# alarm}} kimliðini kabul etmek istediðinizden emin misiniz?", - "clear-alarms-title": "Temizle {count, plural, 1 {1 alarm} other {# alarm}}", - "clear-alarms-text": "count, plural, 1 {1 alarm} diðer {# alarms}} silmek istediðinizden emin misiniz?" + "acknowledge": "Onayla", + "clear": "Temizle", + "search": "Alarm ara", + "selected-alarms": "{ count, select, 1 {1 alarm} other {# alarm} } seçildi", + "no-data": "Görüntülenecek veri bulunmuyor", + "polling-interval": "Alarm yoklama aralığı (saniye)", + "polling-interval-required": "Alarm yoklama aralığı gerekli.", + "min-polling-interval-message": "Alarm yoklama aralığı en az 1 saniye olmalıdır.", + "aknowledge-alarms-title": "{ count, select, 1 {1 alarmı} other {# alarmı} } onayla", + "aknowledge-alarms-text": "{ count, select, 1 {1 alarmı} other {# alarmı} } onaylamak istediğinize emin misiniz?", + "clear-alarms-title": "{ count, select, 1 {1 alarmı} other {# alarmı} } temizle", + "clear-alarms-text": "{ count, select, 1 {1 alarmı} other {# alarmı} } temizlemek istediğinize emin misiniz?" }, "alias": { - "add": "Takma ad ekle", - "edit": "Takma adý düzenle", - "name": "Takma ad", - "name-required": "Takma ad gerekli", - "duplicate-alias": "Ayný ada sahip diðer ad zaten var.", - "filter-type-single-entity": "Tek varlýk", - "filter-type-entity-list": "Varlýk listesi", - "filter-type-entity-name": "Varlýk adý", - "filter-type-state-entity": "Gösterge panosu durumundan varlýk", - "filter-type-state-entity-description": "Gösterge panosu durum parametrelerinden alýnan varlýk", - "filter-type-asset-type": "Varlýk türü", - "filter-type-asset-type-description": "Öðe varlýklarý {{assetType}} '", - "filter-type-asset-type-and-name-description": "{{AssetType}} türündeki varlýklar ve {{prefix}} ile baþlayan adla ", - "filter-type-device-type": "Cihaz tipi", - "filter-type-device-type-description": "Türlü cihazlar {{deviceType}} ", - "filter-type-device-type-and-name-description": "{{DeviceType}} türündeki cihazlar ve {{prefix}} ile baþlayan adla ", - "filter-type-relations-query": "Ýliþkiler sorgusu", - "filter-type-relations-query-description": "{{relationType}} iliþkisine sahip {{direction}} {{rootEntity}} olan {{entities}}", - "filter-type-asset-search-query": "Öðe arama sorgusu", - "filter-type-asset-search-query-description": "{{RelationType}} iliþkisine sahip {{direction}}} türlerine sahip öðeler {{direction}} {{rootEntity}} ", - "filter-type-device-search-query": "Cihaz arama sorgusu", - "filter-type-device-search-query-description": "{{RelationType}} iliþkisi olan {{direction}} {{rootEntity}} içeren {{deviceTypes}} türüne sahip cihazlar", - "entity-filter": "Varlýk filtresi", - "resolve-multiple": "Birden çok varlýk olarak çöz", + "add": "Kısa ad ekle", + "edit": "Kısa ad düzenle", + "name": "Kısa ad", + "name-required": "Kısa ad gerekli", + "duplicate-alias": "Aynı kısa ad daha önce kullanılmış.", + "filter-type-single-entity": "Tek öğe", + "filter-type-entity-list": "Öğe listesi", + "filter-type-entity-name": "Öğe adı", + "filter-type-state-entity": "Kontrol panelinden öğe", + "filter-type-state-entity-description": "Kontrol tablosu durum parametrelerinden alınan öğeler", + "filter-type-asset-type": "Varlık türü", + "filter-type-asset-type-description": "'{{assetType}}' türünde varlıklar", + "filter-type-asset-type-and-name-description": "Adı '{{prefix}}' ile başlayan '{{assetType}}' türünde varlıklar", + "filter-type-device-type": "Aygıt türü", + "filter-type-device-type-description": "'{{deviceType}}' türünde aygıtlar", + "filter-type-device-type-and-name-description": "Adı '{{prefix}}' ile başlayan'{{deviceType}}' türünde aygıtlar", + "filter-type-relations-query": "İlişkiler sorgusu", + "filter-type-relations-query-description": "{{relationType}} türünde ilişkili olan varlıklar: {{entities}}. {{direction}}: {{rootEntity}}", + "filter-type-asset-search-query": "Varlık arama sorgusu", + "filter-type-asset-search-query-description": "{{relationType}} türünde ilişkisi olan varlıklar {{assetTypes}}. {{direction}}: {{rootEntity}}", + "filter-type-device-search-query": "Aygıt arama sorgusu", + "filter-type-device-search-query-description": "{{relationType}} türünde ilişkisi olan aygıt tipleri {{deviceTypes}}. {{direction}}: {{rootEntity}}", + "entity-filter": "Öğe filtresi", + "resolve-multiple": "Çoklu öğe olarak çözümle", "filter-type": "Filtre tipi", - "filter-type-required": "Filtre türü gerekli.", - "entity-filter-no-entity-matched": "Belirtilen filtreyle eþleþen varlýk bulunamadý.", - "no-entity-filter-specified": "Hiçbir varlýk filtresi belirtilmemiþ", - "root-state-entity": "Gösterge panosu durum varlýðýný root olarak kullan", - "root-entity": "Kök varlýk", - "state-entity-parameter-name": "Durum öðesi parametre adý", - "default-state-entity": "Varsayýlan durum varlýðý", - "default-entity-parameter-name": "Varsayýlan olarak", - "max-relation-level": "Maksimum iliþki seviyesi", - "unlimited-level": "Sýnýrsýz seviye", - "state-entity": "Gösterge panosu durumu", - "all-entities": "Tüm varlýklar", - "any-relation": "Herhangi" + "filter-type-required": "Filtre tipi gerekli.", + "entity-filter-no-entity-matched": "Belirlenen filtre ile eşleşen bir öğe bulunamadı.", + "no-entity-filter-specified": "Hiçbir öğe filtresi belirtilmedi", + "root-state-entity": "Kontrol panelini kök olarak kullan", + "root-entity": "Kök öğe", + "state-entity-parameter-name": "Durum varlığı parametre adı", + "default-state-entity": "Varsayılan durum öğesi", + "default-entity-parameter-name": "Varsayılan", + "max-relation-level": "Maksimum ilişki düzeyi", + "unlimited-level": "Sınırsız seviye", + "state-entity": "Kontrol paneli öğesi", + "all-entities": "Tüm öğeler", + "any-relation": "Herhangi biri" }, "asset": { - "asset": "Varlýk", - "assets": "Varlýklar", - "management": "Varlýk Yönetimi", - "view-assets": "Varlýklarý Görüntüle", - "add": "Öðe Ekle", - "assign-to-customer": "Müþteriye atama", - "assign-asset-to-customer": "Müþteriye Varlýk (lar) Atama", - "assign-asset-to-customer-text": "Lütfen müþteriye atamak için varlýklarý seçin", - "no-assets-text": "Öðe bulunamadý", - "assign-to-customer-text": "Lütfen varlýk (lar) a atamak için müþteriyi seçin", - "public": "Halka açýk", - "assignedToCustomer": "Müþteriye atandý", - "make-public": "Varlýðý herkese açýk yap", - "make-private": "Varlýk özel yap", - "unassign-from-customer": "Müþteriden atama", - "delete": "Öðeyi sil", - "asset-public": "Varlýk halka açýk", - "asset-type": "Varlýk türü", - "asset-type-required": "Öðe türü gerekli.", - "select-asset-type": "Varlýk türünü seç", - "enter-asset-type": "Varlýk türünü girin", - "any-asset": "Herhangi bir varlýk", - "no-asset-types-matching": "{{EntitySubtype}} ile eþleþen öðe türü bulunamadý. ", - "asset-type-list-empty": "Hiçbir öðe türü seçilmedi.", - "asset-types": "Varlýk türleri", - "name": "Ad", - "name-required": "Ýsim gerekli.", - "description": "Açýklama", + "asset": "Varlık", + "assets": "Varlıklar", + "management": "Varlık Yönetimi", + "view-assets": "Varlıkları Görüntüle", + "add": "Varlık ekle", + "assign-to-customer": "Kullanıcı grubuna ata", + "assign-asset-to-customer": "Varlıkları Kullanıcı Grubuna Ata", + "assign-asset-to-customer-text": "Lütfen kullanıcı grubuna atanacak varlıkları seçin", + "no-assets-text": "Varlık bulunamadı", + "assign-to-customer-text": "Lütfen varlıkları atamak için kullanıcı grubu seçin", + "public": "Açık", + "assignedToCustomer": "Kullanıcı grubuna atandı", + "make-public": "Varlığı açık hale getir", + "make-private": "Varlığı özel hale getir", + "unassign-from-customer": "Kullanıcı grubundan atamayı kaldır", + "delete": "Varlığı sil", + "asset-public": "Varlık açık halde", + "asset-type": "Varlık türü", + "asset-type-required": "Varlık türü gerekli.", + "select-asset-type": "Varlık türü seçin", + "enter-asset-type": "Varlık türü girin", + "any-asset": "Herhangi bir varlık", + "no-asset-types-matching": "'{{entitySubtype}}' ile eşleşen varlık bulunamadı.", + "asset-type-list-empty": "Herhangi bir varlık türü bulunamadı.", + "asset-types": "Varlık türleri", + "name": "İsim", + "name-required": "İsim gerekli.", + "description": "Açıklama", "type": "Tür", "type-required": "Tür gerekli.", - "details": "Ayrýntýlar", - "events": "Etkinlikler", - "add-asset-text": "Yeni varlýk ekle", - "asset-details": "Varlýk ayrýntýlarý", - "assign-assets": "Öðeleri atama", - "assign-assets-text": "Müþteriye {count, çoðul, 1 {1 asset}} diðer {# asset}} atayýn ", - "delete-assets": "Öðeleri sil", - "unassign-assets": "Varlýklarý atama", - "unassign-assets-action-title": "Müþteriden tekil, sayým, çoðul, 1 {1 öðe} diðer {# varlýk}} atama ", - "assign-new-asset": "Yeni varlýk atama", - "delete-asset-title": "Öðeyi {{assetName}} silmek istediðinizden emin misiniz?", - "delete-asset-text": "Dikkatli olun, onaylandýktan sonra varlýk ve ilgili tüm veriler kurtarýlamaz.", - "delete-assets-title": "{Count, çoðul, 1 {1 asset} diðer {# asset}} silmek istediðinizden emin misiniz?", - "delete-assets-action-title": "Sil {count, çoðul, 1 {1 asset} diðer {# asset}}", - "delete-assets-text": "Dikkatli olun, onaylandýktan sonra tüm seçilmiþ varlýklar kaldýrýlacak ve ilgili tüm veriler kurtarýlamayacaktýr.", - "make-public-asset-title": "Varlýðý {{assetName}} herkese açýk yapmak istediðinizden emin misiniz? ", - "make-public-asset-text": "Onaydan sonra varlýk ve tüm verileri kamuya açýk ve baþkalarý tarafýndan eriþilebilir olacak.", - "make-private-asset-title": "Öðeyi {{assetName}} özel yapmak istediðinizden emin misiniz? ", - "make-private-asset-text": "Onaydan sonra varlýk ve tüm verileri gizli tutulacak ve baþkalarý tarafýndan eriþilemeyecektir.", - "unassign-asset-title": "Öðeyi {{assetName}} öðesinin atamasýný kaldýrmak istediðinizden emin misiniz?", - "unassign-asset-text": "Onaydan sonra varlýk atama yapýlmayacak ve müþteri tarafýndan eriþilemeyecektir.", - "unassign-asset": "Atama atamayý kaldýr", - "unassign-assets-title": "count, plural, 1 {1 öðe} other {# asset}} atama atamak istediðinizden emin misiniz?", - "unassign-assets-text": "Onaylandýktan sonra, seçilen tüm öðeler atamadan kaldýrýlacak ve müþteri tarafýndan eriþilemeyecektir.", - "copyId": "Öðe Kimliði Kopyala", - "idCopiedMessage": "Öðe Kimliði panoya kopyalandý", - "select-asset": "Varlýk seç", - "no-assets-matching": "{{Entity}} ile eþleþen hiçbir öðe bulunamadý. ", - "asset-required": "Varlýk gerekli", - "name-starts-with": "Öðe adý ile baþlar" + "details": "Detaylar", + "events": "Olaylar", + "add-asset-text": "Yeni varlık ekle", + "asset-details": "Varlık detayları", + "assign-assets": "Varlıkları ata", + "assign-assets-text": "{ count, select, 1 {1 varlığı} other {# varlığı} } kullanıcı grubuna ata", + "delete-assets": "Varlıkları sil", + "unassign-assets": "Varlıkların atamalarını kaldır", + "unassign-assets-action-title": "{ count, select, 1 {1 varlığın} other {# varlığın} } atamalarını kullanıcı grubundan kaldır", + "assign-new-asset": "Yeni varlık ata", + "delete-asset-title": "'{{assetName}}' isimli varlığı silmek istediğinize emin misiniz?", + "delete-asset-text": "UYARI: Onaylandıktan sonra varlık ve ilgili tüm veriler geri yüklenemeyecek şekilde silinecek.", + "delete-assets-title": "{ count, select, 1 {1 varlığı} other {# varlığı} } silmek istediğinize emin misiniz?", + "delete-assets-action-title": "{ count, select, 1 {1 varlığı} other {# varlığı} } sil", + "delete-assets-text": "UYARI: Onaylandıktan sonra tüm seçili varlıklar ver ilgili tüm veriler geri yüklenemyeck şekilde silinecek.", + "make-public-asset-title": "'{{assetName}}' isimli varlığı açık hale getirmek istediğinize emin misiniz?", + "make-public-asset-text": "Onaylandıktan sonra varlık ve ilgili veriler açık hale gelecek ve başkaları tarafından erişilebilir olacaktır.", + "make-private-asset-title": "'{{assetName}}' isimli varlığı özel hale getirmek istediğinize emin misiniz?", + "make-private-asset-text": "Onaylandıktan sonra varlık ve ilgili veriler özel hale gelecek ve başkaları tarafından erişilemez olacaktır.", + "unassign-asset-title": "'{{assetName}}' isimli varlığın atamasını kaldırmak istediğinize emin misiniz?", + "unassign-asset-text": "Onaylandıktan sonra varlığın ataması kaldırılacak ve kullanıcı grubu tarafından erişilemez olacaktır.", + "unassign-asset": "Varlık atamasını kaldır", + "unassign-assets-title": " { count, select, 1 {1 varlık} other {# varlık} } atamasını kaldırmak istediğinize emin misiniz?", + "unassign-assets-text": "Onaylandıktan sonra tüm seçili varlıkların ataması kaldırılacak ve kullanıcı grubu tarafından erişilemez olacaktır.", + "copyId": "Varlık kimliğini kopyala", + "idCopiedMessage": "Varlık kimliği panoya kopyalandı", + "select-asset": "Varlık seç", + "no-assets-matching": "'{{entity}}' isimli varlık bulunamadı.", + "asset-required": "Varlık gerekli", + "name-starts-with": "... ile başlayan varlık adı" }, "attribute": { - "attributes": "Öznitellikler", + "attributes": "Öznitelikler", "latest-telemetry": "Son telemetri", - "attributes-scope": "Varlýk öznitelikleri kapsamý", + "attributes-scope": "Varlık öznitelik kapsamı", "scope-latest-telemetry": "Son telemetri", - "scope-client": "Müþteri özellikleri", - "scope-server": "Sunucu öznitelikleri", - "scope-shared": "Paylaþýlan özellikler", - "add": "Özellik ekle", + "scope-client": "İstemci öznitelikler", + "scope-server": "Sunucu öznitelikler", + "scope-shared": "Paylaşılan öznitelikler", + "add": "Öznitelik ekle", "key": "Anahtar", - "last-update-time": "Son güncelleme zamaný", - "key-required": "Özellik anahtarý gerekli.", - "value": "Deðer", - "value-required": "Özellik deðeri gerekli.", - "delete-attributes-title": "{Count, çoðul, 1 {1 özellik} diðer {# attributes}} silmek istediðinizden emin misiniz?", - "delete-attributes-text": "Dikkatli olun, onaylandýktan sonra tüm seçilen özellikler kaldýrýlacak.", - "delete-attributes": "Nitelikleri sil", - "enter-attribute-value": "Özellik deðerini girin", - "show-on-widget": "Widget’ta göster", - "widget-mode": "Widget modu", - "next-widget": "Sonraki pencere öðesi", - "prev-widget": "Önceki pencere öðesi", - "add-to-dashboard": "Gösterge tablosuna ekle", - "add-widget-to-dashboard": "Gösterge tablosuna widget ekle", - "selected-attributes": "{count, çoðul, 1 {1 özellik} diðer {# attributes}} seçildi", - "selected-telemetry": "{count, çoðul, 1 {1 telemetri birimi} diðer {# telemetri birimleri}} seçildi" + "last-update-time": "Son güncelleme zamanı", + "key-required": "Öznitelik anahtarı gerekli.", + "value": "Değer", + "value-required": "Öznitelik değeri gerekli.", + "delete-attributes-title": "Silmek istediğinize emin misiniz { count, select, 1 {1 öznitelik} other {# öznitelik} }?", + "delete-attributes-text": "UYARI: Onaylandıktan sonra tüm seçili öznitelikler kaldırılacak.", + "delete-attributes": "Öznitelikleri sil", + "enter-attribute-value": "Öznitelik değeri gir", + "show-on-widget": "Göstergede göster", + "widget-mode": "Gösterge modu", + "next-widget": "Sonraki gösterge", + "prev-widget": "Önceki gösterge", + "add-to-dashboard": "Kontrol paneline ekle", + "add-widget-to-dashboard": "Göstergeyi kontrol paneline ekle", + "selected-attributes": "{ count, select, 1 {1 öznitelik} other {# öznitelik} } seçildi", + "selected-telemetry": "{ count, select, 1 {1 telemetri birimi} other {# telemetri birimi} } seçildi" }, "audit-log": { - "audit": "Denetim", - "audit-logs": "Denetim Kayýtlarý", - "timestamp": "Zaman Damgasý", - "entity-type": "Varlýk Türü", - "entity-name": "Varlýk adý", - "user": "Kullanýcý", + "audit": "Log ve Hata Yönetimi", + "audit-logs": "Loglar ve Hatalar", + "timestamp": "Zaman", + "entity-type": "Kaynak", + "entity-name": "İsim", + "user": "Kullanıcı", "type": "Tür", "status": "Durum", - "details": "Ayrýntýlar", - "type-added": "Katma", + "details": "Detaylar", + "type-added": "Eklendi", "type-deleted": "Silindi", - "type-updated": "Güncellenmiþ", - "type-attributes-updated": "Öznitelikler güncellendi", - "type-attributes-deleted": "Öznitelikler silindi", - "type-rpc-call": "RPC çaðrýsý", + "type-updated": "Güncellendi", + "type-attributes-updated": "Özellikler güncellendi", + "type-attributes-deleted": "Özellikler silindi", + "type-rpc-call": "Uzaktan işlem çağrısı", "type-credentials-updated": "Kimlik bilgileri güncellendi", - "type-assigned-to-customer": "Müþteriye Atanan", - "type-unassigned-from-customer": "Müþteriden Atanmamýþ", - "type-activated": "Aktif", - "type-suspended": "Askýya alýndý", + "type-assigned-to-customer": "Kullanıcı grubuna atandı", + "type-unassigned-from-customer": "Kullanıcı grubundan atama kaldırıldı", + "type-activated": "Etkinleştirildi", + "type-suspended": "Askıya alındı", "type-credentials-read": "Kimlik bilgileri okundu", - "type-attributes-read": "Nitelikler oku", - "type-relation-add-or-update": "Ýliþki güncellendi", - "type-relation-delete": "Ýliþki silindi", - "type-relations-delete": "Tüm iliþki silindi", + "type-attributes-read": "Özellikler okundu", + "type-relation-add-or-update": "İlişki güncellendi", + "type-relation-delete": "İlişki silindi", + "type-relations-delete": "Tüm ilişki silindi", "type-alarm-ack": "Kabul edilen", "type-alarm-clear": "Temizlendi", - "status-success": "Baþarý", - "status-failure": "Baþarýsýzlýk", - "audit-log-details": "Denetim kaydý ayrýntýlarý", - "no-audit-logs-prompt": "Kayýt bulunamadý", - "action-data": "Eylem verileri", - "failure-details": "Arýza detaylarý", - "search": "Denetim günlüklerini ara", - "clear-search": "Aramayý Temizle" + "status-success": "Başarılı", + "status-failure": "Başarısız", + "audit-log-details": "Log ve hata detayları", + "no-audit-logs-prompt": "Log ve hata bulunamadı", + "action-data": "Eylem verisi", + "failure-details": "Başarısız işlem detayları", + "search": "Hata ve Log Geçmişinde Ara", + "clear-search": "Aramayı temizle" }, "confirm-on-exit": { - "message": "Kaydedilmemiþ deðiþiklikleriniz var. Bu sayfadan ayrýlmak istediðinizden emin misiniz?", - "html-message": "Kaydedilmemiþ deðiþiklikleriniz var.
Bu sayfadan ayrýlmak istediðinizden emin misiniz?", - "title": "Kaydedilmemiþ deðiþiklikler" + "message": "Kaydedilmemiş değişiklikler var. Sayfadan ayrılmak istediğinize emin misiniz?", + "html-message": "Kaydedilmemiş değişiklikler var.
Sayfadan ayrılmak istediğinize emin misiniz?", + "title": "Kaydedilmemiş Değişiklikler" }, "contact": { "country": "Ülke", - "city": "Kent", - "state": "Eyalet / Ýl", + "city": "Şehir", + "state": "Eyalet / İl", "postal-code": "Posta Kodu", - "postal-code-invalid": "Geçersiz Posta Kodu / Posta Kodu biçimi.", - "address": "Adres", - "address2": "Adres 2", + "postal-code-invalid": "Geçersiz Posta Kodu.", + "address": "Addres", + "address2": "Addres 2", "phone": "Telefon", "email": "E-posta", "no-address": "Adres yok" }, "common": { - "username": "Kullanýcý adý", + "username": "Kullanıcı adı", "password": "Parola", - "enter-username": "Kullanýcý adý girin", - "enter-password": "Parolaný Gir", - "enter-search": "Arama girin" + "enter-username": "Kullanıcı adı gir", + "enter-password": "Parola gir", + "enter-search": "Arama gir" }, "content-type": { "json": "Json", "text": "Metin", - "binary": "Ýkili (Base64)" + "binary": "İkili (Base64)" }, "customer": { - "customer": "Müþteri", - "customers": "Müþteriler", - "management": "Müþteri yönetimi", - "dashboard": "Müþteri Kontrol Paneli", - "dashboards": "Müþteri Kontrol Panelleri", - "devices": "Müþteri Cihazlarý", - "entity-views": "Müþteri Varlýðý Görüntüleme Sayýsý", - "assets": "Müþteri Varlýklarý", - "public-dashboards": "Genel Panolar", - "public-devices": "Kamu Aygýtlarý", - "public-assets": "Kamu Varlýklarý", - "public-entity-views": "Kamu Varlýk Görüntüleme Sayýsý", - "add": "Müþteri Ekle", - "delete": "Müþteriyi sil", - "manage-customer-users": "Müþteri kullanýcýlarýný yönet", - "manage-customer-devices": "Müþteri cihazlarýný yönet", - "manage-customer-dashboards": "Müþteri panolarýný yönet", - "manage-public-devices": "Genel cihazlarý yönet", - "manage-public-dashboards": "Genel panolarý yönet", - "manage-customer-assets": "Müþteri varlýklarýný yönet", - "manage-public-assets": "Kamu varlýklarýný yönet", - "add-customer-text": "Yeni müþteri ekle", - "no-customers-text": "Müþteri bulunamadý", - "customer-details": "Müþteri detaylarý", - "delete-customer-title": "Müþteriyi silmek istediðinizden emin misiniz? {{CustomerTitle}} ? ", - "delete-customer-text": "Dikkatli olun, onaylandýktan sonra müþteri ve ilgili tüm veriler kurtarýlamaz.", - "delete-customers-title": "{Count, çoðul, 1 {1 müþteri} diðer {# customers}} silmek istediðinizden emin misiniz?", - "delete-customers-action-title": "Sil {count, çoðul, 1 {1 müþteri} diðer {# customers}}", - "delete-customers-text": "Dikkatli olun, onaylandýktan sonra tüm seçilen müþteriler kaldýrýlacak ve ilgili tüm veriler kurtarýlamayacaktýr.", - "manage-users": "Kullanýcýlarý Yönet", - "manage-assets": "Varlýklarý yönet", - "manage-devices": "Cihazlarý yönet", - "manage-dashboards": "Gösterge tablolarýný yönet", - "title": "Baþlýk", - "title-required": "Baþlýk gerekli.", - "description": "Açýklama", - "details": "Ayrýntýlar", - "events": "Etkinlikler", - "copyId": "Müþteri kimliðini kopyala", - "idCopiedMessage": "Müþteri Kimliði panoya kopyalandý", - "select-customer": "Müþteriyi seç", - "no-customers-matching": "{{Entity}} ile eþleþen hiçbir müþteri bulunamadý. ", - "customer-required": "Müþteri gerekli", - "select-default-customer": "Varsayýlan müþteriyi seç", - "default-customer": "Varsayýlan müþteri", - "default-customer-required": "Kiracý düzeyinde gösterge tablosunda hata ayýklamak için varsayýlan müþteri gerekiyor" + "customer": "Kullanıcı Grubu", + "customers": "Kullanıcı Grupları", + "management": "Kullanıcı Grubu Yönetimi", + "dashboard": "Kullanıcı Grubu Kontrol Paneli", + "dashboards": "Kullanıcı Grubu Kontrol Panellleri", + "devices": "Kullanıcı Grubu Aygıtları", + "entity-views": "Müşteri Varlığı Görüntüleme Sayısı", + "assets": "Kullanıcı Grubu Varlıkları", + "public-dashboards": "Açık Kontrol Panelleri", + "public-devices": "Açık Aygıtlar", + "public-assets": "Açık Varlıklar", + "public-entity-views": "Kamu Varlık Görüntüleme Sayısı", + "add": "Kullanıcı grubu ekle", + "delete": "Kullanıcı grubunu sil", + "manage-customer-users": "Kullanıcı grubu kullanıcılarını yönet", + "manage-customer-devices": "Kullanıcı grubu aygıtlarını yönet", + "manage-customer-dashboards": "Kullanıcı grubu kontrol panellerini yönet", + "manage-public-devices": "Açık aygıtları yönet", + "manage-public-dashboards": "Açık kontrol panellerini yönet", + "manage-customer-assets": "Kullanıcı Grubu varlıklarını yönet", + "manage-public-assets": "Açık varlıkları yönet", + "add-customer-text": "Yeni Kullanıcı Grubu ekle", + "no-customers-text": "Kullanıcı Grubu bulunamadı", + "customer-details": "Kullanıcı Grubu detayları", + "delete-customer-title": "'{{customerTitle}}' isimli kullanıcı grubunu silmek istediğinize emin misiniz?", + "delete-customer-text": "UYARI: Onaylandıktan sonra kullanıcı grubu ve tüm ilişkili veriler geri yüklenemeyecek şekilde silinecek.", + "delete-customers-title": "{ count, select, 1 {1 kullanıcı grubunu} other {# kullanıcı grubunu} } silmek istediğinize emin misiniz?", + "delete-customers-action-title": "{ count, select, 1 {1 kullanıcı grubunu} other {# kullanıcı grubunu} } sil", + "delete-customers-text": "UYARI: Onaylandıktan sonra tüm seçili kullanıcı grupları ve ilişkili veriler geri yüklenemez şekilde silinecek.", + "manage-users": "Kullanıcıları yönet", + "manage-assets": "Varlıkları yönet", + "manage-devices": "Aygıtları yönet", + "manage-dashboards": "Kontrol panellerini yönet", + "title": "Başlık", + "title-required": "Başlık gerekli.", + "description": "Açıklama", + "details": "Detaylar", + "events": "Olaylar", + "copyId": "Kullanıcı kimliğini kopyala", + "idCopiedMessage": "Kullanıcı kimliği panoya kopyalandı", + "select-customer": "Kullanıcı grubunu seç", + "no-customers-matching": "'{{entity}}' ile eşleşen kullanıcı grubu bulunamadı.", + "customer-required": "Kullanıcı grubu gerekli", + "select-default-customer": "Varsayılan müşteriyi seç", + "default-customer": "Varsayılan müşteri", + "default-customer-required": "Kiracı düzeyinde gösterge tablosunda hata ayıklamak için varsayılan müşteri gerekiyor" }, "datetime": { - "date-from": "Tarih", - "time-from": "Zaman", - "date-to": "Tarih", - "time-to": "Zaman" + "date-from": "Tarihinden", + "time-from": "Saatinden", + "date-to": "Tarihine", + "time-to": "Saatine" }, "dashboard": { - "dashboard": "Pano", - "dashboards": "Gösterge tablolarý", - "management": "Gösterge tablosu yönetimi", - "view-dashboards": "Gösterge Panolarý", - "add": "Gösterge Tablosu Ekle", - "assign-dashboard-to-customer": "Gösterge Tablosunu / Müþterilerini Müþteriye Atama", - "assign-dashboard-to-customer-text": "Lütfen müþteriye atamak için kontrol panellerini seçin", - "assign-to-customer-text": "Gösterge panellerini atamak için lütfen müþteriyi seçiniz", - "assign-to-customer": "Müþteriye atama", - "unassign-from-customer": "Müþteriden atama", - "make-public": "Gösterge panosunu herkese açýk yap", - "make-private": "Gösterge panosunu özel yap", - "manage-assigned-customers": "Atanan müþterileri yönet", - "assigned-customers": "Atanan müþteriler", - "assign-to-customers": "Gösterge Tablosunu / Müþterilerini Müþterilere Atama", - "assign-to-customers-text": "Lütfen gösterge panosunu atamak için müþterileri seçin", - "unassign-from-customers": "Müþterilerden Gösterge Tablosunu (Notlarýný) Atama", - "unassign-from-customers-text": "Lütfen gösterge tablosundan atamak için müþterileri seçin", - "no-dashboards-text": "Gösterge panelleri bulunamadý", - "no-widgets": "Hiçbir widget yapýlandýrýlmamýþ", - "add-widget": "Yeni pencere öðesi ekle", - "title": "Baþlýk", - "select-widget-title": "Widget seç", - "select-widget-subtitle": "Kullanýlabilir pencere öðesi türleri", - "delete": "Gösterge tablosunu sil", - "title-required": "Baþlýk gerekli.", - "description": "Açýklama", - "details": "Ayrýntýlar", - "dashboard-details": "Gösterge tablosu ayrýntýlarý", - "add-dashboard-text": "Yeni gösterge tablosu ekle", - "assign-dashboards": "Gösterge tablolarý atama", - "assign-new-dashboard": "Yeni kontrol paneli atama", - "assign-dashboards-text": "Müþterilere {count, plural, 1 {1 gösterge tablosu} other {# dashboard}}} atayýn ", - "unassign-dashboards-action-text": "Müþterilerden atama sayýsý, çoðul, 1 {1 gösterge tablosu} diðer {# panolar}}", - "delete-dashboards": "Gösterge tablolarýný sil", - "unassign-dashboards": "Atanmamýþ gösterge panolarý", - "unassign-dashboards-action-title": "Müþteriden atama sayým, çoðul, 1 {1 gösterge tablosu} diðer {# pano}}", - "delete-dashboard-title": "'{{DashboardTitle}}' gösterge panosunu silmek istediðinizden emin misiniz?", - "delete-dashboard-text": "Doðrulamadan sonra, kontrol panelinden ve ilgili tüm veriler kurtarýlamayacak.", - "delete-dashboards-title": "{Count, çoðul, 1 {1 dashboard} diðer {# dashboards}} silmek istediðinizden emin misiniz?", - "delete-dashboards-action-title": "Sil {count, çoðul, 1 {1 gösterge tablosu} diðer {# dashboard}}", - "delete-dashboards-text": "Dikkatli olun, onaylandýktan sonra tüm seçilen panolar silinecek ve ilgili tüm veriler kurtarýlamayacaktýr.", - "unassign-dashboard-title": "{{DashboardTitle}} gösterge tablosunun atamasýný kaldýrmak istediðinizden emin misiniz? ", - "unassign-dashboard-text": "Onaydan sonra gösterge panosu atanmamýþ olacak ve müþteri tarafýndan eriþilemeyecektir.", - "unassign-dashboard": "Atanmamýþ gösterge panosu", - "unassign-dashboards-title": "Sayým, çoðul, 1 {1 gösterge tablosu} diðer {# panolar}} atama atamak istediðinizden emin misiniz?", - "unassign-dashboards-text": "Onaydan sonra tüm seçilen gösterge tablolarý atanmamýþ olacak ve müþteri tarafýndan eriþilemeyecektir.", - "public-dashboard-title": "Gösterge panosu artýk herkese açýk", - "public-dashboard-text": "Gösterge tablonuz {{dashboardTitle}} artýk herkese açýk ve bir sonraki herkese açýk link üzerinden eriþilebilir:", - "public-dashboard-notice": " Not: Verilerine eriþmek için ilgili cihazlarý herkese açýk yapmayý unutmayýn.", - "make-private-dashboard-title": "Gösterge panosunu {{dashboardTitle}} özel yapmak istediðinizden emin misiniz?", - "make-private-dashboard-text": "Onaydan sonra gösterge panosu özel hale getirilecek ve baþkalarý tarafýndan eriþilemeyecektir.", - "make-private-dashboard": "Gösterge panosunu özel yap", - "socialshare-text": "'{{dashboardTitle}} ThingsBoard tarafýndan desteklenmektedir ", - "socialshare-title": "'{{dashboardTitle}} ThingsBoard tarafýndan desteklenmektedir ", - "select-dashboard": "Gösterge tablosu seç", - "no-dashboards-matching": "{{Entity}} ile eþleþen hiçbir gösterge paneli bulunamadý. ", - "dashboard-required": "Gösterge tablosu gerekli.", - "select-existing": "Mevcut kontrol panelini seç", - "create-new": "Yeni gösterge tablosu oluþtur", - "new-dashboard-title": "Yeni kontrol paneli baþlýðý", - "open-dashboard": "Açýk kontrol paneli", - "set-background": "Arka planý ayarla", + "dashboard": "Kontrol Paneli", + "dashboards": "Kontrol Panelleri", + "management": "Kontrol Paneli Yönetimi", + "view-dashboards": "Kontrol Panellerini Görüntüle", + "add": "Kontrol Paneli Ekle", + "assign-dashboard-to-customer": "Kullanıcı Grubuna Kontrol Panel(ler)i Ata", + "assign-dashboard-to-customer-text": "Lütfen kullanıcı grubuna atanacak kontrol panellerini seçin", + "assign-to-customer-text": "Lütfen kontrol panel(ler)ini atayacak kullanıcı grubu seçin", + "assign-to-customer": "Kullanıcı grubuna ata", + "unassign-from-customer": "Kullanıcı grubundan atamayı kaldır", + "make-public": "Kontrol panelini açık hale getir", + "make-private": "Kontrol panelini özel hale getir", + "manage-assigned-customers": "Atanan müşterileri yönet", + "assigned-customers": "Atanan müşteriler", + "assign-to-customers": "Gösterge Tablosunu / Müşterilerini Müşterilere Atama", + "assign-to-customers-text": "Lütfen gösterge panosunu atamak için müşterileri seçin", + "unassign-from-customers": "Müşterilerden Gösterge Tablosunu (Notlarını) Atama", + "unassign-from-customers-text": "Lütfen gösterge tablosundan atamak için müşterileri seçin", + "no-dashboards-text": "Kontrol paneli bulunamadı", + "no-widgets": "Hiçbir gösterge yapılandırılmadı", + "add-widget": "Yeni gösterge ekle", + "title": "Başlık", + "select-widget-title": "Gösterge seç", + "select-widget-subtitle": "Kullanılabilir gösterge türleri listesi", + "delete": "Kontrol paneli sil", + "title-required": "Başlık gerekli.", + "description": "Açıklama", + "details": "Detaylar", + "dashboard-details": "Kontrol paneli detayları", + "add-dashboard-text": "Yeni kontrol paneli ekle", + "assign-dashboards": "Kontrol panelleri ata", + "assign-new-dashboard": "Yeni kontrol paneli ata", + "assign-dashboards-text": "{ count, select, 1 {1 kontrol panelini} other {# kontrol panelini} } kullanıcı grubuna ata", + "unassign-dashboards-action-text": "Müşterilerden atama sayısı, çoğul, 1 {1 gösterge tablosu} diğer {# panolar}}", + "delete-dashboards": "Kontrol panellerini sil", + "unassign-dashboards": "Kontrol panellerinden atamayı kaldır", + "unassign-dashboards-action-title": "{ count, select, 1 {1 kontrol panelinin} other {# kontrol panelinin} } atamaları kullanıcı grubundan kaldır", + "delete-dashboard-title": "'{{dashboardTitle}}' isimli kontrol panelini silmek istediğinize emin misiniz?", + "delete-dashboard-text": "UYARI: Onaylandıktan sonra kontrol paneli ve ilişkili verileri geri yüklenemez şekilde silinecek.", + "delete-dashboards-title": "{ count, select, 1 {1 kontrol panelini} other {# kontrol panelini} } silmek istediğinize emin misiniz?", + "delete-dashboards-action-title": "{ count, select, 1 {1 kontrol panelini} other {# kontrol panelini} } sil", + "delete-dashboards-text": "UYARI: Onaylandıktan sonra tüm seçili kontrol panelleri ve ilişkili verileri geri yüklenemez şekilde silinecek.", + "unassign-dashboard-title": "'{{dashboardTitle}}' isimli kontrol panelindeki atamayı kaldırmak istediğinize emin misiniz?", + "unassign-dashboard-text": "Onaylandıktan sonra kontrol panelinin ataması kaldırılacak ve kullanıcı grubu tarafından erişilemez hale gelecektir.", + "unassign-dashboard": "Kontrol panelinin ataması kaldır", + "unassign-dashboards-title": "{count, select, 1 {1 kontrol panelindeki} other {# kontrol panelindeki} } atamayı kaldırmak istediğinize emin misiniz?", + "unassign-dashboards-text": "Onaylandıktan {{dashboardTitle}} açık hale getirildi ve bu bağlantıdan erişilebilir durumda", + "public-dashboard-notice": "Not: Kontrol panelinden tüm verilere erişebilmek adına ilişkili aygıtları da açık hale getirmeniz gerekmektedir.", + "make-private-dashboard-title": "'{{dashboardTitle}}' isimli kontrol panelini özel hale getirmek istediğinize emin misiniz?", + "make-private-dashboard-text": "Onaylandıktan sonra kontrol paneli özel hale getirilecek ve başkaları tarafından erişilemez olacak.", + "make-private-dashboard": "Kontrol panelini özel hale getir", + "socialshare-text": "'{{dashboardTitle}}'", + "socialshare-title": "'{{dashboardTitle}}'", + "select-dashboard": "Kontrol paneli seç", + "no-dashboards-matching": "'{{entity}}' ile eşleşen kontrol paneli bulunamadı.", + "dashboard-required": "Kontrol paneli gerekli.", + "select-existing": "Var olan bir kontrol paneli seç", + "create-new": "Yeni bir kontrol paneli oluştur", + "new-dashboard-title": "Yeni kontrol paneli başlığı", + "open-dashboard": "Kontrol panelini aç", + "set-background": "Arka plan belirle", "background-color": "Arka plan rengi", - "background-image": "Arka plan görüntüsü", - "background-size-mode": "Arka plan boyut modu", - "no-image": "Görüntü seçilmedi", - "drop-image": "Bir resim býrakýn veya yüklenecek bir dosya seçmek için týklayýn.", + "background-image": "Arka plan resmi", + "background-size-mode": "Arka plan boyutu modu", + "no-image": "Hiçbir resim seçilmedi", + "drop-image": "Bir resim bırakın veya yüklenecek dosyayı seçmek için tıklayın.", "settings": "Ayarlar", - "columns-count": "Sütun sayýsý", - "columns-count-required": "Sütun sayýsý gerekli.", - "min-columns-count-message": "Sadece 10 minimum sütun sayýsýna izin verilir.", - "max-columns-count-message": "Sadece maksimum 1000 sütun sayýsýna izin verilir.", - "widgets-margins": "Widget arasýnda marj", - "horizontal-margin": "Yatay kenar boþluðu", - "horizontal-margin-required": "Yatay kenar boþluðu deðeri gerekiyor.", - "min-horizontal-margin-message": "Minimum yatay kenar boþluðu deðeri olarak yalnýzca 0'a izin verilir.", - "max-horizontal-margin-message": "Maksimum yatay kenar boþluðu deðeri olarak yalnýzca 50'ye izin verilir.", - "vertical-margin": "Dikey kenar boþluðu", - "vertical-margin-required": "Dikey kenar boþluðu deðeri gereklidir.", - "min-vertical-margin-message": "En az dikey kenar boþluðu deðeri olarak yalnýzca 0'a izin verilir.", - "max-vertical-margin-message": "Maksimum dikey kenar boþluðu deðeri olarak yalnýzca 50'ye izin verilir.", - "autofill-height": "Otomatik dolgu düzeni yüksekliði", - "mobile-layout": "Mobil düzen ayarlarý", - "mobile-row-height": "Mobil satýr yüksekliði, px", - "mobile-row-height-required": "Mobil satýr yüksekliði deðeri gerekli.", - "min-mobile-row-height-message": "Minimum mobil satýr yüksekliði deðeri olarak yalnýzca 5 piksele izin verilir.", - "max-mobile-row-height-message": "Maksimum mobil satýr yüksekliði deðeri olarak yalnýzca 200 piksele izin verilir.", - "display-title": "Gösterge tablosu baþlýðý", - "toolbar-always-open": "Araç çubuðunu açýk tut", - "title-color": "Baþlýk rengi", - "display-dashboards-selection": "Gösterge panolarý seçimi", - "display-entities-selection": "Öðe varlýklarý seçimi", - "display-dashboard-timewindow": "Zaman penceresi göster", - "display-dashboard-export": "Görüntülü dýþa aktarma", - "import": "Gösterge paneli", - "export": "Dýþ gösterge panosu", - "export-failed-error": "Gösterge tablosu gönderilemiyor: {{error}}", - "create-new-dashboard": "Yeni gösterge tablosu oluþtur", - "dashboard-file": "Gösterge tablosu dosyasý", - "invalid-dashboard-file-error": "Gösterge tablosu alýnamadý: Geçersiz pano veri yapýsý.", - "dashboard-import-missing-aliases-title": "Alýnan pano tarafýndan kullanýlan takma adlarý yapýlandýr", - "create-new-widget": "Yeni pencere öðesi oluþtur", - "import-widget": "Widget'ý içe aktar", - "widget-file": "Widget dosyasý", - "invalid-widget-file-error": "Widget içe aktarýlamýyor: Geçersiz pencere öðesi yapýsý.", - "widget-import-missing-aliases-title": "Ýçe aktarýlan pencere aracý tarafýndan kullanýlan takma adlarý yapýlandýr", - "open-toolbar": "Gösterge tablosu araç çubuðunu aç", - "close-toolbar": "Araç çubuðunu kapat", - "configuration-error": "Yapýlandýrma hatasý", - "alias-resolution-error-title": "Gösterge tablosu takma ad hatasý", - "invalid-aliases-config": "Diðer ad filtrelerinin biriyle eþleþen herhangi bir cihaz bulunamadý.
Lütfen bu sorunu çözmek için yöneticinize baþvurun.", - "select-devices": "Cihaz seç", - "assignedToCustomer": "Müþteriye atandý", - "assignedToCustomers": "Müþterilere atandý", - "public": "Halka açýk", - "public-link": "Genel baðlantý", - "copy-public-link": "Genel baðlantýyý kopyala", - "public-link-copied-message": "Pano genel baðlantýsý panoya kopyalandý", - "manage-states": "Gösterge panosu durumlarýný yönet", - "states": "Gösterge durumu", - "search-states": "Gösterge panosu durumlarý", - "selected-states": "{count, çoðul, 1 {1 gösterge tablosu durumu} diðer {# dashboard durumlarý}} seçildi", - "edit-state": "Gösterge panosu durumunu düzenle", - "delete-state": "Gösterge panosu durumunu sil", - "add-state": "Gösterge paneli durumu", - "state": "Gösterge paneli durumu", - "state-name": "Ad", - "state-name-required": "Gösterge panosu durum adý gerekli.", - "state-id": "Durum Kimliði", - "state-id-required": "Gösterge durumu kimliði gerekiyor.", - "state-id-exists": "Ayný kimliðe sahip gösterge tablosu zaten var.", - "is-root-state": "Kök devlet", - "delete-state-title": "Gösterge panosu durumunu sil", - "delete-state-text": "Gösterge panosu durumunu '{{stateName}}' adýyla silmek istediðinizden emin misiniz?", - "show-details": "Detaylarý göster", - "hide-details": "Detaylarý gizle", + "columns-count": "Kolon sayısı", + "columns-count-required": "Kolon sayısı gerekli.", + "min-columns-count-message": "Kolon sayısı en az 10 olabilir.", + "max-columns-count-message": "Kolon sayısı en fazla 1000 olabilir.", + "widgets-margins": "Göstergeler arasındaki aralık", + "horizontal-margin": "Yatay aralık", + "horizontal-margin-required": "Yatay aralık değeri gerekli.", + "min-horizontal-margin-message": "Yatay aralık değeri en az 0 olabilir.", + "max-horizontal-margin-message": "Yatay aralık değeri en fazla 50 olabilir.", + "vertical-margin": "Dikey aralık", + "vertical-margin-required": "Dikey aralık değeri gerekli.", + "min-vertical-margin-message": "Dikey aralık değeri en az 0 olabilir.", + "max-vertical-margin-message": "Dikey aralık değeri en fazla 50 olabilir.", + "autofill-height": "Otomatik doldurma düzeni yüksekliği", + "mobile-layout": "Mobil düzen ayarları", + "mobile-row-height": "Mobil satır yüksekliği, px", + "mobile-row-height-required": "Mobil satır yüksekliği değeri gerekli.", + "min-mobile-row-height-message": "Mobil satır yükseliği değeri en az 5 px olabilir.", + "max-mobile-row-height-message": "Mobil satır yükseliği değeri en çok 200 px olabilir.", + "display-title": "Kontrol paneli başlığını göster", + "toolbar-always-open": "Araç çubuğunu her zaman açık tut", + "title-color": "Başlık rengi", + "display-dashboards-selection": "Kontrol paneli seçimlerinş göster", + "display-entities-selection": "Varlık seçimlerini göster", + "display-dashboard-timewindow": "Zaman aralığını göster", + "display-dashboard-export": "Dışa aktar seçeneğini göster", + "import": "Kontrol panelini içe aktar", + "export": "Kontrol panelini dışa aktar", + "export-failed-error": "Kontrol paneli dışa aktarılamıyor: {{error}}", + "create-new-dashboard": "Yeni kontrol paneli oluştur", + "dashboard-file": "Kontrol paneli dosyası", + "invalid-dashboard-file-error": "Kontrol paneli içe aktarılamadı: Geçersiz kontrol paneli veri yapısı.", + "dashboard-import-missing-aliases-title": "İçe aktarılan kontrol paneli tarafından kullanılan aygıt kısa adlarını yapılandırın", + "create-new-widget": "Yeni gösterge oluştur", + "import-widget": "Göstergeyi içe aktar", + "widget-file": "Gösterge dosyası", + "invalid-widget-file-error": "Gösterge içe aktarılamadı: Geçersiz gösterge veri yapısı.", + "widget-import-missing-aliases-title": "İçe aktarılan gösterge tarafından kullanılan aygıt kısa adlarını yapılandırın", + "open-toolbar": "Kontrol paneli araç çubuğunu aç", + "close-toolbar": "Araç çubuğunu kapat", + "configuration-error": "Yapılandırma hatası", + "alias-resolution-error-title": "Kontro paneli kısa adları yapılandırma hatası", + "invalid-aliases-config": "Kısa ad filtresiyle eşleşen aygıt bulunamadı.
", + "select-devices": "Aygıt seçin", + "assignedToCustomer": "Kullanıcı grubuna atandı", + "assignedToCustomers": "Kullanıcılara atandı", + "public": "Açık", + "public-link": "Açık bağlantı", + "copy-public-link": "Açık bağlantıyı kopyala", + "public-link-copied-message": "Kontrol paneli açık bağlantısı panoya kopyalandı", + "manage-states": "Kontrol paneli durumlarını yönet", + "states": "Kontrol paneli durumları", + "search-states": "Kontrol paneli durumu ara", + "selected-states": "{ count, select, 1 {1 kontrol paneli durumu} other {# kontrol paneli durumu} } seçildi", + "edit-state": "Kontrol paneli durumu düzenle", + "delete-state": "Kontrol paneli durumunu sil", + "add-state": "Kontrol paneli durumu ekle", + "state": "Kontrol paneli durumu", + "state-name": "İsim", + "state-name-required": "Kontrol paneli durumu ismi gerekli.", + "state-id": "Durum Kimliği", + "state-id-required": "Kontrol paneli durum kimliği gerekli.", + "state-id-exists": "Aynı kimlikte bir kontrol paneli durumu mevcut.", + "is-root-state": "Kök durum", + "delete-state-title": "Kontrol paneli durumunu sil", + "delete-state-text": "'{{stateName}}' isimli kontrol paneli durumunu silmek istediğinize emin misiniz?", + "show-details": "Detayları göster", + "hide-details": "Detayları gizle", "select-state": "Hedef durumu seç", - "state-controller": "Durum kontrolörü" + "state-controller": "Durum denetleyicisi" }, "datakey": { "settings": "Ayarlar", - "advanced": "Ýleri", + "advanced": "İleri düzey", "label": "Etiket", "color": "Renk", - "units": "Deðerin yanýnda gösterilecek özel sembol", - "decimals": "Kayan noktadan sonraki basamak sayýsý", - "data-generation-func": "Veri oluþturma iþlevi", - "use-data-post-processing-func": "Veri iþleme sonrasý iþlevini kullan", - "configuration": "Veri anahtarý yapýlandýrmasý", + "units": "Değerin yanında göstermek için özel simge", + "decimals": "Noktadan sonraki basamak sayısı", + "data-generation-func": "Veri oluşturma fonksiyonu", + "use-data-post-processing-func": "Veri işleme sonrası fonksiyonunu kullanın", + "configuration": "Veri anahtarı yapılandırması", "timeseries": "Zaman serisi", - "attributes": "Öznitellikler", - "alarm": "Alarm alanlarý", - "timeseries-required": "Varlýk zamanlamalarý gerekli.", - "timeseries-or-attributes-required": "Varlýk zaman çizelgeleri / öznitelikler gereklidir.", - "maximum-timeseries-or-attributes": "Maksimum {count, çoðul, 1 {1 timeseries / attribute.} Diðer {# timeseries / attributes {} izin verilir}}", - "alarm-fields-required": "Alarm alanlarý gerekli.", - "function-types": "Ýþlev türleri", - "function-types-required": "Ýþlev tipleri gereklidir.", - "maximum-function-types": "Maksimum {sayým, çoðul, 1 {1 iþlev türüne izin verilir.} Diðer {# iþlev türlerine izin verilir}}" + "attributes": "Öznitelikler", + "alarm": "Alarm alanları", + "timeseries-required": "Zaman serisi öğesi gerekli.", + "timeseries-or-attributes-required": "Zaman serisi/öznitelikler öğesi gerekli.", + "maximum-timeseries-or-attributes": "Maksimum { count, select, 1 {1 zamanserisi/öznitelik kabul edilir.} other {# zamanserisi/öznitelik kabul edilir} }", + "alarm-fields-required": "Alarm alanları gerekli.", + "function-types": "Fonksiyon türleri", + "function-types-required": "Fonksiyon türleri gerekli.", + "maximum-function-types": "Maksimum { count, select, 1 {1 fonksiyon türü kabul edilir.} other {# fonksiyon türü kabul edilir} }" }, "datasource": { - "type": "Veri kaynaðý türü", - "name": "Ad", - "add-datasource-prompt": "Lütfen veri kaynaðý ekle" + "type": "Veri kaynağı türü", + "name": "İsim", + "add-datasource-prompt": "Lütfen veri kaynağı ekleyin" }, "details": { "edit-mode": "Düzenleme modu", - "toggle-edit-mode": "Düzenleme modunu deðiþtir" + "toggle-edit-mode": "Düzenleme modunu aç/kapat" }, "device": { - "device": "Cihaz", - "device-required": "Cihaz gerekli.", - "devices": "Cihazlar", - "management": "Cihaz yönetimi", - "view-devices": "Cihazlarý Görüntüle", - "device-alias": "Cihaz takma adý", - "aliases": "Cihaz takma adlarý", - "no-alias-matching": "'{{alias}} bulunamadý. ", - "no-aliases-found": "Takma ad bulunamadý", - "no-key-matching": "'{{anahtar bulunamadý.", - "no-keys-found": "Anahtar bulunamadý.", - "create-new-alias": "Yeni bir tane oluþtur!", - "create-new-key": "Yeni bir tane oluþtur!", - "duplicate-alias-error": "Yinelenen takma ad bulundu {{alias}}..
Cihaz takma adlarý, kontrol panelinde benzersiz olmalýdýr. ", - "configure-alias": "Yapýlandýrma {{alias}} takma ad", - "no-devices-matching": "{{Entity}} ile eþleþen hiçbir cihaz bulunamadý. ", - "alias": "Alias", - "alias-required": "Cihaz takma adý gerekiyor.", - "remove-alias": "Cihaz takma adýný kaldýr", - "add-alias": "Cihaz takma adý ekle", - "name-starts-with": "Cihaz adý ile baþlýyor", - "device-list": "Aygýt listesi", + "device": "Aygıt", + "device-required": "Aygıt gerekli.", + "devices": "Aygıtlar", + "management": "Aygıt Yönetimi", + "view-devices": "Aygıtları görüntüle", + "device-alias": "Aygıt kısa adı", + "aliases": "Aygıt kısa adları", + "no-alias-matching": "'{{alias}}' bulunamadı.", + "no-aliases-found": "Hiçbir kısa ad bulunamadı.", + "no-key-matching": "'{{key}}' bulunamadı.", + "no-keys-found": "Hiçbir anahtar bulunamadı.", + "create-new-alias": "Yeni bir tane oluştur!", + "create-new-key": "Yeni bir tane oluştur!", + "duplicate-alias-error": "'{{alias}}' daha önce kaydedilmiş.
Aygıt kısa adları kontrol paneli özelinde emsalsiz olmalıdır.", + "configure-alias": "'{{alias}}' kısa adını yapılandırın", + "no-devices-matching": "'{{entity}}' ile eşleşen aygıt bulunamadı.", + "alias": "Kısa ad", + "alias-required": "Aygıt kısa adı gerekli.", + "remove-alias": "Aygıt kısa adını kaldır", + "add-alias": "Aygıt kısa adı ekle", + "name-starts-with": "... ile başlayan aygıt adı", + "device-list": "Aygıt listesi", "use-device-name-filter": "Filtre kullan", - "device-list-empty": "Cihaz seçilmedi.", - "device-name-filter-required": "Cihaz adý filtresi gerekli.", - "device-name-filter-no-device-matched": "{{Device}} ile baþlayan hiçbir cihaz bulunamadý. ", - "add": "Cihaz ekle", - "assign-to-customer": "Müþteriye atama", - "assign-device-to-customer": "Aygýtý / Aygýtlarý Müþteriye Atama", - "assign-device-to-customer-text": "Lütfen müþteriye atamak istediðiniz cihazlarý seçin", - "make-public": "Cihazý herkese açýk yap", - "make-private": "Cihazý özel yap", - "no-devices-text": "Hiçbir cihaz bulunamadý", - "assign-to-customer-text": "Lütfen cihazý atamak için müþteriyi seçin", - "device-details": "Cihaz detaylarý", - "add-device-text": "Yeni cihaz ekle", + "device-list-empty": "Hiçbir aygıt seçilmedi.", + "device-name-filter-required": "Aygıt adı filtresi gerekli.", + "device-name-filter-no-device-matched": "'{{device}}' ile başlayan herhangi bir aygıt bulunamadı.", + "add": "Aygıt ekle", + "assign-to-customer": "Kullanıcı grubuna ata", + "assign-device-to-customer": "Aygıt(lar)ı Kullanıcı Grubuna Ata", + "assign-device-to-customer-text": "Lütfen kullanıcı grubuna atanacak aygıtları seçin", + "make-public": "Aygıtı açık hale getir", + "make-private": "Aygıtı gizli hale getir", + "no-devices-text": "Hiçbir aygıt bulunamadı", + "assign-to-customer-text": "Lütfen aygıt(lar)ı atayacak kullanıcı grubu seçin", + "device-details": "Aygıt detayları", + "add-device-text": "Yeni aygıt ekle", "credentials": "Kimlik bilgileri", "manage-credentials": "Kimlik bilgilerini yönet", - "delete": "Cihazý sil", - "assign-devices": "Aygýtlarý atama", - "assign-devices-text": "Müþteriye {count, çoðul, 1 {1 cihaz} diðer {# devices}} atayýn ", - "delete-devices": "Cihazlarý sil", - "unassign-from-customer": "Müþteriden atama", - "unassign-devices": "Atanmamýþ cihazlarý", - "unassign-devices-action-title": "Müþteriden atayýn, çoðul, 1 {1 cihaz} diðer {# devices}} atama ", - "assign-new-device": "Yeni cihaz atama", - "make-public-device-title": "Cihazý {{deviceName}} herkese açýk yapmak istediðinizden emin misiniz?", - "make-public-device-text": "Onaydan sonra cihaz ve tüm verileri kamuya açýk ve baþkalarý tarafýndan eriþilebilir olacak.", - "make-private-device-title": "Cihazý {{deviceName}} özel yapmak istediðinizden emin misiniz?", - "make-private-device-text": "Onaylandýktan sonra cihaz ve tüm verileri gizli tutulacak ve baþkalarý tarafýndan eriþilemeyecektir.", + "delete": "Aygıt sil", + "assign-devices": "Aygıt ata", + "assign-devices-text": "{ count, select, 1 {1 aygıtı} other {# aygıtı} } kullanıcı grubuna ata", + "delete-devices": "Aygıtları sil", + "unassign-from-customer": "Kullanıcı Grubundan atamayı kaldır", + "unassign-devices": "Aygıtlardan atamayı kaldır", + "unassign-devices-action-title": "{ count, select, 1 {1 aygıtın} other {# aygıtın} } atamasını kullanıcı grubundan kaldır", + "assign-new-device": "Yeni aygıt ata", + "make-public-device-title": "'{{deviceName}}' isimli aygıtı açık hale getirmek istediğinizden emin misiniz?", + "make-public-device-text": "Onaylandıktan sonra aygıt ve verileri açık hale getirilecek ve diğerleri tarafından erişilebilir olacak.", + "make-private-device-title": "'{{deviceName}}' isimli aygıtı gizli hale getirmek istediğinizden emin misiniz?", + "make-private-device-text": "Onaylandıktan sonra aygıt ve verileri gizli hale getirilecek ve diğerleri tarafından erişilemez olacak.", "view-credentials": "Kimlik bilgilerini görüntüle", - "delete-device-title": "Cihazý {{deviceName}} silmek istediðinizden emin misiniz? ", - "delete-device-text": "Dikkatli olun, onaylamadan sonra cihaz ve tüm ilgili veriler kurtarýlamaz.", - "delete-devices-title": "{Count, çoðul, 1 {1 cihaz} diðer {# devices}} silmek istediðinizden emin misiniz?", - "delete-devices-action-title": "Sil {count, çoðul, 1 {1 cihaz} diðer {# devices}}", - "delete-devices-text": "Dikkatli olun, onaylandýktan sonra tüm seçilen cihazlar silinecek ve ilgili tüm veriler kurtarýlamayacaktýr.", - "unassign-device-title": "Cihazýn atamasýný kaldýrmak istediðinizden emin misiniz? {{DeviceName}} ? ", - "unassign-device-text": "Onaydan sonra cihaz atanmamýþ olacak ve müþteri tarafýndan eriþilemeyecektir.", - "unassign-device": "Atanmamýþ cihaz", - "unassign-devices-title": "Sayým, çoðul, 1 {1 cihaz} diðer {# devices}} atama atamak istediðinizden emin misiniz?", - "unassign-devices-text": "Onaylandýktan sonra tüm seçilen cihazlar atanmamýþ olacak ve müþteri tarafýndan eriþilemeyecektir.", - "device-credentials": "Cihaz Kimlik Bilgileri", - "credentials-type": "Kimlik bilgileri türü", - "access-token": "Eriþim belirteci", - "access-token-required": "Eriþim belirteci gerekli.", - "access-token-invalid": "Eriþim belirteci uzunluðu 1 ile 20 karakter arasýnda olmalýdýr.", - "rsa-key": "RSA ortak anahtarý", - "rsa-key-required": "RSA ortak anahtarý gerekli.", - "secret": "Gizli", - "secret-required": "Gizli gerekli", - "device-type": "Cihaz tipi", - "device-type-required": "Cihaz tipi gerekli.", - "select-device-type": "Cihaz türünü seç", - "enter-device-type": "Cihaz türünü girin", - "any-device": "Herhangi bir cihaz", - "no-device-types-matching": "{{EntitySubtype}} ile eþleþen cihaz türü bulunamadý. ", - "device-type-list-empty": "Hiçbir cihaz türü seçilmedi.", - "device-types": "Cihaz türleri", - "name": "Ad", - "name-required": "Ýsim gerekli.", - "description": "Açýklama", - "events": "Etkinlikler", - "details": "Ayrýntýlar", - "copyId": "Cihaz kimliðini kopyala", - "copyAccessToken": "Eriþim belirteci kopyala", - "idCopiedMessage": "Cihaz Kimliði panoya kopyalandý", - "accessTokenCopiedMessage": "Cihaz eriþim belirteci panoya kopyalandý", - "assignedToCustomer": "Müþteriye atandý", - "unable-delete-device-alias-title": "Cihaz takma adý silinemiyor", - "unable-delete-device-alias-text": "Cihaz takma adý {{deviceAlias}} ', þu widget (lar) tarafýndan kullanýldýðý þekliyle silinemiyor:
{{widgetsList}} ", - "is-gateway": "Að geçidi", - "public": "Halka açýk", - "device-public": "Cihaz herkese açýk", - "select-device": "Cihaz seç" + "delete-device-title": "'{{deviceName}}' isimli aygıtı silmek istediğinize emin misiniz?", + "delete-device-text": "UYARI: Onaylandıktan sonra aygıt ve ilişkili verileri geri yüklenemez şekilde silinecek.", + "delete-devices-title": "{ count, select, 1 {1 aygıtı} other {# aygıtı} } silmek istediğinize emin misiniz?", + "delete-devices-action-title": "{ count, select, 1 {1 aygıtı} other {# aygıtı} } sil", + "delete-devices-text": "UYARI: Onaylandıktan sonra tüm seçili aygıtlar ve ilişkili verileri geri yüklenemez şekilde silinecek.", + "unassign-device-title": "'{{deviceName}}' isimli aygıtın atamasını kaldırmak istediğinize emin misiniz?", + "unassign-device-text": "Onaylandıktan sonra aygıtın ataması kaldırılacak ve kullanıcı grubu tarafından erişilemez olacak.", + "unassign-device": "Aygıt atamasını kaldır", + "unassign-devices-title": "{ count, select, 1 {1 aygıtın} other {# aygıtın} } atamasını kaldırmak istediğinize emin misiniz?", + "unassign-devices-text": "Onaylandıktan sonra seçili aygıtların atamaları kaldırılacak ve kullanıcı grubu tarafından erişilemez olacak.", + "device-credentials": "Aygıt Kimlik Bilgileri", + "credentials-type": "Kimlik Bilgi Türü", + "access-token": "Erişim şifresi", + "access-token-required": "Erişim şifresi gerekli.", + "access-token-invalid": "Erişim şifresi uzunluğu 1 ile 20 karakter arasında olmalıdır.", + "rsa-key": "RSA açık anahtarı", + "rsa-key-required": "RSA açık anahtarı gerekli.", + "secret": "Secret", + "secret-required": "Secret gerekli.", + "device-type": "Aygıt Türü", + "device-type-required": "Aygıt türü gereli.", + "select-device-type": "Aygıt türü seç", + "enter-device-type": "Aygıt türü gir", + "any-device": "Herhangi bir aygıt", + "no-device-types-matching": "'{{entitySubtype}}' ile eşleşen aygıt türü bulunamadı.", + "device-type-list-empty": "Hiçbir aygıt türü seçilmedi.", + "device-types": "Aygıt türleri", + "name": "İsim", + "name-required": "İsim gerekli.", + "description": "Açıklama", + "events": "Olaylar", + "details": "Detaylar", + "copyId": "Aygıt kimliğini kopyala", + "copyAccessToken": "Erişim şifresini kopyala", + "idCopiedMessage": "Aygıt kimliği panoya kopyalandı.", + "accessTokenCopiedMessage": "Aygıt erişim şifresi panoya kopyalandı", + "assignedToCustomer": "Kullanıcı Grubuna atandı", + "unable-delete-device-alias-title": "Aygıt kısa adı silinemedi", + "unable-delete-device-alias-text": "Aygıt kısa adı('{{deviceAlias}}'), şu göstergeler tarafından kullanıldığı için silinemedi:
{{widgetsList}}", + "is-gateway": "Ağ geçidi mi?", + "public": "Açık", + "device-public": "Aygıt açık", + "select-device": "Aygıt seç" }, "dialog": { - "close": "Ýletiþim kutusunu kapat" + "close": "Kapat" }, "error": { - "unable-to-connect": "Sunucuya baðlanýlamýyor! Lütfen Ýnternet baðlantýnýzý kontrol edin.", - "unhandled-error-code": "Ýþlenmemiþ hata kodu: {{errorCode}}", + "unable-to-connect": "Sunucuya bağlanamadı! Lütfen internet bağlantınızı kontrol edin.", + "unhandled-error-code": "İşlenmeyen hata koud: {{errorCode}}", "unknown-error": "Bilinmeyen hata" }, "entity": { - "entity": "Varlýk", - "entities": "Varlýklarý", - "aliases": "Varlýk takma adlarý", - "entity-alias": "Varlýk takma adý", - "unable-delete-entity-alias-title": "Varlýk takma adý silinemiyor", - "unable-delete-entity-alias-text": "Varlýk takma adý {{entityAlias}} ', þu widget (lar) tarafýndan kullanýldýðý þekliyle silinemez:
{{widgetsList}} ", - "duplicate-alias-error": "Yinelenen takma ad bulundu {{alias}} '... Entity takma adlar, gösterge panosunda benzersiz olmalýdýr. ", - "missing-entity-filter-error": "Diðer adlar için filtre eksik {{alias}}. ", - "configure-alias": "Yapýlandýrma {{alias}} takma ad", - "alias": "Alias", - "alias-required": "Varlýk takma adý gerekiyor.", - "remove-alias": "Varlýk takma adýný kaldýrma", - "add-alias": "Varlýk takma adý ekle", - "entity-list": "Varlýk listesi", - "entity-type": "Varlýk türü", - "entity-types": "Varlýk türleri", - "entity-type-list": "Varlýk türü listesi", - "any-entity": "Herhangi bir varlýk", - "enter-entity-type": "Varlýk türü girin", - "no-entities-matching": "{{Entity}} ile eþleþen hiçbir varlýk bulunamadý. ", - "no-entity-types-matching": "{{EntityType}} ile eþleþen hiçbir varlýk türü bulunamadý. ", - "name-starts-with": "Ýsim ile baþlar", + "entity": "Öğe", + "entities": "Öğeler", + "aliases": "Öğe kısa adları", + "entity-alias": "Öğe kısa adı", + "unable-delete-entity-alias-title": "Öğe kısa adı silinemedi", + "unable-delete-entity-alias-text": "Öğe kısa adı('{{entityAlias}}'), şu göstergeler tarafından kullanıldığı için silinemiyor:
{{widgetsList}}", + "duplicate-alias-error": "'{{alias}}' daha önce kaydedilmiş.
Öğe kısa adları kontrol paneli özelinde emsalsiz olmalı.", + "missing-entity-filter-error": "'{{alias}}' için filtre bulunmuyor.", + "configure-alias": "'{{alias}}' kısa adını yapılandır", + "alias": "Kısa ad", + "alias-required": "Öğe kısa adı gerekli.", + "remove-alias": "Öğe kısa adını kaldır", + "add-alias": "Öğe kısa adı ekle", + "entity-list": "Öğe listesi", + "entity-type": "Öğe türü", + "entity-types": "Öğe türleri", + "entity-type-list": "Öğe türü listesi", + "any-entity": "Herhangi bir öğe", + "enter-entity-type": "Öğe türü girin", + "no-entities-matching": "'{{entity}}' ile eşleşen öğe bulunamadı.", + "no-entity-types-matching": "'{{entityType}}' ile eşleşen öğe türü bulunamadı.", + "name-starts-with": "... ile başlayan isim", "use-entity-name-filter": "Filtre kullan", - "entity-list-empty": "Hiçbir varlýk seçilmedi.", - "entity-type-list-empty": "Hiçbir varlýk türü seçilmedi.", - "entity-name-filter-required": "Varlýk adý filtresi gerekli.", - "entity-name-filter-no-entity-matched": "{{Entity}} ile baþlayan hiçbir varlýk bulunamadý. ", - "all-subtypes": "Herþey", - "select-entities": "Öðeleri seç", - "no-aliases-found": "Takma ad bulunamadý", - "no-alias-matching": "'{{alias}} bulunamadý. ", - "create-new-alias": "Yeni bir tane oluþtur!", + "entity-list-empty": "Hiçbir öğe seçilmedi.", + "entity-type-list-empty": "Hiçbir öğe türü seçilmedi.", + "entity-name-filter-required": "Öğe ismi filtresi gerekli.", + "entity-name-filter-no-entity-matched": "'{{entity}}' ile başlayan hiçbir öğe bulunamadı.", + "all-subtypes": "Tümü", + "select-entities": "Öğeleri seç", + "no-aliases-found": "Hiçbir kısa ad bulunamadı.", + "no-alias-matching": "'{{alias}}' bulunamadı.", + "create-new-alias": "Yeni bir tane oluştur!", "key": "Anahtar", - "key-name": "Anahtar adý", - "no-keys-found": "Anahtar bulunamadý.", - "no-key-matching": "'{{anahtar bulunamadý.", - "create-new-key": "Yeni bir tane oluþtur!", + "key-name": "Anahtar adı", + "no-keys-found": "Hiçbir anahtar bulunamadı.", + "no-key-matching": "'{{key}}' bulunamadı.", + "create-new-key": "Yeni bir tane oluştur!", "type": "Tür", - "type-required": "Varlýk türü gerekli.", - "type-device": "Cihaz", - "type-devices": "Cihazlar", - "list-of-devices": "{sayým, çoðul, 1 {Bir cihaz} diðer {# cihazlarýn listesi}}", - "device-name-starts-with": "Ýsimleri '{{prefix}} ile baþlayan cihazlar ", - "type-asset": "Varlýk", - "type-assets": "Varlýklar", - "list-of-assets": "{count, plural, 1 {One asset} diðer {# asset}}", - "asset-name-starts-with": "Adlarý {{prefix}} ile baþlayan varlýklar ", - "type-entity-view": "Varlýk Görünümü", - "type-entity-views": "Varlýk Görünümleri", - "list-of-entity-views": "{count, çoðul, 1 {Bir varlýk görünümü} diðer {# varlýk görüntüleme}} listesi", - "entity-view-name-starts-with": "Adý {{önek}} ile baþlayan varlýk görünümleri", + "type-required": "Öğe türü gerekli.", + "type-device": "Aygıt", + "type-devices": "Aygıtlar", + "list-of-devices": "{ count, select, 1 {Bir aygıt} other {# Aygıtın Listesi} }", + "device-name-starts-with": "İsimleri '{{prefix}}' ile başlayan aygıtlar", + "type-asset": "Varlık", + "type-assets": "Varlıklar", + "list-of-assets": "{ count, select, 1 {Bir varlık} other {# Varlığın Listesi} }", + "asset-name-starts-with": "İsmi '{{prefix}}' ile başlayan varlıklar", + "type-entity-view": "Varlık Görünümü", + "type-entity-views": "Varlık Görünümleri", + "list-of-entity-views": "{count, çoğul, 1 {Bir varlık görünümü} diğer {# varlık görüntüleme}} listesi", + "entity-view-name-starts-with": "Adı {{önek}} ile başlayan varlık görünümleri", "type-rule": "Kural", "type-rules": "Kurallar", - "list-of-rules": "{count, çoðul, 1 {Bir kural} diðer {# kurallarýn}} listesi", - "rule-name-starts-with": "Ýsimleri {{prefix}} ile baþlayan kurallar", + "list-of-rules": "{ count, select, 1 {Bir kural} other {# Kuralın Listesi} }", + "rule-name-starts-with": "İsmi '{{prefix}}' ile başlayan kurallar", "type-plugin": "Eklenti", "type-plugins": "Eklentiler", - "list-of-plugins": "{count, çoðul, 1 {Bir eklenti} diðer {# eklenti listesi}}", - "plugin-name-starts-with": "Ýsimleri {{prefix}} ile baþlayan eklentiler", - "type-tenant": "Kiracý", - "type-tenants": "Kiracýlar", - "list-of-tenants": "{count, çoðul, 1 {Bir kiracý} diðer {# kiracýlarýn listesi}}", - "tenant-name-starts-with": "Ýsimleri {{prefix}} ile baþlayan kiracýlar, ", - "type-customer": "Müþteri", - "type-customers": "Müþteriler", - "list-of-customers": "{count, çoðul, 1 {Bir müþteri} diðer {# müþteri}} listesi", - "customer-name-starts-with": "Ýsimleri {{prefix}} ile baþlayan müþteriler,", - "type-user": "Kullanýcý", - "type-users": "Kullanýcýlar", - "list-of-users": "{count, çoðul, 1 {Bir kullanýcý} diðer {# user}} listesi", - "user-name-starts-with": "Ýsimleri {{prefix}} ile baþlayan kullanýcýlar", - "type-dashboard": "Pano", - "type-dashboards": "Gösterge tablolarý", - "list-of-dashboards": "{count, çoðul, 1 {Bir pano} Diðer {# panolarýn}}} listesi", - "dashboard-name-starts-with": "Ýsimleri {{prefix}} ile baþlayan panolar", + "list-of-plugins": "{ count, select, 1 {Bir eklenti} other {# Eklentinin Listesi} }", + "plugin-name-starts-with": "İsmi '{{prefix}}' ile başlayan eklentiler", + "type-tenant": "Tenant", + "type-tenants": "Tenantlar", + "list-of-tenants": "{ count, select, 1 {Bir tenant} other {# Tenantın Listesi} }", + "tenant-name-starts-with": "İsmi '{{prefix}}' ile başlayan tenantlar", + "type-customer": "Kullanıcı Grubu", + "type-customers": "Kullanıcı Grupları", + "list-of-customers": "{ count, select, 1 {Bir Kullanıcı Grubu} other {# Kullanıcı Grupları} }", + "customer-name-starts-with": "İsmi '{{prefix}}' ile başlayan Kullanıcı Grupları", + "type-user": "Kullanıcı", + "type-users": "Kullanıcılar", + "list-of-users": "{ count, select, 1 {Bir kullanıcı} other {# Kullanıcının Listesi} }", + "user-name-starts-with": "İsmi '{{prefix}}' ile başlayan kullanıcılar", + "type-dashboard": "Kontrol paneli", + "type-dashboards": "Kontrol panelleri", + "list-of-dashboards": "{ count, select, 1 {Bir kontrol paneli} other {# Kontrol Panelinin Listesi} }", + "dashboard-name-starts-with": "İsmi '{{prefix}}' ile başlayan kontrol panelleri", "type-alarm": "Alarm", "type-alarms": "Alarmlar", - "list-of-alarms": "{count, çoðul, 1 {Bir alarm} diðer {{# alarm}} listesi", - "alarm-name-starts-with": "Ýsimleri {{prefix}} ile baþlayan alarmlar", + "list-of-alarms": "{ count, select, 1 {Bir alarm} other {# Alarmın Listesi} }", + "alarm-name-starts-with": "İsmi '{{prefix}}' ile başlayan alarmlar", "type-rulechain": "Kural zinciri", "type-rulechains": "Kural zincirleri", - "list-of-rulechains": "{count, çoðul, 1 {Bir kural zinciri} diðer {# kural zincirinin listesi}}", - "rulechain-name-starts-with": "Ýsimleri {{prefix}} ile baþlayan kural zincirleri", - "type-rulenode": "Kural düðümü", - "type-rulenodes": "Kural düðümleri", - "list-of-rulenodes": "{count, çoðul, 1 {Bir kural node} diðer {# kural düðümünün listesi}}", - "rulenode-name-starts-with": "Ýsimleri '{{prefix}} ile baþlayan kural düðümleri", - "type-current-customer": "Mevcut Müþteri", - "search": "Varlýklar ara", - "selected-entities": "{count, çoðul, 1 {1 varlýk} diðer {# entities}} seçildi", - "entity-name": "Varlýk adý", - "details": "Varlýk ayrýntýlarý", - "no-entities-prompt": "Hiçbir varlýk bulunamadý", - "no-data": "Gösterilecek bilgi yok" + "list-of-rulechains": "{count, çoğul, 1 {Bir kural zinciri} diğer {# kural zincirinin listesi}}", + "rulechain-name-starts-with": "İsimleri {{prefix}} ile başlayan kural zincirleri", + "type-rulenode": "Kural düğümü", + "type-rulenodes": "Kural düğümleri", + "list-of-rulenodes": "{count, çoğul, 1 {Bir kural node} diğer {# kural düğümünün listesi}}", + "rulenode-name-starts-with": "İsimleri '{{prefix}} ile başlayan kural düğümleri", + "type-current-customer": "Mevcut Müşteri", + "search": "Öğeleri ara", + "selected-entities": "{ count, select, 1 {1 öğe} other {# öğe} } seçildi", + "entity-name": "Öğe adı", + "details": "Öğe detayları", + "no-entities-prompt": "Hiçbir öğe bulunamadı", + "no-data": "Görüntülenecek veri yok" }, "entity-view": { - "entity-view": "Varlýk Görünümü", - "entity-views": "Varlýk Görünümleri", - "management": "Varlýk Görünümü yönetimi", - "view-entity-views": "Varlýk Görünümlerini Görüntüle", - "entity-view-alias": "Varlýk Görünümü takma adý", - "aliases": "Varlýk Görünümü takma adlarý", - "no-alias-matching": "'{{alias}} bulunamadý. ", - "no-aliases-found": "Takma ad bulunamadý", - "no-key-matching": "'{{anahtar bulunamadý.", - "no-keys-found": "Anahtar bulunamadý.", - "create-new-alias": "Yeni bir tane oluþtur!", - "create-new-key": "Yeni bir tane oluþtur!", - "duplicate-alias-error": "Yinelenen takma ad bulundu {{alias}} '.. Entity View diðer adlar, gösterge panosunda benzersiz olmalýdýr. ", - "configure-alias": "Yapýlandýrma {{alias}} takma ad", - "no-entity-views-matching": "{{Entity}} ile eþleþen hiçbir varlýk yorumu bulunamadý. ", + "entity-view": "Varlık Görünümü", + "entity-views": "Varlık Görünümleri", + "management": "Varlık Görünümü yönetimi", + "view-entity-views": "Varlık Görünümlerini Görüntüle", + "entity-view-alias": "Varlık Görünümü takma adı", + "aliases": "Varlık Görünümü takma adları", + "no-alias-matching": "'{{alias}} bulunamadı. ", + "no-aliases-found": "Takma ad bulunamadı", + "no-key-matching": "'{{anahtar bulunamadı.", + "no-keys-found": "Anahtar bulunamadı.", + "create-new-alias": "Yeni bir tane oluştur!", + "create-new-key": "Yeni bir tane oluştur!", + "duplicate-alias-error": "Yinelenen takma ad bulundu {{alias}} '.. Entity View diğer adlar, gösterge panosunda benzersiz olmalıdır. ", + "configure-alias": "Yapılandırma {{alias}} takma ad", + "no-entity-views-matching": "{{entity}} ile eşleşen hiçbir varlık yorumu bulunamadı. ", "alias": "Alias", - "alias-required": "Varlýk Görünümü takma adý gerekiyor.", - "remove-alias": "Varlýk görünümü takma adýný kaldýr", - "add-alias": "Varlýk görünümü takma adý ekle", - "name-starts-with": "Varlýk Görünümü adý ile baþlýyor", - "entity-view-list": "Varlýk Görünümü listesi", + "alias-required": "Varlık Görünümü takma adı gerekiyor.", + "remove-alias": "Varlık görünümü takma adını kaldır", + "add-alias": "Varlık görünümü takma adı ekle", + "name-starts-with": "Varlık Görünümü adı ile başlıyor", + "entity-view-list": "Varlık Görünümü listesi", "use-entity-view-name-filter": "Filtre kullan", - "entity-view-list-empty": "Hiçbir varlýk görüþü seçilmedi.", - "entity-view-name-filter-required": "Varlýk görünüm adý filtresi gerekli.", - "entity-view-name-filter-no-entity-view-matched": "{{EntityView}} ile baþlayan hiçbir varlýk sayýsý bulunamadý.", - "add": "Varlýk Görünümü Ekle", - "assign-to-customer": "Müþteriye atama", - "assign-entity-view-to-customer": "Varlýk Görünümlerini Müþteriye Atama", - "assign-entity-view-to-customer-text": "Lütfen müþteriye atamak için varlýk görünümlerini seçin", - "no-entity-views-text": "Varlýk görüþü bulunamadý", - "assign-to-customer-text": "Lütfen varlýk görünümlerini atamak için müþteriyi seçin", - "entity-view-details": "Varlýk görünümü ayrýntýlarý", - "add-entity-view-text": "Yeni varlýk görünümü ekle", - "delete": "Varlýk görünümünü sil", - "assign-entity-views": "Varlýk görünümleri atama", - "assign-entity-views-text": "Müþteriye {count, çoðul, 1 {1 entityView} diðer {# entityViews}} atayýn ", - "delete-entity-views": "Varlýk görünümlerini sil", - "unassign-from-customer": "Müþteriden atama", - "unassign-entity-views": "Varlýk görünümlerini atama", - "unassign-entity-views-action-title": "Müþteriden atama sayým, çoðul, 1 {1 entityView} diðer {# entityViews}}", - "assign-new-entity-view": "Yeni varlýk görünümü atama", - "delete-entity-view-title": "Varlýk görünümünü silmek istediðinizden emin misiniz?, {{EntityViewName}} '? ", - "delete-entity-view-text": "Dikkatli olun, onaylandýktan sonra varlýk görünümü ve ilgili tüm veriler kurtarýlamayacak.", - "delete-entity-views-title": "{Count, çoðul, 1 {1 entityView} diðer {# entityViews}} varlýk görünümüne sahip olmak istediðinizden emin misiniz?", - "delete-entity-views-action-title": "Sil {count, çoðul, 1 {1 entityView} diðer {# entityViews}}", - "delete-entity-views-text": "Dikkatli olun, onaylandýktan sonra tüm seçilen görünümler kaldýrýlacak ve ilgili tüm veriler kurtarýlamayacaktýr.", - "unassign-entity-view-title": "Varlýk görünümünün atamasýný kaldýrmak istediðinizden emin misiniz? {{EntityViewName}} '? ", - "unassign-entity-view-text": "Onaydan sonra varlýk görünümü atanmamýþ olacak ve müþteri tarafýndan eriþilemeyecektir.", - "unassign-entity-view": "Varlýk görünümünün atamasýný kaldýr", - "unassign-entity-views-title": "Sayým, çoðul, 1 {1 entityView} diðer {# entityViews}} hesabýnýn atamasýný kaldýrmak istediðinizden emin misiniz?", - "unassign-entity-views-text": "Onaylandýktan sonra, seçilen tüm öðe görünümleri atamadan kaldýrýlacak ve müþteri tarafýndan eriþilemeyecektir.", - "entity-view-type": "Varlýk Görünümü türü", - "entity-view-type-required": "Varlýk Görünümü türü gerekli.", - "select-entity-view-type": "Varlýk görüntüleme türünü seç", - "enter-entity-view-type": "Varlýk görüntüleme türünü girin", - "any-entity-view": "Herhangi bir varlýk görünümü", - "no-entity-view-types-matching": "{{EntitySubtype}} ile eþleþen hiçbir varlýk görüntüleme türü bulunamadý. ", - "entity-view-type-list-empty": "Hiçbir varlýk görünümü türü seçilmemiþ.", - "entity-view-types": "Varlýk Görünümü türleri", + "entity-view-list-empty": "Hiçbir varlık görüşü seçilmedi.", + "entity-view-name-filter-required": "Varlık görünüm adı filtresi gerekli.", + "entity-view-name-filter-no-entity-view-matched": "{{entityView}} ile başlayan hiçbir varlık sayısı bulunamadı.", + "add": "Varlık Görünümü Ekle", + "assign-to-customer": "Müşteriye atama", + "assign-entity-view-to-customer": "Varlık Görünümlerini Müşteriye Atama", + "assign-entity-view-to-customer-text": "Lütfen müşteriye atamak için varlık görünümlerini seçin", + "no-entity-views-text": "Varlık görüşü bulunamadı", + "assign-to-customer-text": "Lütfen varlık görünümlerini atamak için müşteriyi seçin", + "entity-view-details": "Varlık görünümü ayrıntıları", + "add-entity-view-text": "Yeni varlık görünümü ekle", + "delete": "Varlık görünümünü sil", + "assign-entity-views": "Varlık görünümleri atama", + "assign-entity-views-text": "Müşteriye {count, çoğul, 1 {1 entityView} diğer {# entityViews}} atayın ", + "delete-entity-views": "Varlık görünümlerini sil", + "unassign-from-customer": "Müşteriden atama", + "unassign-entity-views": "Varlık görünümlerini atama", + "unassign-entity-views-action-title": "Müşteriden atama sayım, çoğul, 1 {1 entityView} diğer {# entityViews}}", + "assign-new-entity-view": "Yeni varlık görünümü atama", + "delete-entity-view-title": "Varlık görünümünü silmek istediğinizden emin misiniz?, {{entityViewName}} '? ", + "delete-entity-view-text": "Dikkatli olun, onaylandıktan sonra varlık görünümü ve ilgili tüm veriler kurtarılamayacak.", + "delete-entity-views-title": "{count, çoğul, 1 {1 entityView} diğer {# entityViews}} varlık görünümüne sahip olmak istediğinizden emin misiniz?", + "delete-entity-views-action-title": "Sil {count, çoğul, 1 {1 entityView} diğer {# entityViews}}", + "delete-entity-views-text": "Dikkatli olun, onaylandıktan sonra tüm seçilen görünümler kaldırılacak ve ilgili tüm veriler kurtarılamayacaktır.", + "unassign-entity-view-title": "Varlık görünümünün atamasını kaldırmak istediğinizden emin misiniz? {{entityViewName}} '? ", + "unassign-entity-view-text": "Onaydan sonra varlık görünümü atanmamış olacak ve müşteri tarafından erişilemeyecektir.", + "unassign-entity-view": "Varlık görünümünün atamasını kaldır", + "unassign-entity-views-title": "Sayım, çoğul, 1 {1 entityView} diğer {# entityViews}} hesabının atamasını kaldırmak istediğinizden emin misiniz?", + "unassign-entity-views-text": "Onaylandıktan sonra, seçilen tüm öğe görünümleri atamadan kaldırılacak ve müşteri tarafından erişilemeyecektir.", + "entity-view-type": "Varlık Görünümü türü", + "entity-view-type-required": "Varlık Görünümü türü gerekli.", + "select-entity-view-type": "Varlık görüntüleme türünü seç", + "enter-entity-view-type": "Varlık görüntüleme türünü girin", + "any-entity-view": "Herhangi bir varlık görünümü", + "no-entity-view-types-matching": "{{entitySubtype}} ile eşleşen hiçbir varlık görüntüleme türü bulunamadı. ", + "entity-view-type-list-empty": "Hiçbir varlık görünümü türü seçilmemiş.", + "entity-view-types": "Varlık Görünümü türleri", "name": "Ad", - "name-required": "Ýsim gerekli.", - "description": "Açýklama", + "name-required": "İsim gerekli.", + "description": "Açıklama", "events": "Etkinlikler", - "details": "Ayrýntýlar", - "copyId": "Varlýk görüntüleme kimliðini kopyala", - "assignedToCustomer": "Müþteriye atandý", - "unable-entity-view-device-alias-title": "Varlýk görünümü takma adý silinemiyor", - "unable-entity-view-device-alias-text": "Cihaz takma adý {{entityViewAlias}} ', aþaðýdaki widget (lar) tarafýndan kullanýldýðý þekliyle silinemez:
{{widgetsList}} ", - "select-entity-view": "Varlýk görünümünü seç", - "make-public": "Varlýðý herkese görünür yap", + "details": "Ayrıntılar", + "copyId": "Varlık görüntüleme kimliğini kopyala", + "assignedToCustomer": "Müşteriye atandı", + "unable-entity-view-device-alias-title": "Varlık görünümü takma adı silinemiyor", + "unable-entity-view-device-alias-text": "Cihaz takma adı {{entityViewAlias}} ', aşağıdaki widget (lar) tarafından kullanıldığı şekliyle silinemez:
{{widgetsList}} ", + "select-entity-view": "Varlık görünümünü seç", + "make-public": "Varlığı herkese görünür yap", "start-ts": "Ts", "end-ts": "End ts" }, "event": { - "event-type": "Etkinlik tipi", + "event-type": "Olay türü", "type-error": "Hata", - "type-lc-event": "Yaþam döngüsü etkinliði", - "type-stats": "Ýstatistik", - "type-debug-rule-node": "Hata ayýklama", - "type-debug-rule-chain": "Hata ayýklama", - "no-events-prompt": "Etkinlik bulunamadý", + "type-lc-event": "Yaşam döngüsü olayı", + "type-stats": "İstatistikler", + "type-debug-rule-node": "Hata ayıklama", + "type-debug-rule-chain": "Hata ayıklama", + "no-events-prompt": "Hiçbir olay bulunamadı", "error": "Hata", "alarm": "Alarm", - "event-time": "Etkinlik zamaný", + "event-time": "Olay zamanı", "server": "Sunucu", - "body": "Vücut", + "body": "İçerik //(Body)", "method": "Yöntem", "type": "Tür", - "entity": "Varlýk", - "message-id": "Mesaj Kimliði", + "entity": "Varlık", + "message-id": "Mesaj Kimliği", "message-type": "Mesaj tipi", "data-type": "Veri tipi", - "relation-type": "Ýliþki Türü", + "relation-type": "İlişki Türü", "metadata": "Meta veri", "data": "Veri", - "event": "Etkinlik", + "event": "Olay", "status": "Durum", - "success": "Baþarý", - "failed": "Baþarýsýz oldu", - "messages-processed": "Mesajlar iþlendi", - "errors-occurred": "Hatalar oluþtu" + "success": "Başarı", + "failed": "Başarısız oldu", + "messages-processed": "Mesajlar işlendi", + "errors-occurred": "Hatalar oluştu" }, "extension": { - "extensions": "Uzantýlar", - "selected-extensions": "{count, çoðul, 1 {1 uzantý} diðer {# extensions}} seçildi", + "extensions": "Uzantılar", + "selected-extensions": "{count, çoğul, 1 {1 uzantı} diğer {# extensions}} seçildi", "type": "Tür", "key": "Anahtar", - "value": "Deðer", - "id": "ÝD", - "extension-id": "Uzantý kimliði", + "value": "Değer", + "id": "İD", + "extension-id": "Uzantı kimliği", "extension-type": "Uzatma tipi", "transformer-json": "JSON *", - "unique-id-required": "Mevcut uzantý kimliði zaten mevcut.", - "delete": "Uzantýyý sil", - "add": "Uzantý eklemek", - "edit": "Uzantýyý düzenle", - "delete-extension-title": "{{ExtensionId}} uzantýsýný silmek istediðinizden emin misiniz? ", - "delete-extension-text": "Dikkatli olun, onaylamadan sonra uzantý ve ilgili tüm veriler kurtarýlamaz.", - "delete-extensions-title": "{Count, çoðul, 1 {1 uzantý} diðer {# extensions}} silmek istediðinizden emin misiniz?", - "delete-extensions-text": "Dikkatli olun, onaylandýktan sonra tüm seçilen uzantýlar kaldýrýlacak.", - "converters": "Dönüþtürücü", - "converter-id": "Dönüþtürücü kimliði", - "configuration": "Yapýlandýrma", - "converter-configurations": "Dönüþtürücü yapýlandýrmalarý", + "unique-id-required": "Mevcut uzantı kimliği zaten mevcut.", + "delete": "Uzantıyı sil", + "add": "Uzantı eklemek", + "edit": "Uzantıyı düzenle", + "delete-extension-title": "{{ExtensionId}} uzantısını silmek istediğinizden emin misiniz? ", + "delete-extension-text": "Dikkatli olun, onaylamadan sonra uzantı ve ilgili tüm veriler kurtarılamaz.", + "delete-extensions-title": "{Count, çoğul, 1 {1 uzantı} diğer {# extensions}} silmek istediğinizden emin misiniz?", + "delete-extensions-text": "Dikkatli olun, onaylandıktan sonra tüm seçilen uzantılar kaldırılacak.", + "converters": "Dönüştürücü", + "converter-id": "Dönüştürücü kimliği", + "configuration": "Yapılandırma", + "converter-configurations": "Dönüştürücü yapılandırmaları", "token": "Güvenlik belirteci", - "add-converter": "Dönüþtürücü ekle", - "add-config": "Dönüþtürücü yapýlandýrmasý ekle", - "device-name-expression": "Cihaz adý ifadesi", + "add-converter": "Dönüştürücü ekle", + "add-config": "Dönüştürücü yapılandırması ekle", + "device-name-expression": "Cihaz adı ifadesi", "device-type-expression": "Cihaz tipi ifadesi", "custom": "Özel", "to-double": "Çifte", "transformer": "Transformer", "json-required": "Trafo jsonu gerekli.", - "json-parse": "Trafo json ayrýþtýrýlamýyor.", + "json-parse": "Trafo json ayrıştırılamıyor.", "attributes": "Öznitellikler", "add-attribute": "Özellik ekle", - "add-map": "Eþleme elemaný ekle", + "add-map": "Eşleme elemanı ekle", "timeseries": "Zaman serisi", "add-timeseries": "Zaman çizelgeleri ekle", "field-required": "Alan gereklidir", @@ -901,26 +901,26 @@ "add-broker": "Broker ekle", "host": "Host", "port": "Liman", - "port-range": "Liman 1'den 65535'e kadar olmalýdýr.", + "port-range": "Liman 1'den 65535'e kadar olmalıdır.", "ssl": "SSL", "credentials": "Kimlik bilgileri", - "username": "Kullanýcý adý", + "username": "Kullanıcı adı", "password": "Parola", - "retry-interval": "Milisaniye cinsinden tekrar deneme aralýðý", + "retry-interval": "Milisaniye cinsinden tekrar deneme aralığı", "anonymous": "Anonim", "basic": "Temel", "pem": "PEM", - "ca-cert": "CA sertifika dosyasý *", + "ca-cert": "CA sertifika dosyası *", "private-key": "Özel anahtar dosya *", - "cert": "Sertifika dosyasý *", + "cert": "Sertifika dosyası *", "no-file": "Dosya seçilmedi.", - "drop-file": "Bir dosya býrakýn veya yüklenecek bir dosya seçmek için týklayýn.", + "drop-file": "Bir dosya bırakın veya yüklenecek bir dosya seçmek için tıklayın.", "mapping": "Mapping", "topic-filter": "Konu filtresi", - "converter-type": "Dönüþtürücü tipi", + "converter-type": "Dönüştürücü tipi", "converter-json": "Json", - "json-name-expression": "Cihaz adý json ifadesi", - "topic-name-expression": "Cihaz adý konu ifadesi", + "json-name-expression": "Cihaz adı json ifadesi", + "topic-name-expression": "Cihaz adı konu ifadesi", "json-type-expression": "Cihaz tipi json ifadesi", "topic-type-expression": "Cihaz tipi konu ifadesi", "attribute-key-expression": "Öznitelik anahtar ifadesi", @@ -929,35 +929,35 @@ "request-id-expression": "Kimlik ifadesi iste", "request-id-json-expression": "Kimlik json ifadesi iste", "request-id-topic-expression": "Kimlik konu ifadesini isteyin", - "response-topic-expression": "Yanýt konusu ifadesi", - "value-expression": "Deðer ifadesi", + "response-topic-expression": "Yanıt konusu ifadesi", + "value-expression": "Değer ifadesi", "topic": "Konu", - "timeout": "Zaman aþýmý milisaniye cinsinden", - "converter-json-required": "Dönüþtürücü json gerekli.", - "converter-json-parse": "Dönüþtürücü json ayrýþtýrýlamýyor.", + "timeout": "Zaman aşımı milisaniye cinsinden", + "converter-json-required": "Dönüştürücü json gerekli.", + "converter-json-parse": "Dönüştürücü json ayrıştırılamıyor.", "filter-expression": "Filtre ifadesi", - "connect-requests": "Ýstekleri baðla", - "add-connect-request": "Baðlantý talebi ekle", - "disconnect-requests": "Ýstekleri kes", - "add-disconnect-request": "Baðlantýyý kes isteði ekle", + "connect-requests": "İstekleri bağla", + "add-connect-request": "Bağlantı talebi ekle", + "disconnect-requests": "İstekleri kes", + "add-disconnect-request": "Bağlantıyı kes isteği ekle", "attribute-requests": "Özellik istekleri", - "add-attribute-request": "Özellik isteði ekle", + "add-attribute-request": "Özellik isteği ekle", "attribute-updates": "Öznitelik güncellemeleri", "add-attribute-update": "Özellik güncellemesi ekle", - "server-side-rpc": "Sunucu tarafý RPC", - "add-server-side-rpc-request": "Sunucu tarafý RPC isteði ekle", - "device-name-filter": "Cihaz adý filtresi", + "server-side-rpc": "Sunucu tarafı RPC", + "add-server-side-rpc-request": "Sunucu tarafı RPC isteği ekle", + "device-name-filter": "Cihaz adı filtresi", "attribute-filter": "Özellik filtresi", "method-filter": "Yöntem filtresi", "request-topic-expression": "Konu ifadesi iste", - "response-timeout": "Milisaniye cinsinden yanýt zaman aþýmý", + "response-timeout": "Milisaniye cinsinden yanıt zaman aşımı", "topic-expression": "Konu ifadesi", - "client-scope": "Müþteri kapsamý", + "client-scope": "Müşteri kapsamı", "add-device": "Cihaz ekle", "opc-server": "Sunucular", "opc-add-server": "Sunucu ekle", "opc-add-server-prompt": "Lütfen sunucu ekle", - "opc-application-name": "Uygulama Adý", + "opc-application-name": "Uygulama Adı", "opc-application-uri": "Uygulama uri", "opc-scan-period-in-seconds": "Saniyeler içinde tarama süresi", "opc-security": "Güvenlik", @@ -968,578 +968,578 @@ "opc-keystore-location": "Yer *", "opc-keystore-password": "Parola", "opc-keystore-alias": "Alias", - "opc-keystore-key-password": "Anahtar þifre", - "opc-device-node-pattern": "Cihaz düðümü modeli", - "opc-device-name-pattern": "Cihaz adý deseni", + "opc-keystore-key-password": "Anahtar şifre", + "opc-device-node-pattern": "Cihaz düğümü modeli", + "opc-device-name-pattern": "Cihaz adı deseni", "modbus-server": "Sunucular / köle", "modbus-add-server": "Sunucu ekle / köle", "modbus-add-server-prompt": "Lütfen sunucu / slave ekle", - "modbus-transport": "Taþýma", - "modbus-port-name": "Seri port adý", + "modbus-transport": "Taşıma", + "modbus-port-name": "Seri port adı", "modbus-encoding": "Kodlama", "modbus-parity": "Parite", - "modbus-baudrate": "Baud hýzý", + "modbus-baudrate": "Baud hızı", "modbus-databits": "Veri bitleri", "modbus-stopbits": "Bitleri durdur", - "modbus-databits-range": "Veri bitleri 7 ila 8 arasýnda olmalýdýr", - "modbus-stopbits-range": "Durma bitleri 1'den 2'ye kadar olmalýdýr.", - "modbus-unit-id": "Birim Kimliði", - "modbus-unit-id-range": "Birim numarasý 1 ile 247 arasýnda olmalýdýr.", - "modbus-device-name": "Cihaz adý", + "modbus-databits-range": "Veri bitleri 7 ila 8 arasında olmalıdır", + "modbus-stopbits-range": "Durma bitleri 1'den 2'ye kadar olmalıdır.", + "modbus-unit-id": "Birim Kimliği", + "modbus-unit-id-range": "Birim numarası 1 ile 247 arasında olmalıdır.", + "modbus-device-name": "Cihaz adı", "modbus-poll-period": "Anket dönemi (ms)", "modbus-attributes-poll-period": "Nitelikler yoklama süresi (ms)", "modbus-timeseries-poll-period": "Timeseries anket süresi (ms)", - "modbus-poll-period-range": "Anket dönemi pozitif deðer olmalý", + "modbus-poll-period-range": "Anket dönemi pozitif değer olmalı", "modbus-tag": "Etiket", - "modbus-function": "Ýþlev", - "modbus-register-address": "Kayýt adresi", - "modbus-register-address-range": "Kayýt adresi 0 ile 65535 arasýnda olmalýdýr.", + "modbus-function": "İşlev", + "modbus-register-address": "Kayıt adresi", + "modbus-register-address-range": "Kayıt adresi 0 ile 65535 arasında olmalıdır.", "modbus-register-bit-index": "Bit endeksi", - "modbus-register-bit-index-range": "Bit endeksi 0 ile 15 arasýnda olmalýdýr", - "modbus-register-count": "Kayýt sayýsý", - "modbus-register-count-range": "Kayýt sayýsý pozitif bir deðer olmalýdýr.", - "modbus-byte-order": "Bayt sýrasý", + "modbus-register-bit-index-range": "Bit endeksi 0 ile 15 arasında olmalıdır", + "modbus-register-count": "Kayıt sayısı", + "modbus-register-count-range": "Kayıt sayısı pozitif bir değer olmalıdır.", + "modbus-byte-order": "Bayt sırası", "sync": { "status": "Durum", "sync": "Senkronizasyon", - "not-sync": "Eþitleme", - "last-sync-time": "Son senkronizasyon zamaný", - "not-available": "Müsait deðil" + "not-sync": "Eşitleme", + "last-sync-time": "Son senkronizasyon zamanı", + "not-available": "Müsait değil" }, - "export-extensions-configuration": "Ýhracat uzantýlarý yapýlandýrmasý", - "import-extensions-configuration": "Uzantýlarýný içe aktarma yapýlandýrmasý", - "import-extensions": "Uzantýlarý içe aktar", - "import-extension": "Uzantý içe aktar", - "export-extension": "Ýhracat uzantýsý", - "file": "Uzantýlar dosyasý", - "invalid-file-error": "Geçersiz uzantý dosyasý" + "export-extensions-configuration": "İhracat uzantıları yapılandırması", + "import-extensions-configuration": "Uzantılarını içe aktarma yapılandırması", + "import-extensions": "Uzantıları içe aktar", + "import-extension": "Uzantı içe aktar", + "export-extension": "İhracat uzantısı", + "file": "Uzantılar dosyası", + "invalid-file-error": "Geçersiz uzantı dosyası" }, "fullscreen": { - "expand": "Tam ekrana geniþlet", - "exit": "Tam ekrandan çýk", - "toggle": "Tam ekran modunu deðiþtir", + "expand": "Tam ekran yap", + "exit": "Tam ekrandan çık", + "toggle": "Tam ekran modu aç/kapat", "fullscreen": "Tam ekran" }, "function": { - "function": "Ýþlev" + "function": "Fonksiyon" }, "grid": { - "delete-item-title": "Bu maddeyi silmek istediðinden emin misin?", - "delete-item-text": "Dikkatli olun, onaylandýktan sonra bu öðe ve ilgili tüm veriler kurtarýlamaz.", - "delete-items-title": "{Count, çoðul, 1 {1 item} diðer {# items}} silmek istediðinizden emin misiniz?", - "delete-items-action-title": "Sil {count, çoðul, 1 {1 öðe} diðer {# items}}", - "delete-items-text": "Dikkatli olun, onaylandýktan sonra tüm seçilen öðeler silinecek ve ilgili tüm veriler kurtarýlamayacaktýr.", - "add-item-text": "Yeni öðe ekle", - "no-items-text": "Hiç bir öðe bulunamadý", - "item-details": "Ürün detaylarý", - "delete-item": "Öðeyi silmek", - "delete-items": "Ürünleri sil", - "scroll-to-top": "Baþa kaydýr" + "delete-item-title": "Bu öğeyi silmek istediğinizden emin misiniz?", + "delete-item-text": "UYARI: Onayladıktan sonra bu öğe ve ilişkili tüm verileri geri yüklenemez şekilde silinecektir.", + "delete-items-title": "{ count, select, 1 {1 öğeyi} other {# öğeyi} } silmek istediğinizden emin misiniz?", + "delete-items-action-title": "{ count, select, 1 {1 öğeyi} other {# öğeyi} } sil", + "delete-items-text": "UYARI: Onayladıktan sonra tüm seçili öğeler ve ilişkili tüm verileri geri yüklenemez şekilde silinecektir.", + "add-item-text": "Yeni öğe ekle", + "no-items-text": "Hiç bir öğe bulunamadı", + "item-details": "Öğe detayları", + "delete-item": "Öğeyi sil", + "delete-items": "Öğeleri sil", + "scroll-to-top": "Üste kaydır" }, "help": { - "goto-help-page": "Yardým sayfasýna git" + "goto-help-page": "Yardım sayfasına git" }, "home": { - "home": "Ev", + "home": "Ana sayfa", "profile": "Profil", - "logout": "Çýkýþ Yap", + "logout": "Çıkış", "menu": "Menü", "avatar": "Avatar", - "open-user-menu": "Kullanýcý menüsünü aç" + "open-user-menu": "Kullanıcı menüsünü aç" }, "import": { - "no-file": "Dosya seçilmedi", - "drop-file": "Bir JSON dosyasýný indirin veya yüklemek için bir dosya seçmek için týklayýn." + "no-file": "Hiçbir dosya seçilmedi", + "drop-file": "Bir JSON dosyası bırakın veya yüklenecek bir dosyayı seçmek için tıklayın." }, "item": { - "selected": "Seçilmiþ" + "selected": "Seçildi" }, "js-func": { - "no-return-error": "Ýþlev deðer döndürmeli!", - "return-type-mismatch": "Ýþlev '{{type}}' tipinin deðerini döndürmelidir!", + "no-return-error": "Fonksiyon bir değer dönmeli!", + "return-type-mismatch": "Fonksiyon '{{type}}' türünde bir değer dönmeli!", "tidy": "Düzenli" }, "key-val": { "key": "Anahtar", - "value": "Deðer", - "remove-entry": "Giriþi kaldýr", - "add-entry": "Giriþ ekle", - "no-data": "Giriþ yok" + "value": "Değer", + "remove-entry": "Girişi kaldır", + "add-entry": "Giriş ekle", + "no-data": "Giriş yok" }, "layout": { - "layout": "Düzen", - "manage": "Düzenleri yönet", - "settings": "Yerleþim ayarlarý", + "layout": "Arayüz Düzeni", + "manage": "Arayüz düzenini yönet", + "settings": "Arayüz düzeni ayarları", "color": "Renk", "main": "Ana", - "right": "Sað", - "select": "Hedef yerleþimini seç" + "right": "Sağ", + "select": "Hedef düzen seç" }, "legend": { - "position": "Efsane pozisyonu", - "show-max": "Maksimum deðeri göster", - "show-min": "Min deðerini göster", - "show-avg": "Ortalama deðeri göster", - "show-total": "Toplam deðeri göster", - "settings": "Açýklama ayarlarý", + "position": "Lejant konumu", + "show-max": "Maksimum değeri göster", + "show-min": "Minimum değeri göster", + "show-avg": "Ortalama değeri göster", + "show-total": "Toplam değeri göster", + "settings": "Lejant ayarları", "min": "min", - "max": "max", - "avg": "avg", - "total": "Genel Toplam" + "max": "maks", + "avg": "ort.", + "total": "toplam" }, "login": { "login": "Oturum aç", - "request-password-reset": "Þifre sýfýrlama isteði", - "reset-password": "Þifreyi yenile", - "create-password": "Þifre oluþtur", - "passwords-mismatch-error": "Girilen þifreler ayný olmalýdýr!", - "password-again": "Þifre Tekrar", - "sign-in": "Lütfen giriþ yapýn", - "username": "Kullanýcý adý (email)", - "remember-me": "Beni hatýrla", - "forgot-password": "Parolanýzý mý unuttunuz?", - "password-reset": "Parola sýfýrlama", - "new-password": "Yeni Þifre", - "new-password-again": "Yeni Þifre Tekrar", - "password-link-sent-message": "Þifre sýfýrlama baðlantýsý baþarýyla gönderildi!", + "request-password-reset": "Parola Sıfırlama İsteği Gönder", + "reset-password": "Parola Sıfırla", + "create-password": "Parola Oluştur", + "passwords-mismatch-error": "Girilen parolalar eşleşmeli!", + "password-again": "Parola tekrarı", + "sign-in": "Lütfen girişi yapın", + "username": "Kullanıcı adı (e-posta)", + "remember-me": "Beni hatırla", + "forgot-password": "Parolamı unuttum", + "password-reset": "Parola sıfırla", + "new-password": "Yeni parola", + "new-password-again": "Yeni parola tekrarı", + "password-link-sent-message": "Parola sıfırlama e-postası başarıyla gönderildi!", "email": "E-posta" }, "position": { "top": "Üst", "bottom": "Alt", - "left": "Ayrýldý", - "right": "Sað" + "left": "Sol", + "right": "Sağ" }, "profile": { "profile": "Profil", - "change-password": "Þifre deðiþtir", - "current-password": "Þimdiki Þifre" + "change-password": "Şifre değiştir", + "current-password": "Şimdiki şifre" }, "relation": { - "relations": "Ýliþkiler", - "direction": "Yön", + "relations": "İlişkiler", + "direction": "Yönelim", "search-direction": { - "FROM": "Kimden", - "TO": "Alýcý" + "FROM": "KAYNAK", + "TO": "HEDEF" }, "direction-type": { - "FROM": "den", - "TO": "to" + "FROM": "kaynak", + "TO": "hedef" }, - "from-relations": "Giden iliþkiler", - "to-relations": "Gelen iliþkiler", - "selected-relations": "{count, çoðul, 1 {1 iliþki} diðer {# relations}} seçildi", + "from-relations": "Giden ilişkiler", + "to-relations": "Gelen ilişkiler", + "selected-relations": "{ count, select, 1 {1 ilişki} other {# ilişki} } seçildi", "type": "Tür", - "to-entity-type": "Varlýk türüne", - "to-entity-name": "Varlýk adýna", - "from-entity-type": "Varlýk türünden", - "from-entity-name": "Varlýk adýndan", - "to-entity": "Varlýk", - "from-entity": "Varlýktan", - "delete": "Ýliþkisi sil", - "relation-type": "Ýliþki türü", - "relation-type-required": "Ýliþki türü gerekli.", + "to-entity-type": "Hedef Öğe Türü", + "to-entity-name": "Hedef Öğe Adı", + "from-entity-type": "Kaynak Öğe Türü", + "from-entity-name": "Kaynak Öğe Adı", + "to-entity": "Hedef Öğe", + "from-entity": "Kaynak Öğe", + "delete": "İlişkiyi sil", + "relation-type": "İlişki türü", + "relation-type-required": "İlişki türü gerekli.", "any-relation-type": "Her hangi bir tür", - "add": "Ýliþki ekle", - "edit": "Ýliþkisi düzenle", - "delete-to-relation-title": "{{EntityName}} varlýðýna iliþkin iliþkiyi silmek istediðinizden emin misiniz? ", - "delete-to-relation-text": "Doðrulamadan sonra, varlýðýn {{entityName}} öðesinin mevcut varlýktan alakasýz olacaðýndan emin olun. ", - "delete-to-relations-title": "{Count, çoðul, 1 {1 iliþki} diðer {# relations}} silmek istediðinizden emin misiniz?", - "delete-to-relations-text": "Dikkatli olun, onaylandýktan sonra tüm seçilen iliþkiler kaldýrýlacak ve ilgili varlýklar mevcut varlýk ile ilgisiz olacaktýr.", - "delete-from-relation-title": "{{EntityName}} varlýðýndan iliþkiyi silmek istediðinizden emin misiniz? ", - "delete-from-relation-text": "Doðrulama varlýðýnýn, {{entityName}} kuruluþundan alakasýz olacaðýndan emin olun.", - "delete-from-relations-title": "{Count, çoðul, 1 {1 iliþki} diðer {# relations}} silmek istediðinizden emin misiniz?", - "delete-from-relations-text": "Dikkatli olun, onaylandýktan sonra tüm seçilen iliþkiler kaldýrýlacak ve mevcut varlýk ilgili varlýklardan ilgisiz olacaktýr.", - "remove-relation-filter": "Ýliþki filtresini kaldýr", - "add-relation-filter": "Ýliþki filtresi ekle", - "any-relation": "Herhangi bir iliþki", - "relation-filters": "Ýliþki filtreleri", + "add": "İlişki ekle", + "edit": "İlişki düzenle", + "delete-to-relation-title": "'{{entityName}}' öğesine olan ilişkiyi silmek istediğinize emin misiniz?", + "delete-to-relation-text": "UYARI: Onaylandıktan sonra '{{entityName}}' öğesinin şimdiki öğeyle olan ilişkisi sona erecektir.", + "delete-to-relations-title": "{ count, select, 1 {1 ilişkiyi} other {# ilişkiyi} } silmek istediğinize emin misiniz?", + "delete-to-relations-text": "UYARI: Onaylandıktan sonra tüm seçili ilişkiler kaldırılacaktır ve ilgili öğelerin şimdiki öğeyle ilişkisi sona erecektir.", + "delete-from-relation-title": "'{{entityName}}' öğesinden ilişkiyi silmek istediğinize emin misiniz?", + "delete-from-relation-text": "UYARI: Onaylandıktan sonra şimdiki öğenin '{{entityName}}' öğesiyle ilişkisi sonlandırılacaktır.", + "delete-from-relations-title": "{ count, select, 1 {1 ilişkiyi} other {# ilişkiyi} } silmek istediğinize emin misiniz?", + "delete-from-relations-text": "UYARI: Onaylandıktan sonra tüm seçili ilişkiler kaldırılacak ve şimdiki öğenin ilgili tüm öğelerle ilişkisi sona erecektir.", + "remove-relation-filter": "İlişki filtresini kaldır", + "add-relation-filter": "İlişkisi ekle", + "any-relation": "Herhangi bir ilişki", + "relation-filters": "İlişki filtreleri", "additional-info": "Ek bilgi (JSON)", - "invalid-additional-info": "Ek bilgi json ayrýþtýrýlamýyor." + "invalid-additional-info": "Ek bilgi JSON'ı parse edilip işlenemedi." }, "rulechain": { - "rulechain": "Kural zinciri", - "rulechains": "Kural zincirleri", + "rulechain": "Kural", + "rulechains": "Kurallar", "root": "Kök", - "delete": "Kural zincirini sil", - "name": "Ad", - "name-required": "Ýsim gerekli.", - "description": "Açýklama", - "add": "Kural Zinciri Ekleme", + "delete": "Kuralı sil", + "name": "İsim", + "name-required": "İsim gerekli.", + "description": "Açıklama", + "add": "Kural Ekle", "set-root": "Kural zincirinin kökü yap", - "set-root-rulechain-title": "Kural zincirini {{ruleChainName}} root? Yapmak istediðinizden emin misiniz?", - "set-root-rulechain-text": "Onaydan sonra kural zinciri kökleþecek ve gelen tüm iletilerle ilgilenecek.", - "delete-rulechain-title": "Kural zincirini {{ruleChainName}} silmek istediðinizden emin misiniz?", - "delete-rulechain-text": "Dikkatli olun, onaylamadan sonra kural zinciri ve ilgili tüm veriler kurtarýlamaz.", - "delete-rulechains-title": "{Count, çoðul, 1 {1 kural zinciri} diðer {# kural zincirleri}} silmek istediðinizden emin misiniz?", - "delete-rulechains-action-title": "Sil {count, çoðul, 1 {1 kural zinciri} diðer {# kural zincirleri}}", - "delete-rulechains-text": "Dikkatli olun, onaylandýktan sonra seçilen tüm kural zincirleri silinecek ve ilgili tüm veriler kurtarýlamayacaktýr.", - "add-rulechain-text": "Yeni kural zinciri ekle", - "no-rulechains-text": "Kural zinciri bulunamadý", - "rulechain-details": "Kural zinciri detaylarý", - "details": "Ayrýntýlar", - "events": "Etkinlikler", + "set-root-rulechain-title": "Kural zincirini {{ruleChainName}} root? Yapmak istediğinizden emin misiniz?", + "set-root-rulechain-text": "Onaydan sonra kural zinciri kökleşecek ve gelen tüm iletilerle ilgilenecek.", + "delete-rulechain-title": "'{{ruleName}}' isimli kuralı silmek istediğinize emin misiniz?", + "delete-rulechain-text": "UYARI: Onaylandıktan sonra kural ve ilişkili tüm veriler geri yüklenemez şekilde silinecektir.", + "delete-rulechains-title": "{ count, select, 1 {1 kuralı} other {# kuralı} } sikmek istediğinize emin misiniz?", + "delete-rulechains-action-title": "{ count, select, 1 {1 kuralı} other {# kuralı} sil}", + "delete-rulechains-text": "UYARI: Onaylandıktan sonra seçili tüm kurallar ve ilişkili tüm veriler geri yüklenemez şekilde silinecektir.", + "add-rulechain-text": "Yeni kural ekle", + "no-rulechains-text":"Hiçbir kural bulunamadı", + "rulechain-details": "Kural detayları", + "details": "Detaylar", + "events": "Olaylar", "system": "Sistem", - "import": "Kural zincirini içe aktar", - "export": "Kural zinciri dýþa aktar", - "export-failed-error": "Kural zinciri dýþa aktarýlamadý: {{error}}", - "create-new-rulechain": "Yeni kural zinciri oluþtur", - "rulechain-file": "Kural zinciri dosyasý", - "invalid-rulechain-file-error": "Kural zinciri içe aktarýlamýyor: Geçersiz kural zinciri veri yapýsý.", - "copyId": "Kural zinciri kimliðini kopyala", - "idCopiedMessage": "Kural zinciri kimliði panoya kopyalandý", - "select-rulechain": "Kural zincirini seç", - "no-rulechains-matching": "{{Entity}} ile eþleþen kural zinciri bulunamadý. ", - "rulechain-required": "Kural zinciri gerekli", + "import": "Kuralı içe aktar", + "export": "Kuralı dışa aktar", + "export-failed-error": "Kural dışa aktarılamadı: {{error}}", + "create-new-rule": "Yeni kural oluştur", + "rulechain-file": "Kural dosyası", + "invalid-rulechain-file-error": "Kural içe aktarılamadı: Geçersiz kural veri yapısı.", + "copyId": "Kural kimliğini kopyala", + "idCopiedMessage": "Kural kimliği panoya kopyalandı", + "select-rulechain": "Kural seç", + "no-rulechains-matching": "'{{entity}}' ile eşleşen kural bulunamadı.", + "rulechain-required": "Kural gerekli", "management": "Kural yönetimi", - "debug-mode": "Hata ayýklama modu" + "debug-mode": "Hata ayıklama modu" }, "rulenode": { - "details": "Ayrýntýlar", + "details": "Ayrıntılar", "events": "Etkinlikler", - "search": "Arama düðümleri", - "open-node-library": "Düðüm kütüphanesini aç", - "add": "Kural düðümü ekle", + "search": "Arama düğümleri", + "open-node-library": "Düğüm kütüphanesini aç", + "add": "Kural düğümü ekle", "name": "Ad", - "name-required": "Ýsim gerekli.", + "name-required": "İsim gerekli.", "type": "Tür", - "description": "Açýklama", - "delete": "Kural düðümünü sil", - "select-all-objects": "Tüm düðümleri ve baðlantýlarý seç", - "deselect-all-objects": "Tüm düðümlerin ve baðlantýlarýn seçimini kaldýrýn", - "delete-selected-objects": "Seçilen düðümleri ve baðlantýlarý sil", + "description": "Açıklama", + "delete": "Kural düğümünü sil", + "select-all-objects": "Tüm düğümleri ve bağlantıları seç", + "deselect-all-objects": "Tüm düğümlerin ve bağlantıların seçimini kaldırın", + "delete-selected-objects": "Seçilen düğümleri ve bağlantıları sil", "delete-selected": "Silme seçildi", "select-all": "Hepsini seç", "copy-selected": "Seçilenleri kopyala", "deselect-all": "Hiçbirini seçme", - "rulenode-details": "Kural düðümü ayrýntýlarý", - "debug-mode": "Hata ayýklama modu", - "configuration": "Yapýlandýrma", - "link": "Baðlantý", - "link-details": "Kural düðüm baðlantý detaylarý", + "rulenode-details": "Kural düğümü ayrıntıları", + "debug-mode": "Hata ayıklama modu", + "configuration": "Yapılandırma", + "link": "Bağlantı", + "link-details": "Kural düğüm bağlantı detayları", "add-link": "Link ekle", - "link-label": "Baðlantý etiketi", - "link-label-required": "Baðlantý etiketi gerekli.", - "custom-link-label": "Özel baðlantý etiketi", - "custom-link-label-required": "Özel baðlantý etiketi gerekli.", + "link-label": "Bağlantı etiketi", + "link-label-required": "Bağlantı etiketi gerekli.", + "custom-link-label": "Özel bağlantı etiketi", + "custom-link-label-required": "Özel bağlantı etiketi gerekli.", "link-labels": "Link etiketleri", "link-labels-required": "Link etiketleri gerekli.", - "no-link-labels-found": "Baðlantý etiketi bulunamadý", - "no-link-label-matching": "{{label}} bulunamadý. ", - "create-new-link-label": "Yeni bir tane oluþtur!", + "no-link-labels-found": "Bağlantı etiketi bulunamadı", + "no-link-label-matching": "{{label}} bulunamadı. ", + "create-new-link-label": "Yeni bir tane oluştur!", "type-filter": "Filtre", - "type-filter-details": "Gelen iletileri yapýlandýrýlmýþ koþullara göre filtrele", - "type-enrichment": "Zenginleþtirme", + "type-filter-details": "Gelen iletileri yapılandırılmış koşullara göre filtrele", + "type-enrichment": "Zenginleştirme", "type-enrichment-details": "Mesaj Meta Verilerine ek bilgi", - "type-transformation": "Dönüþüm", - "type-transformation-details": "Mesaj yükünü ve Meta Verileri Deðiþtir", + "type-transformation": "Dönüşüm", + "type-transformation-details": "Mesaj yükünü ve Meta Verileri Değiştir", "type-action": "Aksiyon", - "type-action-details": "Özel eylem gerçekleþtir", - "type-external": "Dýþ", - "type-external-details": "Dýþ sistemle etkileþir", + "type-action-details": "Özel eylem gerçekleştir", + "type-external": "Dış", + "type-external-details": "Dış sistemle etkileşir", "type-rule-chain": "Kural Zinciri", - "type-rule-chain-details": "Belirtilen Kural Zincirine gelen mesajlarý ilet", - "type-input": "Giriþ", - "type-input-details": "Kural Zinciri'nin mantýksal girdisi, bir sonraki ilgili Kural Düðümüne gelen iletileri iletme", + "type-rule-chain-details": "Belirtilen Kural Zincirine gelen mesajları ilet", + "type-input": "Giriş", + "type-input-details": "Kural Zinciri'nin mantıksal girdisi, bir sonraki ilgili Kural Düğümüne gelen iletileri iletme", "type-unknown": "Bilinmeyen", - "type-unknown-details": "Çözümlenmemiþ Kural Düðümü", - "directive-is-not-loaded": "Tanýmlanmýþ yapýlandýrma yönergesi {{directiveName}} 'mevcut deðil. ", - "ui-resources-load-error": "Yapýlandýrma kullanýcý arayüzü kaynaklarý yüklenemedi.", + "type-unknown-details": "Çözümlenmemiş Kural Düğümü", + "directive-is-not-loaded": "Tanımlanmış yapılandırma yönergesi {{directiveName}} 'mevcut değil. ", + "ui-resources-load-error": "Yapılandırma kullanıcı arayüzü kaynakları yüklenemedi.", "invalid-target-rulechain": "Hedef kural zinciri çözülemiyor!", - "test-script-function": "Test komut dosyasý iþlevi", + "test-script-function": "Test komut dosyası işlevi", "message": "Mesaj", "message-type": "Mesaj tipi", "select-message-type": "Mesaj tipini seç", "message-type-required": "Mesaj türü gerekli", "metadata": "Meta veri", - "metadata-required": "Meta veri giriþleri boþ býrakýlamaz.", - "output": "Çýktý", + "metadata-required": "Meta veri girişleri boş bırakılamaz.", + "output": "Çıktı", "test": "Ölçek", - "help": "Yardým et" + "help": "Yardım et" }, "tenant": { - "tenant": "Kiracý", - "tenants": "Kiracýlar", - "management": "Kiracý yönetimi", - "add": "Kiracý ekle", - "admins": "Yöneticiler", - "manage-tenant-admins": "Kiracý yöneticileri yönet", - "delete": "Kiracýyý sil", - "add-tenant-text": "Yeni kiracý ekle", - "no-tenants-text": "Kiracý bulunamadý", - "tenant-details": "Kiracý detaylarý", - "delete-tenant-title": "Kiracýyý silmek istediðinizden emin misiniz? {{TenantTitle}}? ", - "delete-tenant-text": "Dikkatli olun, onayýndan sonra kiracý ve ilgili tüm veriler kurtarýlamaz.", - "delete-tenants-title": "{Count, çoðul, 1 {1 kiracý} diðer {# kiracý}} silmek istediðinizden emin misiniz?", - "delete-tenants-action-title": "Sil {count, çoðul, 1 {1 kiracý} diðer {# kiracý}}", - "delete-tenants-text": "Dikkatli olun, onaylandýktan sonra tüm kiracýlar silinecek ve ilgili tüm veriler kurtarýlamayacaktýr.", - "title": "Baþlýk", - "title-required": "Baþlýk gerekli.", - "description": "Açýklama", - "details": "Ayrýntýlar", - "events": "Etkinlikler", - "copyId": "Kiracý Kimliði Kimliði", - "idCopiedMessage": "Kiracý Kimliði panoya kopyalandý", - "select-tenant": "Kiracý seç", - "no-tenants-matching": "{{Entity}} ile eþleþen kiracý bulunamadý. ", - "tenant-required": "Kiracý gerekli" + "tenant": "Tenant", + "tenants": "Tenantlar", + "management": "Tenant yönetimi", + "add": "Tenant Ekle", + "admins": "Adminler", + "manage-tenant-admins": "Tenant Adminlerini Yönet", + "delete": "Tenant sil", + "add-tenant-text": "Yeni tenant ekle", + "no-tenants-text": "Hiçbir tenant bulunamadı", + "tenant-details": "Tenant detayları", + "delete-tenant-title": "'{{tenantTitle}}' isimli tenantı silmek istediğinize emin misiniz?", + "delete-tenant-text": "UYARI: Onaylandıktan sonra tenant ve ilişkili tüm veriler geri yüklenemez şekilde silinecektir.", + "delete-tenants-title": "{ count, select, 1 {1 tenantı} other {# tenantı} } silmek istediğinize emin misiniz?", + "delete-tenants-action-title": "{ count, select, 1 {1 tenantı} other {# tenantı} } sil", + "delete-tenants-text": "UYARI: Onaylandıktan sonra seçili tüm tenantlar ve ilişkili tüm veriler geri yüklenemez şekilde silinecektir", + "title": "Başlık", + "title-required": "Başlık gerekli.", + "description": "Açıklama", + "details": "Detaylar", + "events": "Olaylar", + "copyId": "Tenant kimliğini kopyala", + "idCopiedMessage": "Tenant kimliği panoya kopyalandı", + "select-tenant": "Tenant seç", + "no-tenants-matching": "'{{entity}}' ile eşleşen tenant bulunamadı.", + "tenant-required": "Tenant gerekli" }, "timeinterval": { - "seconds-interval": "{saniye, çoðul, 1 {1 saniye} diðer {# seconds}}", - "minutes-interval": "{dakika, çoðul, 1 {1 dakika} diðer {# dakika}}", - "hours-interval": "{saat, çoðul, 1 {1 saat} diðer {# hours}}", - "days-interval": "{günler, çoðul, 1 {1 gün} diðer {# gün}}", + "seconds-interval": "{ seconds, select, 1 {1 saniye} other {# saniye} }", + "minutes-interval": "{ minutes, select, 1 {1 dakika} other {# dakika} }", + "hours-interval": "{ hours, select, 1 {1 saat} other {# saat} }", + "days-interval": "{ days, select, 1 {1 gün} other {# gün} }", "days": "Gün", - "hours": "Saatler", + "hours": "Saat", "minutes": "Dakika", "seconds": "Saniye", - "advanced": "Ýleri" + "advanced": "İleri düzey" }, "timewindow": { - "days": "{günler, çoðul, 1 {gün} diðer {# gün}}", - "hours": "{saat, çoðul, 0 {saat} 1 {1 saat} diðer {# hours}}", - "minutes": "{dakika, çoðul, 0 {dakika} 1 {1 dakika} diðer {# dakika}}", - "seconds": "{saniye, çoðul, 0 {saniye} 1 {1 saniye} diðer {# seconds}}", + "days": "{ days, select, 1 { gün } other {# gün } }", + "hours": "{ hours, select, 0 { saat } 1 {1 saat } other {# saat } }", + "minutes": "{ minutes, select, 0 { dakika } 1 {1 dakika } other {# dakika } }", + "seconds": "{ seconds, select, 0 { saniye } 1 {1 saniye } other {# saniye } }", "realtime": "Gerçek zaman", - "history": "Tarihçe", + "history": "Tarih", "last-prefix": "son", - "period": "{{startTime}} - {{endTime}} arasýnda ", - "edit": "Zaman penceresini düzenle", - "date-range": "Tarih aralýðý", + "period": "{{ startTime }}'dan {{ endTime }}'a kadar", + "edit": "Zaman aralığını düzenle", + "date-range": "Tarih aralığı", "last": "Son", - "time-period": "Zaman dilimi" + "time-period": "Zaman periyodu" }, "user": { - "user": "Kullanýcý", - "users": "Kullanýcýlar", - "customer-users": "Müþteri Kullanýcýlarý", - "tenant-admins": "Kiracý Admins", + "user": "Kullanıcı", + "users": "Kullanıcılar", + "customer-users": "Kullanıcılar", + "tenant-admins": "Tenant Adminleri", "sys-admin": "Sistem yöneticisi", - "tenant-admin": "Kiracý yöneticisi", - "customer": "Müþteri", + "tenant-admin": "Tenant yöneticisi", + "customer": "Kullanıcı Grubu", "anonymous": "Anonim", - "add": "Kullanýcý Ekle", - "delete": "Kullanýcýyý sil", - "add-user-text": "Yeni kullanýcý Ekle", - "no-users-text": "Kullanýcý bulunamadý", - "user-details": "Kullanýcý detaylarý", - "delete-user-title": "Kullanýcýyý silmek istediðinizden emin misiniz? {{UserEmail}} '? ", - "delete-user-text": "Dikkatli olun, onaylandýktan sonra kullanýcý ve ilgili tüm veriler kurtarýlamayacaktýr.", - "delete-users-title": "{Count, çoðul, 1 {1 kullanýcý} diðer {# users}} silmek istediðinizden emin misiniz?", - "delete-users-action-title": "Sil {count, çoðul, 1 {1 kullanýcý} diðer {# users}}", - "delete-users-text": "Dikkatli olun, onaylandýktan sonra tüm seçilen kullanýcýlar silinecek ve ilgili tüm veriler kurtarýlamayacaktýr.", - "activation-email-sent-message": "Etkinleþtirme e-postasý baþarýyla gönderildi!", - "resend-activation": "Etkinleþtirmeyi tekrar gönder", + "add": "Kullanıcı ekle", + "delete": "Kullanıcı sil", + "add-user-text": "Yeni kullanıcı ekle", + "no-users-text": "Hiçbir kullanıcı bulunamadı", + "user-details": "Kullanıcı detayları", + "delete-user-title": "'{{userEmail}}' kullanıcısını silmek istediğinize emin misiniz?", + "delete-user-text": "UYARI: Onaylandıktan sonra kullanıcı ve ilişkili tüm verileri geri yüklenemez şekilde silinecektir.", + "delete-users-title": "{ count, select, 1 {1 kullanıcıyı} other {# kullanıcıyı} } sikmek istediğinize emin misiniz?", + "delete-users-action-title": "{ count, select, 1 {1 kullancıyı} other {# kullanıcıyı} } sil", + "delete-users-text": "UYARI: Onaylandıktan sonra kullanıcı ve ilişkili tüm verileri geri yüklenemez şekilde silinecektir.", + "activation-email-sent-message": "Etkinleştirme e-postası başarılı bir şekilde gönderildi!", + "resend-activation": "Etkinleştirme e-postasını yeniden gönder", "email": "E-posta", - "email-required": "Email gereklidir.", - "invalid-email-format": "Geçersiz e-posta formatý.", - "first-name": "Ýsim", - "last-name": "Soyadý", - "description": "Açýklama", - "default-dashboard": "Varsayýlan gösterge paneli", + "email-required": "E-posta gerekli.", + "invalid-email-format": "Geçersiz e-posta formatı.", + "first-name": "Ad", + "last-name": "Soyad", + "description": "Açıklama", + "default-dashboard": "Varsayılan kontrol paneli", "always-fullscreen": "Her zaman tam ekran", - "select-user": "Kullanýcý seç", - "no-users-matching": "{{Entity}} ile eþleþen kullanýcý bulunamadý. ", - "user-required": "Kullanýcý gerekli", - "activation-method": "Aktivasyon yöntemi", - "display-activation-link": "Etkinleþtirme baðlantýsý göster", - "send-activation-mail": "Etkinleþtirme postasý gönder", - "activation-link": "Kullanýcý aktivasyon linki", - "activation-link-text": "Kullanýcýyý aktif hale getirmek için aþaðýdaki aktivasyon linki kullanýn.", - "copy-activation-link": "Etkinleþtirme baðlantýsýný kopyala", - "activation-link-copied-message": "Kullanýcý aktivasyon linki panoya kopyalandý", - "details": "Ayrýntýlar", - "login-as-tenant-admin": "Kiracý Yönetici Giriþi", - "login-as-customer-user": "Müþteri olarak giriþ yap" + "select-user": "Kullanıcı se.", + "no-users-matching": "'{{entity}}' ile eşleşen kullanıcı bulunamadı.", + "user-required": "Kullanıcı gerekli", + "activation-method": "Etkinleştirme yöntemi", + "display-activation-link": "Etkinleştirme bağlantısını görüntüle", + "send-activation-mail": "Etkinleştirme e-postası gönder", + "activation-link": "Kullanıcı hesabını etkinleştirme bağlantısı", + "activation-link-text": "Kullanıcı hesabını etkinleştirmek için bağlantıyı kullanın:", + "copy-activation-link": "Etkinleştirme bağlantısını kopyala", + "activation-link-copied-message": "Kullanıcı hesabı etkinleştirme bağlantısı panoya kopyalandı", + "details": "Ayrıntılar", + "login-as-tenant-admin": "Tenant Yönetici Girişi", + "login-as-customer-user": "Kullanıcı olarak giriş yap" }, "value": { - "type": "Deðer türü", - "string": "Dize", - "string-value": "Dize deðeri", + "type": "Değer tğrğ", + "string": "String", + "string-value": "String değeri", "integer": "Integer", - "integer-value": "Tamsayý deðeri", - "invalid-integer-value": "Geçersiz tam sayý", - "double": "Çift", - "double-value": "Çift deðer", - "boolean": "Boole", - "boolean-value": "Boole deðeri", - "false": "Yanlýþ", - "true": "Doðru", + "integer-value": "Integer değeri", + "invalid-integer-value": "Geçersiz integer değeri", + "double": "Double", + "double-value": "Double değeri", + "boolean": "Boolean", + "boolean-value": "Boolean değeri", + "false": "Yanlış", + "true": "Doğru", "long": "Uzun" }, "widget": { - "widget-library": "Widgets Kitaplýðý", - "widget-bundle": "Widget Paketi", - "select-widgets-bundle": "Widget paketini seç", - "management": "Widget yönetimi", - "editor": "Widget Düzenleyici", - "widget-type-not-found": "Sorun yükleme pencere öðesi yapýlandýrmasý.
Muhtemelen iliþkili /n pencere öðesi türü kaldýrýldý.", - "widget-type-load-error": "Widget, aþaðýdaki hatalardan dolayý yüklenmedi:", - "remove": "Widget'ý kaldýr", - "edit": "Widget düzenle", - "remove-widget-title": "Widget'ý kaldýrmak istediðinizden emin misiniz? {{WidgetTitle}}? ", - "remove-widget-text": "Onaydan sonra widget ve ilgili tüm veriler kurtarýlamaz.", + "widget-library": "Gösterge Kütüphanesi", + "widget-bundle": "Gösterge Demeti", + "select-widgets-bundle": "Gösterge demeti seç", + "management": "Gösterge yönetimi", + "editor": "Gösterge düzenleyici", + "widget-type-not-found": "Gösterge yapılandırması yüklenemedi.
Muhtemelen ilgili\n gösterge türü kaldırılmış.", + "widget-type-load-error": "Gösterge şu sebeplerden dolayı yüklenemedi:", + "remove": "Göstergeyi kaldır", + "edit": "Göstergeyi düzenle", + "remove-widget-title": "'{{widgetTitle}}' isimli göstermeyi kaldırmak istediğinizden emin misiniz?", + "remove-widget-text": "UYARI: Onaylandıktan sonra gösterge ve tüm ilişkili verileri geri yüklenemez şekilde silinecek.", "timeseries": "Zaman serisi", "search-data": "Arama verileri", - "no-data-found": "Veri bulunamadý", - "latest-values": "Son deðerler", - "rpc": "Kontrol aracý", - "alarm": "Alarm gereci", - "static": "Statik pencere öðesi", - "select-widget-type": "Widget tipi seç", - "missing-widget-title-error": "Widget baþlýðý belirtilmelidir!", - "widget-saved": "Widget kaydedildi", - "unable-to-save-widget-error": "Widget kaydedilemiyor! Widget'ýn hatalarý var!", - "save": "Widget kaydet", - "saveAs": "Widget olarak kaydet", - "save-widget-type-as": "Widget türünü kaydet", - "save-widget-type-as-text": "Lütfen yeni pencere öðesi baþlýðýný girin ve / veya hedef widget'larý seçin", - "toggle-fullscreen": "Tam ekrana geç", - "run": "Widget'ý çalýþtýr", - "title": "Widget Baþlýðý", - "title-required": "Widget baþlýðý gerekiyor.", - "type": "Widget türü", + "no-data-found": "Veri bulunamadı", + "latest-values": "Son değerler", + "rpc": "Kontrol göstergesi", + "alarm": "Alarm göstergesi", + "static": "Statik gösterge", + "select-widget-type": "Gösterge türü seç", + "missing-widget-title-error": "Gösterge başlığı belirtilmelidir!", + "widget-saved": "Gösterge kaydedildi", + "unable-to-save-widget-error": "Gösterge kaydedilemedi! Göstergede hatalar mevcut!", + "save": "Göstergeyi kaydet", + "saveAs": "Göstergeyi farklı kaydet", + "save-widget-type-as": "Gösterge türünü farklı kaydet", + "save-widget-type-as-text": "Lütfen gösterge başlığı girin veya hedef gösterge demeti seçin", + "toggle-fullscreen": "Tam ekran aç/kapat", + "run": "Göstergeyi çalıştır", + "title": "Gösterge başlığı", + "title-required": "Gösterge başlığı gerekli.", + "type": "Gösterge türü", "resources": "Kaynaklar", "resource-url": "JavaScript / CSS URL", - "remove-resource": "Kaynaðý kaldýr", + "remove-resource": "Kaynağı kaldır", "add-resource": "Kaynak ekle", "html": "HTML", - "tidy": "Düzenli", + "tidy": "Tertiple", "css": "CSS", - "settings-schema": "Ayarlar þemasý", - "datakey-settings-schema": "Veri anahtarý ayarlarý þemasý", - "javascript": "JavaScript", - "remove-widget-type-title": "'{{WidgetName}}' widget türünü kaldýrmak istediðinizden emin misiniz?", - "remove-widget-type-text": "Onaydan sonra widget tipi ve ilgili tüm veriler kurtarýlamayacak.", - "remove-widget-type": "Widget türünü kaldýr", - "add-widget-type": "Yeni widget türü ekle", - "widget-type-load-failed-error": "Widget türü yüklenemedi!", - "widget-template-load-failed-error": "Widget þablonu yüklenemedi!", - "add": "Widget Ekle", - "undo": "Widget deðiþikliklerini geri al", - "export": "Widget'ý dýþa aktar" + "settings-schema": "Ayarlar şeması", + "datakey-settings-schema": "Veri anahtarı ayarları şeması", + "javascript": "Javascript", + "remove-widget-type-title": "'{{widgetName}}' isimli gösterge türünü kaldırmak istediğinizden emin misiniz?", + "remove-widget-type-text": "UYARI: Onaylandıktan sonra, gösterge türü ve ilgili tüm veriler geri yüklenemez şekilde silinecektir.", + "remove-widget-type": "Gösterge türünü kaldır", + "add-widget-type": "Yeni gösterge türü ekle", + "widget-type-load-failed-error": "Gösterge türü yüklenemedi!", + "widget-template-load-failed-error": "Gösterge şablonu yüklenemedi!", + "add": "Gösterge ekle", + "undo": "Gösterge değişikliklerini geri al", + "export": "Göstergeyi dışa aktar" }, "widget-action": { - "header-button": "Widget baþlýk düðmesi", - "open-dashboard-state": "Yeni gösterge panosuna git", - "update-dashboard-state": "Mevcut kontrol paneli durumunu güncelle", - "open-dashboard": "Diðer kontrol paneline git", + "header-button": "Gösterge başlık butonu", + "open-dashboard-state": "Yeni kontrol paneli durumunua git", + "update-dashboard-state": "Kontrol paneli durumunu güncelle", + "open-dashboard": "Diğer kontrol paneline git", "custom": "Özel eylem", - "target-dashboard-state": "Hedef gösterge panosu durumu", - "target-dashboard-state-required": "Hedef gösterge tablosu gerekli", - "set-entity-from-widget": "Öðeyi pencere öðesinden ayarla", - "target-dashboard": "Hedef gösterge panosu", - "open-right-layout": "Saðdaki gösterge tablosu düzeni (mobil görünüm)" + "target-dashboard-state": "Hedef kontrol paneli durumu", + "target-dashboard-state-required": "Hedef kontrol paneli durumu gerekli", + "set-entity-from-widget": "Göstergeden öğe belirle", + "target-dashboard": "Hedef kontrol paneli", + "open-right-layout": "Sağdaki kontrol paneli arayüz düzenini aç(mobil görünüm)" }, "widgets-bundle": { - "current": "Mevcut paket", - "widgets-bundles": "Widget Paketleri", - "add": "Widget Paketi Ekle", - "delete": "Widget paketini sil", - "title": "Baþlýk", - "title-required": "Baþlýk gerekli.", - "add-widgets-bundle-text": "Yeni widget'lar paketi ekle", - "no-widgets-bundles-text": "Widget paketi bulunamadý", - "empty": "Widget'ler paketi boþ", - "details": "Ayrýntýlar", - "widgets-bundle-details": "Widget'lar paket ayrýntýlarýný", - "delete-widgets-bundle-title": "Widget paketini {{widgetsBundleTitle}} silmek istediðinizden emin misiniz?", - "delete-widgets-bundle-text": "Dikkatli olun, onaylandýktan sonra widget'lar paketi ve tüm ilgili veriler kurtarýlamayacak.", - "delete-widgets-bundles-title": "{Count, çoðul, 1 {1 widgets bundle} diðer {# widgets bundles}} silmek istediðinizden emin misiniz?", - "delete-widgets-bundles-action-title": "Sil {count, çoðul, 1 {1 widgets bundle} diðer {# widgets bundles}}", - "delete-widgets-bundles-text": "Dikkatli olun, onaylandýktan sonra tüm seçilen widget'lar paketler kaldýrýlacak ve ilgili tüm veriler kurtarýlamayacaktýr.", - "no-widgets-bundles-matching": "{{WidgetsBundle}} ile eþleþen hiçbir widget grubu bulunamadý. ", - "widgets-bundle-required": "Widget paketi gerekli.", + "current": "Şimdiki demet", + "widgets-bundles": "Gösterge Demetleri", + "add": "Gösterge Demeti Ekle", + "delete": "Gösterge demeti sil", + "title": "Başlık", + "title-required": "Başlık gerekli.", + "add-widgets-bundle-text": "Yeni gösterge demeti ekle", + "no-widgets-bundles-text": "Hiçbir gösterge demeti bulunamadı", + "empty": "Gösterge demeti boş", + "details": "Detaylar", + "widgets-bundle-details": "Gösterge demeti detayları", + "delete-widgets-bundle-title": "'{{widgetsBundleTitle}}' isimli gösterge demetini silmek istediğinize emin misiniz?", + "delete-widgets-bundle-text": "UYARI: Onaylandıktan sonra gösterge demeti ve ilişkili tüm veriler geri yüklenemez şekilde silinecektir.", + "delete-widgets-bundles-title": "{ count, select, 1 {1 gösterge demetini} other {# gösterge demetini} } silmek istediğinize emin misiniz?", + "delete-widgets-bundles-action-title": "{ count, select, 1 {1 gösterge demetini} other {# gösterge demetini} } sil", + "delete-widgets-bundles-text": "UYARI: Onaylandıktan sonra seçili tüm gösterge demetleri ve ilişkili tüm veriler geri yüklenemez şekilde silinecektir.", + "no-widgets-bundles-matching": "'{{widgetsBundle}}' ile eşleşen gösterge demeti bulunamadı.", + "widgets-bundle-required": "Gösterge demeti gerekli.", "system": "Sistem", - "import": "Widget paketlerini içe aktar", - "export": "Widget paketini dýþa aktar", - "export-failed-error": "Widget grubu dýþa aktarýlamadý: {{error}}", - "create-new-widgets-bundle": "Yeni widget'lar paketi oluþtur", - "widgets-bundle-file": "Widgets paket dosyasý", - "invalid-widgets-bundle-file-error": "Widget grubu içe aktarýlamýyor: Geçersiz widget'lar veri yapýsýný paketliyor." + "import": "Gösterge demetini içe aktar", + "export": "Gösterge demetini dışa aktar", + "export-failed-error": "Gösterge demetini dışa aktaramadı: {{error}}", + "create-new-widgets-bundle": "Yeni gösterge demeti oluştur", + "widgets-bundle-file": "Gösterge demeti dosyası", + "invalid-widgets-bundle-file-error": "Gösterge demeti içe aktarılamadı: Geçersiz gösterge demeti veri yapısı." }, "widget-config": { "data": "Veri", "settings": "Ayarlar", - "advanced": "Ýleri", - "title": "Baþlýk", - "general-settings": "Genel Ayarlar", - "display-title": "Baþlýk", - "drop-shadow": "Düþen gölge", - "enable-fullscreen": "Tam ekraný etkinleþtir", + "advanced": "İleri düzey", + "title": "Başlık", + "general-settings": "Genel ayarlar", + "display-title": "Başlığı göster", + "drop-shadow": "Gölge", + "enable-fullscreen": "Tam ekranı etkinleştir", "background-color": "Arka plan rengi", - "text-color": "Metin rengi", - "padding": "Dolgu malzemesi", - "margin": "Kenar", - "widget-style": "Widget stili", - "title-style": "Baþlýk stili", - "mobile-mode-settings": "Mobil mod ayarlarý", - "order": "Sipariþ", + "text-color": "Yazı rengi", + "padding": "İç aralık (Padding)", + "margin": "Dış aralık (Margin)", + "widget-style": "Gösterge stili", + "title-style": "Başlık stili", + "mobile-mode-settings": "Mobil mod ayarları", + "order": "Sıra", "height": "Yükseklik", - "units": "Deðerin yanýnda gösterilecek özel sembol", - "decimals": "Kayan noktadan sonraki basamak sayýsý", - "timewindow": "Timewindow", - "use-dashboard-timewindow": "Gösterge panosu zaman tüneli", - "display-legend": "Gösterge efsanesi", - "datasources": "Veri kaynaklarý", - "maximum-datasources": "Maksimum {sayým, çoðul, 1 {1 veri kaynaðý izinli.} Diðer {# veri kaynaklarýna izin verilir}}", + "units": "Değerin yanında göstermek için özel simge", + "decimals": "Noktadan sonraki basamak sayısı", + "timewindow": "Zaman aralığı", + "use-dashboard-timewindow": "Kontrol paneli zaman aralığı kullan", + "display-legend": "Lejant göster", + "datasources": "Veri kaynakları", + "maximum-datasources": "En fazla { count, select, 1 {1 veri kaynağı kullanılabilir.} other {# veri kaynağı kullanılabilir} }", "datasource-type": "Tür", "datasource-parameters": "Parametreler", - "remove-datasource": "Veri kaynaðýný kaldýr", - "add-datasource": "Veri kaynaðý ekle", - "target-device": "Hedef cihaz", - "alarm-source": "Alarm kaynaðý", - "actions": "Ýþlemler", - "action": "Aksiyon", + "remove-datasource": "Veri kaynağını kaldır", + "add-datasource": "Veri kaynağı ekle", + "target-device": "Hedef aygıt", + "alarm-source": "Alarm kaynağı", + "actions": "Eylemler", + "action": "Eylem", "add-action": "Eylem ekle", - "search-actions": "Arama iþlemleri", - "action-source": "Eylem kaynaðý", - "action-source-required": "Eylem kaynaðý gerekli.", - "action-name": "Ad", - "action-name-required": "Eylem adý gerekli.", - "action-name-not-unique": "Ayný ada sahip baþka bir eylem zaten var.
Eylem adý, ayný eylem kaynaðý içinde benzersiz olmalýdýr.", - "action-icon": "Simge", + "search-actions": "Eylem ara", + "action-source": "Eylem kaynağı", + "action-source-required": "Eylem kaynağı gerekli.", + "action-name": "İsim", + "action-name-required": "Eylem ismi gerekli.", + "action-name-not-unique": "Aynı ada sahip başka bir işlem zaten var.
Eylem adı, aynı eylem kaynağı içinde emsalsiz olmalıdır.", + "action-icon": "İkon", "action-type": "Tür", - "action-type-required": "Eylem türü gerekli", + "action-type-required": "Eylem türü gerekli.", "edit-action": "Eylemi düzenle", "delete-action": "Eylemi sil", - "delete-action-title": "Widget eylemini sil", - "delete-action-text": "Widget eylemini {{actionName}} adýyla silmek istediðinizden emin misiniz?" + "delete-action-title": "Gösterge eylemini sil", + "delete-action-text": "'{{actionName}}' isimli gösterge eylemini silmek istediğinizden emin misiniz?" }, "widget-type": { - "import": "Widget türü içe aktar", - "export": "Widget türünü dýþa aktar", - "export-failed-error": "Widget türü verilemiyor: {{error}}", - "create-new-widget-type": "Yeni pencere öðesi türü oluþtur", - "widget-type-file": "Widget tipi dosya", - "invalid-widget-type-file-error": "Widget türü içe aktarýlamýyor: Geçersiz pencere öðesi türü yapýsý." + "import": "Gösterge türünü içer aktar", + "export": "Gösterge türünü dışa aktar", + "export-failed-error": "Gösterge türü dışa aktarılamadı: {{error}}", + "create-new-widget-type": "Yeni gösterge türü oluştur", + "widget-type-file": "Gösterge türü dosyası", + "invalid-widget-type-file-error": "Gösterge türü içe aktarılamadı: Geçersiz gösterge türü veri yapısı." }, "icon": { - "icon": "Simge", - "select-icon": "Simge seç", - "material-icons": "Malzeme simgeleri", - "show-all": "Tüm simgeleri göster" + "icon": "İkon", + "select-icon": "İkon seç", + "material-icons": "Material konları", + "show-all": "Tüm ikonları göster" }, "custom": { "widget-action": { - "action-cell-button": "Eylem hücresi düðmesi", - "row-click": "Satýr týklamasý", - "marker-click": "Ýþaretçi týklamasýnda ", - "tooltip-tag-action": "Araç ipucu etiketi iþlemi" + "action-cell-button": "Eylem hücre butonu", + "row-click": "Satır tıklama eylemi", + "marker-click": "İşaretçi tıklama eylemi", + "tooltip-tag-action": "İpucu etiket eylemi" } }, "language": { "language": "Dil", "locales": { - "fr_FR": "Fransýzca", + "fr_FR": "Fransızca", "zh_CN": "Çince", - "en_US": "Ýngilizce", - "it_IT": "Ýtalyan", + "en_US": "İngilizce", + "it_IT": "İtalyan", "ko_KR": "Koreli", "ru_RU": "Rusça", - "es_ES": "Ýspanyol", + "es_ES": "İspanyol", "ja_JA": "Japonca", - "TR": "Türk" + "TR": "Türkçe" } } -} +} \ No newline at end of file diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json index 1fde4b6d47..9f326c7612 100644 --- a/ui/src/app/locale/locale.constant-en_US.json +++ b/ui/src/app/locale/locale.constant-en_US.json @@ -555,7 +555,12 @@ "alarm-fields-required": "Alarm fields are required.", "function-types": "Function types", "function-types-required": "Function types are required.", - "maximum-function-types": "Maximum { count, plural, 1 {1 function type is allowed.} other {# function types are allowed} }" + "maximum-function-types": "Maximum { count, plural, 1 {1 function type is allowed.} other {# function types are allowed} }", + "time-description": "timestamp of the current value;", + "value-description": "the current value;", + "prev-value-description": "result of the previous function call;", + "time-prev-description": "timestamp of the previous value;", + "prev-orig-value-description": "original previous value;" }, "datasource": { "type": "Datasource type",