]> git.basschouten.com Git - openhab-addons.git/commitdiff
[androidtv] Adds additional i18n support to ConnectionManagers (#15184)
authormorph166955 <53797132+morph166955@users.noreply.github.com>
Sat, 15 Jul 2023 07:39:45 +0000 (02:39 -0500)
committerGitHub <noreply@github.com>
Sat, 15 Jul 2023 07:39:45 +0000 (09:39 +0200)
Signed-off-by: Ben Rosenblum <rosenblumb@gmail.com>
bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/AndroidTVHandler.java
bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/AndroidTVHandlerFactory.java
bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/AndroidTVTranslationProvider.java [new file with mode: 0644]
bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/googletv/GoogleTVConnectionManager.java
bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/shieldtv/ShieldTVConnectionManager.java
bundles/org.openhab.binding.androidtv/src/main/resources/OH-INF/i18n/androidtv.properties

index f43936324250feccb839f4ec90c1af2daef92689..6904d8b21c1a556d929764319d43a950c8a7ad73 100644 (file)
@@ -61,13 +61,15 @@ public class AndroidTVHandler extends BaseThingHandler {
     private static final int THING_STATUS_FREQUENCY = 250;
 
     private final AndroidTVDynamicCommandDescriptionProvider commandDescriptionProvider;
+    private final AndroidTVTranslationProvider translationProvider;
     private final ThingTypeUID thingTypeUID;
     private final String thingID;
 
     public AndroidTVHandler(Thing thing, AndroidTVDynamicCommandDescriptionProvider commandDescriptionProvider,
-            ThingTypeUID thingTypeUID) {
+            AndroidTVTranslationProvider translationProvider, ThingTypeUID thingTypeUID) {
         super(thing);
         this.commandDescriptionProvider = commandDescriptionProvider;
+        this.translationProvider = translationProvider;
         this.thingTypeUID = thingTypeUID;
         this.thingID = this.getThing().getUID().getId();
     }
@@ -76,6 +78,10 @@ public class AndroidTVHandler extends BaseThingHandler {
         thing.setProperty(property, value);
     }
 
+    public AndroidTVTranslationProvider getTranslationProvider() {
+        return translationProvider;
+    }
+
     public String getThingID() {
         return this.thingID;
     }
@@ -113,21 +119,17 @@ public class AndroidTVHandler extends BaseThingHandler {
 
         if (googletvConnectionManager != null) {
             if (!googletvConnectionManager.getLoggedIn()) {
-                statusMessage = "GoogleTV: " + googletvConnectionManager.getStatusMessage();
                 failed = true;
-            } else {
-                statusMessage = "GoogleTV: ONLINE";
             }
+            statusMessage = "GoogleTV: " + googletvConnectionManager.getStatusMessage();
         }
 
         if (THING_TYPE_SHIELDTV.equals(thingTypeUID)) {
             if (shieldtvConnectionManager != null) {
                 if (!shieldtvConnectionManager.getLoggedIn()) {
-                    statusMessage = statusMessage + " | ShieldTV: " + shieldtvConnectionManager.getStatusMessage();
                     failed = true;
-                } else {
-                    statusMessage = statusMessage + " | ShieldTV: ONLINE";
                 }
+                statusMessage = statusMessage + " | ShieldTV: " + shieldtvConnectionManager.getStatusMessage();
             }
         }
 
index d5690ddc4e58460592958fdb5d36806936dda269..38581ad6b681c3499630374e2a75b25ae2d638f2 100644 (file)
@@ -18,6 +18,8 @@ import java.util.Set;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.i18n.LocaleProvider;
+import org.openhab.core.i18n.TranslationProvider;
 import org.openhab.core.thing.Thing;
 import org.openhab.core.thing.ThingTypeUID;
 import org.openhab.core.thing.binding.BaseThingHandlerFactory;
@@ -41,11 +43,14 @@ public class AndroidTVHandlerFactory extends BaseThingHandlerFactory {
             THING_TYPE_SHIELDTV);
 
     private final AndroidTVDynamicCommandDescriptionProvider commandDescriptionProvider;
+    private final AndroidTVTranslationProvider translationProvider;
 
     @Activate
     public AndroidTVHandlerFactory(
-            final @Reference AndroidTVDynamicCommandDescriptionProvider commandDescriptionProvider) {
+            final @Reference AndroidTVDynamicCommandDescriptionProvider commandDescriptionProvider,
+            final @Reference TranslationProvider i18nProvider, final @Reference LocaleProvider localeProvider) {
         this.commandDescriptionProvider = commandDescriptionProvider;
+        this.translationProvider = new AndroidTVTranslationProvider(i18nProvider, localeProvider);
     }
 
     @Override
@@ -56,6 +61,6 @@ public class AndroidTVHandlerFactory extends BaseThingHandlerFactory {
     @Override
     protected @Nullable ThingHandler createHandler(Thing thing) {
         ThingTypeUID thingTypeUID = thing.getThingTypeUID();
-        return new AndroidTVHandler(thing, commandDescriptionProvider, thingTypeUID);
+        return new AndroidTVHandler(thing, commandDescriptionProvider, translationProvider, thingTypeUID);
     }
 }
diff --git a/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/AndroidTVTranslationProvider.java b/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/AndroidTVTranslationProvider.java
new file mode 100644 (file)
index 0000000..1b9fd18
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.androidtv.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.i18n.LocaleProvider;
+import org.openhab.core.i18n.TranslationProvider;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link AndroidTVTranslationProvider} provides i18n message lookup.
+ * 
+ * @author Ben Rosenblum - Initial contribution
+ */
+@NonNullByDefault
+public class AndroidTVTranslationProvider {
+
+    private final Bundle bundle;
+    private final TranslationProvider i18nProvider;
+    private final LocaleProvider localeProvider;
+    private final Logger logger = LoggerFactory.getLogger(AndroidTVTranslationProvider.class);
+
+    public AndroidTVTranslationProvider(TranslationProvider i18nProvider, LocaleProvider localeProvider) {
+        this.bundle = FrameworkUtil.getBundle(this.getClass());
+        this.i18nProvider = i18nProvider;
+        this.localeProvider = localeProvider;
+    }
+
+    public String getText(String key, @Nullable Object... arguments) {
+        @Nullable
+        String text = i18nProvider.getText(bundle, key, null, localeProvider.getLocale(), arguments);
+        if (text != null) {
+            logger.trace("Translated: {} as {}", key, text);
+            return text;
+        } else {
+            logger.trace("Failed to translate: {}", key);
+            return key;
+        }
+    }
+}
index d60465459948043fd01524af9fac33226d604c23..92ac284549f3d8f036afd085968ac9c8b3c3dc91 100644 (file)
@@ -60,6 +60,7 @@ import javax.net.ssl.X509TrustManager;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.androidtv.internal.AndroidTVHandler;
+import org.openhab.binding.androidtv.internal.AndroidTVTranslationProvider;
 import org.openhab.binding.androidtv.internal.utils.AndroidTVPKI;
 import org.openhab.core.OpenHAB;
 import org.openhab.core.library.types.NextPreviousType;
@@ -97,6 +98,7 @@ public class GoogleTVConnectionManager {
 
     private final AndroidTVHandler handler;
     private GoogleTVConfiguration config;
+    private final AndroidTVTranslationProvider translationProvider;
 
     private @NonNullByDefault({}) SSLSocketFactory sslSocketFactory;
     private @Nullable SSLSocket sslSocket;
@@ -166,6 +168,7 @@ public class GoogleTVConnectionManager {
         messageParser = new GoogleTVMessageParser(this);
         this.config = config;
         this.handler = handler;
+        this.translationProvider = handler.getTranslationProvider();
         this.connectionManager = this;
         this.scheduler = handler.getScheduler();
         this.encryptionKey = androidtvPKI.generateEncryptionKey();
@@ -177,6 +180,7 @@ public class GoogleTVConnectionManager {
         messageParser = new GoogleTVMessageParser(this);
         this.config = config;
         this.handler = handler;
+        this.translationProvider = handler.getTranslationProvider();
         this.connectionManager = connectionManager;
         this.scheduler = handler.getScheduler();
         this.encryptionKey = androidtvPKI.generateEncryptionKey();
@@ -298,16 +302,17 @@ public class GoogleTVConnectionManager {
 
     private void setStatus(boolean isLoggedIn) {
         if (isLoggedIn) {
-            setStatus(isLoggedIn, "ONLINE");
+            setStatus(isLoggedIn, "online.online");
         } else {
-            setStatus(isLoggedIn, "UNKNOWN");
+            setStatus(isLoggedIn, "offline.unknown");
         }
     }
 
     private void setStatus(boolean isLoggedIn, String statusMessage) {
-        if ((this.isLoggedIn != isLoggedIn) || (!this.statusMessage.equals(statusMessage))) {
+        String translatedMessage = translationProvider.getText(statusMessage);
+        if ((this.isLoggedIn != isLoggedIn) || (!this.statusMessage.equals(translatedMessage))) {
             this.isLoggedIn = isLoggedIn;
-            this.statusMessage = statusMessage;
+            this.statusMessage = translatedMessage;
             handler.checkThingStatus();
         }
     }
@@ -501,10 +506,10 @@ public class GoogleTVConnectionManager {
                 shimAsyncInitializeTask = scheduler.submit(this::shimInitialize);
             }
         } catch (NoSuchAlgorithmException | IOException e) {
-            setStatus(false, "Error initializing keystore");
+            setStatus(false, "offline.error-initalizing-keystore");
             logger.debug("Error initializing keystore", e);
         } catch (UnrecoverableKeyException e) {
-            setStatus(false, "Key unrecoverable with supplied password");
+            setStatus(false, "offline.key-unrecoverable-with-supplied-password");
         } catch (GeneralSecurityException e) {
             logger.debug("General security exception", e);
         } catch (Exception e) {
@@ -530,12 +535,12 @@ public class GoogleTVConnectionManager {
                     logger.debug("{} - Connection to {}:{} {} successful", handler.getThingID(), config.ipAddress,
                             config.port, config.mode);
                 } catch (UnknownHostException e) {
-                    setStatus(false, "Unknown host");
+                    setStatus(false, "offline.unknown-host");
                     logger.debug("{} - Unknown host {}", handler.getThingID(), config.ipAddress);
                     return;
                 } catch (IllegalArgumentException e) {
                     // port out of valid range
-                    setStatus(false, "Invalid port number");
+                    setStatus(false, "offline.invalid-port-number");
                     logger.debug("{} - Invalid port number {}:{}", handler.getThingID(), config.ipAddress, config.port);
                     return;
                 } catch (InterruptedIOException e) {
@@ -546,7 +551,7 @@ public class GoogleTVConnectionManager {
                     String message = e.getMessage();
                     if ((message != null) && (message.contains("certificate_unknown"))
                             && (!config.mode.equals(PIN_MODE)) && (!config.shim)) {
-                        setStatus(false, "PIN Process Incomplete");
+                        setStatus(false, "offline.pin-process-incomplete");
                         logger.debug("{} - GoogleTV PIN Process Incomplete", handler.getThingID());
                         reconnectTaskCancel(true);
                         startChildConnectionManager(this.config.port + 1, PIN_MODE);
@@ -562,8 +567,8 @@ public class GoogleTVConnectionManager {
                             this.shimServerSocket = null;
                         }
                     } else {
-                        setStatus(false, "Error opening GoogleTV SSL connection. Check log.");
-                        logger.info("{} - Error opening GoogleTV SSL connection to {}:{} {}", handler.getThingID(),
+                        setStatus(false, "offline.error-opening-ssl-connection-check-log");
+                        logger.info("{} - Error opening SSL connection to {}:{} {}", handler.getThingID(),
                                 config.ipAddress, config.port, e.getMessage());
                         disconnect(false);
                         scheduleConnectRetry(config.reconnect); // Possibly a temporary problem. Try again later.
@@ -571,7 +576,7 @@ public class GoogleTVConnectionManager {
                     return;
                 }
 
-                setStatus(false, "Initializing");
+                setStatus(false, "offline.initializing");
 
                 logger.trace("{} - Starting Reader Thread for {}:{}", handler.getThingID(), config.ipAddress,
                         config.port);
@@ -826,7 +831,7 @@ public class GoogleTVConnectionManager {
         synchronized (connectionLock) {
             if (!this.disposing) {
                 logger.debug("{} - Attempting to reconnect to the GoogleTV", handler.getThingID());
-                setStatus(false, "reconnecting");
+                setStatus(false, "offline.reconnecting");
                 disconnect(false);
                 connect();
             }
@@ -852,12 +857,12 @@ public class GoogleTVConnectionManager {
                     }
                 } catch (InterruptedIOException e) {
                     logger.debug("Interrupted while sending to GoogleTV");
-                    setStatus(false, "Interrupted");
+                    setStatus(false, "offline.interrupted");
                     break; // exit loop and terminate thread
                 } catch (IOException e) {
                     logger.warn("{} - Communication error, will try to reconnect GoogleTV. Error: {}",
                             handler.getThingID(), e.getMessage());
-                    setStatus(false, "Communication error, will try to reconnect");
+                    setStatus(false, "offline.communication-error-will-try-to-reconnect");
                     sendQueue.add(command); // Requeue command
                     this.isLoggedIn = false;
                     reconnect();
@@ -944,12 +949,12 @@ public class GoogleTVConnectionManager {
             }
         } catch (InterruptedIOException e) {
             logger.debug("Interrupted while reading");
-            setStatus(false, "Interrupted");
+            setStatus(false, "offline.interrupted");
         } catch (IOException e) {
             String message = e.getMessage();
             if ((message != null) && (message.contains("certificate_unknown")) && (!config.mode.equals(PIN_MODE))
                     && (!config.shim)) {
-                setStatus(false, "PIN Process Incomplete");
+                setStatus(false, "offline.pin-process-incomplete");
                 logger.debug("{} - GoogleTV PIN Process Incomplete", handler.getThingID());
                 reconnectTaskCancel(true);
                 startChildConnectionManager(this.config.port + 1, PIN_MODE);
@@ -966,11 +971,11 @@ public class GoogleTVConnectionManager {
                 }
             } else {
                 logger.debug("I/O error while reading from stream: {}", e.getMessage());
-                setStatus(false, "I/O Error");
+                setStatus(false, "offline.io-error");
             }
         } catch (RuntimeException e) {
             logger.warn("Runtime exception in reader thread", e);
-            setStatus(false, "Runtime exception");
+            setStatus(false, "offline.runtime-exception");
         } finally {
             logger.debug("{} - Message reader thread exiting {}", handler.getThingID(), config.port);
         }
@@ -1038,13 +1043,13 @@ public class GoogleTVConnectionManager {
             }
         } catch (InterruptedIOException e) {
             logger.debug("Interrupted while reading");
-            setStatus(false, "Interrupted");
+            setStatus(false, "offline.interrupted");
         } catch (IOException e) {
             logger.debug("I/O error while reading from stream: {}", e.getMessage());
-            setStatus(false, "I/O Error");
+            setStatus(false, "offline.io-error");
         } catch (RuntimeException e) {
             logger.warn("Runtime exception in reader thread", e);
-            setStatus(false, "Runtime exception");
+            setStatus(false, "offline.runtime-exception");
         } finally {
             logger.debug("Shim message reader thread exiting {}", config.port);
         }
@@ -1263,7 +1268,7 @@ public class GoogleTVConnectionManager {
                     if (config.mode.equals(DEFAULT_MODE)) {
                         if ((!isLoggedIn) && (command.toString().equals("REQUEST"))
                                 && (childConnectionManager == null)) {
-                            setStatus(false, "User Forced PIN Process");
+                            setStatus(false, "offline.user-forced-pin-process");
                             logger.debug("{} - User Forced PIN Process", handler.getThingID());
                             disconnect(true);
                             startChildConnectionManager(config.port + 1, PIN_MODE);
index 3fed339d5b6518bfe7714a54a4d4cc8823935f83..c52937c9ac600f4726a9e2c138402c6b399e3fb1 100644 (file)
@@ -58,6 +58,7 @@ import javax.net.ssl.X509TrustManager;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.androidtv.internal.AndroidTVHandler;
+import org.openhab.binding.androidtv.internal.AndroidTVTranslationProvider;
 import org.openhab.binding.androidtv.internal.utils.AndroidTVPKI;
 import org.openhab.core.OpenHAB;
 import org.openhab.core.library.types.StringType;
@@ -87,6 +88,7 @@ public class ShieldTVConnectionManager {
 
     private final AndroidTVHandler handler;
     private ShieldTVConfiguration config;
+    private final AndroidTVTranslationProvider translationProvider;
 
     private @NonNullByDefault({}) SSLSocketFactory sslSocketFactory;
     private @Nullable SSLSocket sslSocket;
@@ -148,6 +150,7 @@ public class ShieldTVConnectionManager {
         messageParser = new ShieldTVMessageParser(this);
         this.config = config;
         this.handler = handler;
+        this.translationProvider = handler.getTranslationProvider();
         this.scheduler = handler.getScheduler();
         this.encryptionKey = androidtvPKI.generateEncryptionKey();
         initialize();
@@ -215,16 +218,17 @@ public class ShieldTVConnectionManager {
 
     private void setStatus(boolean isLoggedIn) {
         if (isLoggedIn) {
-            setStatus(isLoggedIn, "ONLINE");
+            setStatus(isLoggedIn, "online.online");
         } else {
-            setStatus(isLoggedIn, "UNKNOWN");
+            setStatus(isLoggedIn, "offline.unknown");
         }
     }
 
     private void setStatus(boolean isLoggedIn, String statusMessage) {
-        if ((this.isLoggedIn != isLoggedIn) || (!this.statusMessage.equals(statusMessage))) {
+        String translatedMessage = translationProvider.getText(statusMessage);
+        if ((this.isLoggedIn != isLoggedIn) || (!this.statusMessage.equals(translatedMessage))) {
             this.isLoggedIn = isLoggedIn;
-            this.statusMessage = statusMessage;
+            this.statusMessage = translatedMessage;
             handler.checkThingStatus();
         }
     }
@@ -399,10 +403,10 @@ public class ShieldTVConnectionManager {
                 shimAsyncInitializeTask = scheduler.submit(this::shimInitialize);
             }
         } catch (NoSuchAlgorithmException | IOException e) {
-            setStatus(false, "Error initializing keystore");
+            setStatus(false, "offline.error-initalizing-keystore");
             logger.debug("Error initializing keystore", e);
         } catch (UnrecoverableKeyException e) {
-            setStatus(false, "Key unrecoverable with supplied password");
+            setStatus(false, "offline.key-unrecoverable-with-supplied-password");
         } catch (GeneralSecurityException e) {
             logger.debug("General security exception", e);
         } catch (Exception e) {
@@ -424,26 +428,26 @@ public class ShieldTVConnectionManager {
                             new InputStreamReader(sslSocket.getInputStream(), StandardCharsets.ISO_8859_1));
                     this.sslSocket = sslSocket;
                 } catch (UnknownHostException e) {
-                    setStatus(false, "Unknown host");
+                    setStatus(false, "offline.unknown-host");
                     return;
                 } catch (IllegalArgumentException e) {
                     // port out of valid range
-                    setStatus(false, "Invalid port number");
+                    setStatus(false, "offline.invalid-port-number");
                     return;
                 } catch (InterruptedIOException e) {
                     logger.debug("Interrupted while establishing ShieldTV connection");
                     Thread.currentThread().interrupt();
                     return;
                 } catch (IOException e) {
-                    setStatus(false, "Error opening ShieldTV SSL connection. Check log.");
-                    logger.info("{} - Error opening ShieldTV SSL connection to {}:{} {}", handler.getThingID(),
-                            config.ipAddress, config.port, e.getMessage());
+                    setStatus(false, "offline.error-opening-ssl-connection-check-log");
+                    logger.info("{} - Error opening SSL connection to {}:{} {}", handler.getThingID(), config.ipAddress,
+                            config.port, e.getMessage());
                     disconnect(false);
                     scheduleConnectRetry(config.reconnect); // Possibly a temporary problem. Try again later.
                     return;
                 }
 
-                setStatus(false, "Initializing");
+                setStatus(false, "offline.initializing");
 
                 Thread readerThread = new Thread(this::readerThreadJob, "ShieldTV reader " + handler.getThingID());
                 readerThread.setDaemon(true);
@@ -640,7 +644,7 @@ public class ShieldTVConnectionManager {
         synchronized (connectionLock) {
             if (!this.disposing) {
                 logger.debug("{} - Attempting to reconnect to the ShieldTV", handler.getThingID());
-                setStatus(false, "reconnecting");
+                setStatus(false, "offline.reconnecting");
                 disconnect(false);
                 connect();
             }
@@ -666,12 +670,12 @@ public class ShieldTVConnectionManager {
                     }
                 } catch (InterruptedIOException e) {
                     logger.debug("Interrupted while sending to ShieldTV");
-                    setStatus(false, "Interrupted");
+                    setStatus(false, "offline.interrupted");
                     break; // exit loop and terminate thread
                 } catch (IOException e) {
                     logger.warn("{} - Communication error, will try to reconnect ShieldTV. Error: {}",
                             handler.getThingID(), e.getMessage());
-                    setStatus(false, "Communication error, will try to reconnect");
+                    setStatus(false, "offline.communication-error-will-try-to-reconnect");
                     sendQueue.add(command); // Requeue command
                     this.isLoggedIn = false;
                     reconnect();
@@ -785,13 +789,13 @@ public class ShieldTVConnectionManager {
             }
         } catch (InterruptedIOException e) {
             logger.debug("Interrupted while reading");
-            setStatus(false, "Interrupted");
+            setStatus(false, "offline.interrupted");
         } catch (IOException e) {
             logger.debug("I/O error while reading from stream: {}", e.getMessage());
-            setStatus(false, "I/O Error");
+            setStatus(false, "offline.io-error");
         } catch (RuntimeException e) {
             logger.warn("Runtime exception in reader thread", e);
-            setStatus(false, "Runtime exception");
+            setStatus(false, "offline.runtime-exception");
         } finally {
             logger.debug("{} - Message reader thread exiting", handler.getThingID());
         }
@@ -886,13 +890,13 @@ public class ShieldTVConnectionManager {
             }
         } catch (InterruptedIOException e) {
             logger.debug("Interrupted while reading");
-            setStatus(false, "Interrupted");
+            setStatus(false, "offline.interrupted");
         } catch (IOException e) {
             logger.debug("I/O error while reading from stream: {}", e.getMessage());
-            setStatus(false, "I/O Error");
+            setStatus(false, "offline.io-error");
         } catch (RuntimeException e) {
             logger.warn("Runtime exception in reader thread", e);
-            setStatus(false, "Runtime exception");
+            setStatus(false, "offline.runtime-exception");
         } finally {
             logger.debug("Message reader thread exiting");
         }
index d8a2799c2917cf0e9ad8cdd8636807c149d66a2f..91cb9eb79dd905004e63ba442d8e0a53067266da 100644 (file)
@@ -66,4 +66,19 @@ channel-type.androidtv.player.description = Player Control
 offline.protocols-starting = Protocols Starting
 offline.googletv-address-not-specified = googletv address not specified
 offline.shieldtv-address-not-specified = shieldtv address not specified
+offline.error-initalizing-keystore = Error initializing keystore
+offline.key-unrecoverable-with-supplied-password = Key unrecoverable with supplied password
+offline.unknown-host = Unknown host
+offline.invalid-port-number = Invalid port number
+offline.pin-process-incomplete = PIN Process Incomplete
+offline.error-opening-ssl-connection-check-log = Error opening SSL connection. Check log.
+offline.initializing = Initializing
+offline.reconnecting = Reconnecting
+offline.communication-error-will-try-to-reconnect = Communication error, will try to reconnect
+offline.interrupted = Interrupted
+offline.io-error = I/O Error
+offline.runtime-exception = Runtime exception
+offline.user-forced-pin-process = User Forced PIN Process
+offline.unknown = Unknown
+online.online = Online