ONOS-6730: Topo View i18n:
- augmented UiMessageHandler base class to allow injection of
  localization bundles, so that the handler can look up localized
  text when composing data to ship to the client.
- i18n'd the Summary Panel in Topo view.

Change-Id: I15010d1e2fcce72e3133a9ce40e51510c8f5146f
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java
index 0d7ff82..3cbce06 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java
@@ -82,7 +82,9 @@
 import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_ADDED;
 import static org.onosproject.net.DeviceId.deviceId;
 import static org.onosproject.net.HostId.hostId;
-import static org.onosproject.net.device.DeviceEvent.Type.*;
+import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED;
+import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_UPDATED;
+import static org.onosproject.net.device.DeviceEvent.Type.PORT_STATS_UPDATED;
 import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED;
 import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
 import static org.onosproject.ui.JsonUtils.envelope;
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandlerBase.java b/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandlerBase.java
index 2437132..c2e290d 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandlerBase.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandlerBase.java
@@ -18,6 +18,7 @@
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableSet;
 import org.onlab.osgi.ServiceDirectory;
 import org.onlab.packet.IpAddress;
 import org.onlab.util.DefaultHashMap;
@@ -50,6 +51,7 @@
 import org.onosproject.ui.UiConnection;
 import org.onosproject.ui.UiMessageHandler;
 import org.onosproject.ui.impl.topo.util.ServicesBundle;
+import org.onosproject.ui.lion.LionBundle;
 import org.onosproject.ui.topo.PropertyPanel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -66,6 +68,14 @@
 import static org.onosproject.net.PortNumber.portNumber;
 import static org.onosproject.ui.topo.TopoConstants.CoreButtons;
 import static org.onosproject.ui.topo.TopoConstants.Properties;
+import static org.onosproject.ui.topo.TopoConstants.Properties.DEVICES;
+import static org.onosproject.ui.topo.TopoConstants.Properties.FLOWS;
+import static org.onosproject.ui.topo.TopoConstants.Properties.HOSTS;
+import static org.onosproject.ui.topo.TopoConstants.Properties.INTENTS;
+import static org.onosproject.ui.topo.TopoConstants.Properties.LINKS;
+import static org.onosproject.ui.topo.TopoConstants.Properties.TOPOLOGY_SSCS;
+import static org.onosproject.ui.topo.TopoConstants.Properties.TUNNELS;
+import static org.onosproject.ui.topo.TopoConstants.Properties.VERSION;
 import static org.onosproject.ui.topo.TopoUtils.compactLinkString;
 
 /**
@@ -125,6 +135,11 @@
         return Collections.unmodifiableMap(metaUi);
     }
 
+    private static final String LION_TOPO = "core.view.Topo";
+
+    private static final Set<String> REQ_LION_BUNDLES = ImmutableSet.of(
+            LION_TOPO
+    );
 
     protected ServicesBundle services;
 
@@ -144,6 +159,11 @@
         version = ver.replace(".SNAPSHOT", "*").replaceFirst("~.*$", "");
     }
 
+    @Override
+    public Set<String> requiredLionBundles() {
+        return REQ_LION_BUNDLES;
+    }
+
     // Returns the first of the given set of IP addresses as a string.
     private String ip(Set<IpAddress> ipAddresses) {
         Iterator<IpAddress> it = ipAddresses.iterator();
@@ -351,18 +371,20 @@
     // Returns property panel model for summary response.
     protected PropertyPanel summmaryMessage() {
         Topology topology = services.topology().currentTopology();
+        LionBundle lion = getLionBundle(LION_TOPO);
+        String panelTitle = lion.getSafe("title_panel_summary");
 
-        return new PropertyPanel("ONOS Summary", "node")
-                .addProp(Properties.VERSION, version)
+        return new PropertyPanel(panelTitle, "node")
+                .addProp(VERSION, lion.getSafe(VERSION), version)
                 .addSeparator()
-                .addProp(Properties.DEVICES, services.device().getDeviceCount())
-                .addProp(Properties.LINKS, topology.linkCount())
-                .addProp(Properties.HOSTS, services.host().getHostCount())
-                .addProp(Properties.TOPOLOGY_SSCS, topology.clusterCount())
+                .addProp(DEVICES, lion.getSafe(DEVICES), services.device().getDeviceCount())
+                .addProp(LINKS, lion.getSafe(LINKS), topology.linkCount())
+                .addProp(HOSTS, lion.getSafe(HOSTS), services.host().getHostCount())
+                .addProp(TOPOLOGY_SSCS, lion.getSafe(TOPOLOGY_SSCS), topology.clusterCount())
                 .addSeparator()
-                .addProp(Properties.INTENTS, services.intent().getIntentCount())
-                .addProp(Properties.TUNNELS, services.tunnel().tunnelCount())
-                .addProp(Properties.FLOWS, services.flow().getFlowRuleCount());
+                .addProp(INTENTS, lion.getSafe(INTENTS), services.intent().getIntentCount())
+                .addProp(TUNNELS, lion.getSafe(TUNNELS), services.tunnel().tunnelCount())
+                .addProp(FLOWS, lion.getSafe(FLOWS), services.flow().getFlowRuleCount());
     }
 
     // Returns property panel model for device details response.
@@ -394,8 +416,8 @@
                 .addSeparator()
 
                 .addProp(Properties.PORTS, portCount)
-                .addProp(Properties.FLOWS, flowCount)
-                .addProp(Properties.TUNNELS, tunnelCount)
+                .addProp(FLOWS, flowCount)
+                .addProp(TUNNELS, tunnelCount)
 
                 .addButton(CoreButtons.SHOW_DEVICE_VIEW)
                 .addButton(CoreButtons.SHOW_FLOW_VIEW)
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
index 55f3183..07a0b0d 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
@@ -40,6 +40,7 @@
 import org.onosproject.ui.impl.topo.Topo2ViewMessageHandler;
 import org.onosproject.ui.impl.topo.UiTopoSession;
 import org.onosproject.ui.impl.topo.model.UiSharedTopologyModel;
+import org.onosproject.ui.lion.LionBundle;
 import org.onosproject.ui.model.topo.UiTopoLayout;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -97,6 +98,8 @@
     private TopoOverlayCache overlayCache;
     private Topo2OverlayCache overlay2Cache;
 
+    private Map<String, LionBundle> lionBundleMap;
+
     private UiSessionToken sessionToken;
 
 
@@ -289,14 +292,16 @@
         overlay2Cache = new Topo2OverlayCache();
 
         Map<Class<?>, UiMessageHandler> handlerInstances = new HashMap<>();
-
         UiExtensionService service = directory.get(UiExtensionService.class);
+        lionBundleMap = generateLionMap(service);
+
         service.getExtensions().forEach(ext -> {
             UiMessageHandlerFactory factory = ext.messageHandlerFactory();
             if (factory != null) {
                 factory.newHandlers().forEach(handler -> {
                     try {
                         handler.init(this, directory);
+                        injectLionBundles(handler, lionBundleMap);
                         handler.messageTypes().forEach(type -> handlers.put(type, handler));
                         handlerInstances.put(handler.getClass(), handler);
 
@@ -305,13 +310,34 @@
                     }
                 });
             }
-
             registerOverlays(ext);
         });
 
         handlerCrossConnects(handlerInstances);
 
-        log.debug("#handlers = {}, #overlays = {}", handlers.size(), overlayCache.size());
+        log.debug("#handlers = {}, #overlays = {}",
+                  handlers.size(), overlayCache.size());
+    }
+
+    private Map<String, LionBundle> generateLionMap(UiExtensionService service) {
+        Map<String, LionBundle> bundles = new HashMap<>();
+        service.getExtensions().forEach(ext -> {
+            ext.lionBundles().forEach(lb -> bundles.put(lb.id(), lb));
+        });
+        return bundles;
+    }
+
+    private void injectLionBundles(UiMessageHandler handler,
+                                   Map<String, LionBundle> lionBundleMap) {
+        handler.requiredLionBundles().forEach(lbid -> {
+            LionBundle lb = lionBundleMap.get(lbid);
+            if (lb != null) {
+                handler.cacheLionBundle(lb);
+            } else {
+                log.warn("handler {}: Lion bundle {} non existent!",
+                         handler.getClass().getName(), lbid);
+            }
+        });
     }
 
     private void authenticate(String type, ObjectNode message) {
@@ -424,9 +450,7 @@
         service.getExtensions().forEach(ext -> {
             ext.lionBundles().forEach(lb -> {
                 ObjectNode lionMap = objectNode();
-                lb.getItems().forEach(item -> {
-                    lionMap.put(item.key(), item.value());
-                });
+                lb.getItems().forEach(item -> lionMap.put(item.key(), item.value()));
                 lion.set(lb.id(), lionMap);
             });
         });
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/_config/core.view.Topo.lioncfg b/web/gui/src/main/resources/org/onosproject/ui/lion/_config/core.view.Topo.lioncfg
index 5d66622..3f4d269 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/_config/core.view.Topo.lioncfg
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/_config/core.view.Topo.lioncfg
@@ -26,6 +26,7 @@
 from cf.QuickHelp import qh_hint_close_detail
 
 from cc.Action import show, hide, enable, disable, select
-from cc.Network import hosts, devices
+from cc.Network import devices, links, hosts, topology_sccs, intents, tunnels, flows, protocol
+from cc.Props import version, vendor, hw_version, sw_version, serial_number
 from cc.State import visible, hidden
 from cc.Ui import click, shift_click, drag, cmd_scroll, cmd_drag, ok, close
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network.properties
index 9064478..3c1bf49 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network.properties
@@ -22,15 +22,24 @@
 device=Device
 host=Host
 link=Link
+intent=Intent
+tunnel=Tunnel
+flow=Flow
+port=Port
 
 # --- Elements (Plural)
 nodes=Nodes
 topologies=Topologies
+topology_sccs=Topology SCCs
 networks=Networks
 regions=Regions
 devices=Devices
 hosts=Hosts
 links=Links
+intents=Intents
+tunnels=Tunnels
+flows=Flows
+ports=Ports
 
 # --- Element IDs
 node_id=Node ID
@@ -38,6 +47,10 @@
 device_id=Device ID
 host_id=Host ID
 link_id=Link ID
+intent_id=Intent ID
+tunnel_id=Tunnel ID
+flow_id=Flow ID
+port_id=Port ID
 
 # --- Protocol terms
 protocol=Protocol
@@ -47,3 +60,4 @@
 mac=MAC
 mac_address=MAC Address
 uri=URI
+vlan=VLAN
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_es.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_es.properties
index df8f8ef..3a3f6df 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_es.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_es.properties
@@ -22,15 +22,24 @@
 device=Dispositivo
 host=Host
 link=Enlace
+intent=Intent (es)
+tunnel=Tunnel (es)
+flow=Flow (es)
+port=Port (es)
 
 # --- Elements (Plural)
 nodes=Nodos
 topologies=Topologías
+topology_sccs=Topology SCCs (es)
 networks=Redes
 regions=Regiones
 devices=Dispositivos
 hosts=Hosts
 links=Enlaces
+intents=Intents (es)
+tunnels=Tunnels (es)
+flows=Flows (es)
+ports=Ports (es)
 
 # --- Element IDs
 node_id=ID del Nodo
@@ -38,6 +47,10 @@
 device_id=ID del Dispositivo
 host_id=ID del Host
 link_id=ID del Enlace
+intent_id=Intent ID (es)
+tunnel_id=Tunnel ID (es)
+flow_id=Flow ID (es)
+port_id=Port ID (es)
 
 # --- Protocol terms
 protocol=Protocolo
@@ -47,3 +60,4 @@
 mac=MAC
 mac_address=Dirección MAC
 uri=URI
+vlan=VLAN (es)
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_it.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_it.properties
index c073672..5cf41eb 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_it.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_it.properties
@@ -22,15 +22,24 @@
 device=Dispositivo
 host=Host
 link=Collegamento
+intent=Intent (it)
+tunnel=Tunnel (it)
+flow=Flow (it)
+port=Port (it)
 
 # --- Elements (Plural)
 nodes=Nodi
 topologies=Topologie
+topology_sccs=Topology SCCs (it)
 networks=Reti
 regions=Regioni
 devices=Dispositivi
 hosts=Hosts
 links=Collegamenti
+intents=Intents (it)
+tunnels=Tunnels (it)
+flows=Flows (it)
+ports=Ports (it)
 
 # --- Element IDs
 node_id=ID del Nodo
@@ -38,6 +47,10 @@
 device_id=ID del Dispositivo
 host_id=ID dell'Host
 link_id=ID del collegamento
+intent_id=Intent ID (it)
+tunnel_id=Tunnel ID (it)
+flow_id=Flow ID (it)
+port_id=Port ID (it)
 
 # --- Protocol terms
 protocol=Protocollo
@@ -47,3 +60,4 @@
 mac=MAC
 mac_address=Indirizzo MAC
 uri=URI
+vlan=VLAN (it)
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_ko.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_ko.properties
index cb30ed7..1190278 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_ko.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_ko.properties
@@ -22,15 +22,24 @@
 device=장치
 host=호스트
 link=링크
+intent=Intent (ko)
+tunnel=Tunnel (ko)
+flow=Flow (ko)
+port=Port (ko)
 
 # --- Elements (Plural)
 nodes=노드
 topologies=토폴로지
+topology_sccs=Topology SCCs (ko)
 networks=네트워크
 regions=리젼
 devices=장치
 hosts=호스트
 links=링크
+intents=Intents (ko)
+tunnels=Tunnels (ko)
+flows=Flows (ko)
+ports=Ports (ko)
 
 # --- Element IDs
 node_id=노드 아이디
@@ -38,6 +47,10 @@
 device_id=장치 아이디
 host_id=호스트 아이디
 link_id=링크 아이디
+intent_id=Intent ID (ko)
+tunnel_id=Tunnel ID (ko)
+flow_id=Flow ID (ko)
+port_id=Port ID (ko)
 
 # --- Protocol terms
 protocol=프로토콜
@@ -47,3 +60,4 @@
 mac=MAC
 mac_address=MAC 주소
 uri=URI
+vlan=VLAN (ko)
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_zh_CN.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_zh_CN.properties
index 2db4017..724bd4d 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_zh_CN.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_zh_CN.properties
@@ -22,15 +22,24 @@
 device=设备
 host=主机
 link=链路
+intent=Intent (zh_CN)
+tunnel=Tunnel (zh_CN)
+flow=Flow (zh_CN)
+port=Port (zh_CN)
 
 # --- Elements (Plural)
 nodes=节点
 topologies=拓扑
+topology_sccs=Topology SCCs (zh_CN)
 networks=网络
 regions=区域
 devices=设备
 hosts=主机
 links=链路
+intents=Intents (zh_CN)
+tunnels=Tunnels (zh_CN)
+flows=Flows (zh_CN)
+ports=Ports (zh_CN)
 
 # --- Element IDs
 node_id=节点 ID
@@ -38,6 +47,10 @@
 device_id=设备 ID
 host_id=主机 ID
 link_id=链路 ID
+intent_id=Intent ID (zh_CN)
+tunnel_id=Tunnel ID (zh_CN)
+flow_id=Flow ID (zh_CN)
+port_id=Port ID (zh_CN)
 
 # --- Protocol terms
 protocol=协议
@@ -47,3 +60,4 @@
 mac=MAC
 mac_address=MAC 地址
 uri=URI
+vlan=VLAN (zh_CN)
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_zh_TW.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_zh_TW.properties
index 22ff27c..30fd81e 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_zh_TW.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_zh_TW.properties
@@ -22,15 +22,24 @@
 device=設備
 host=主機
 link=連結
+intent=Intent (zh_TW)
+tunnel=Tunnel (zh_TW)
+flow=Flow (zh_TW)
+port=Port (zh_TW)
 
 # --- Elements (Plural)
 nodes=節點
 topologies=拓撲
+topology_sccs=Topology SCCs (zh_TW)
 networks=網路
 regions=區域
 devices=設備
 hosts=主機
 links=連結
+intents=Intents (zh_TW)
+tunnels=Tunnels (zh_TW)
+flows=Flows (zh_TW)
+ports=Ports (zh_TW)
 
 # --- Element IDs
 node_id=節點 ID
@@ -38,6 +47,10 @@
 device_id=設備 ID
 host_id=主機 ID
 link_id=連結 ID
+intent_id=Intent ID (zh_TW)
+tunnel_id=Tunnel ID (zh_TW)
+flow_id=Flow ID (zh_TW)
+port_id=Port ID (zh_TW)
 
 # --- Protocol terms
 protocol=協定
@@ -47,3 +60,4 @@
 mac=MAC
 mac_address=MAC 地址
 uri=URI
+vlan=VLAN (zh_TW)
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props.properties
index 3dac6c6..86f02dc 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props.properties
@@ -32,3 +32,8 @@
 version=Version
 origin=Origin
 role=Role
+
+latitude=Latitude
+longitude=Longitude
+grid_y=Grid Y
+grid_x=Grid X
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_es.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_es.properties
index b74c36a..5d026b9 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_es.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_es.properties
@@ -32,3 +32,8 @@
 version=Versión
 origin=Origen
 role=Rol
+
+latitude=Latitude (es)
+longitude=Longitude (es)
+grid_y=Grid Y (es)
+grid_x=Grid X (es)
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_it.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_it.properties
index dceeed1..e897aea 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_it.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_it.properties
@@ -32,3 +32,8 @@
 version=Versione
 origin=Origine
 role=Ruolo
+
+latitude=Latitude (it)
+longitude=Longitude (it)
+grid_y=Grid Y (it)
+grid_x=Grid X (it)
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_ko.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_ko.properties
index e7681be..dd4593c 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_ko.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_ko.properties
@@ -32,3 +32,8 @@
 version=버전
 origin=제조사
 role=역할
+
+latitude=Latitude (ko)
+longitude=Longitude (ko)
+grid_y=Grid Y (ko)
+grid_x=Grid X (ko)
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_zh_CN.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_zh_CN.properties
index 57701a6..1c08fa9 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_zh_CN.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_zh_CN.properties
@@ -32,3 +32,8 @@
 version=版本
 origin=源
 role=角色
+
+latitude=Latitude (zh_CN)
+longitude=Longitude (zh_CN)
+grid_y=Grid Y (zh_CN)
+grid_x=Grid X (zh_CN)
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_zh_TW.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_zh_TW.properties
index 1d2e0f4..042bb1d 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_zh_TW.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_zh_TW.properties
@@ -32,3 +32,8 @@
 version=版本
 origin=來源
 role=角色
+
+latitude=Latitude (zh_TW)
+longitude=Longitude (zh_TW)
+grid_y=Grid Y (zh_TW)
+grid_x=Grid X (zh_TW)
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo.properties
index c6adb3e..c32cd6a 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo.properties
@@ -76,6 +76,7 @@
 fl_layer_opt=Optical Layer Shown
 
 fl_panel_instances=Instances Panel
+fl_panel_summary=Summary Panel
 
 fl_port_highlighting=Port Highlighting
 
@@ -91,3 +92,4 @@
 
 # Miscellaneous
 title_select_map=Select Map
+title_panel_summary=ONOS Summary
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_it.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_it.properties
index 23f6460..c32b249 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_it.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_it.properties
@@ -71,6 +71,7 @@
 fl_layer_opt=Optical Layer Shown (it)
 
 fl_panel_instances=Instances Panel (it)
+fl_panel_summary=Summary Panel (it)
 
 fl_port_highlighting=Port Highlighting (it)
 
@@ -86,3 +87,4 @@
 
 # Miscellaneous
 title_select_map=Select Map (it)
+title_panel_summary=ONOS Summary (it)
diff --git a/web/gui/src/main/webapp/app/view/topo/topo.css b/web/gui/src/main/webapp/app/view/topo/topo.css
index 540b480..74fe0c6 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.css
+++ b/web/gui/src/main/webapp/app/view/topo/topo.css
@@ -124,8 +124,8 @@
     padding: 0;
 }
 
-#topo-p-summary  td.label {
-    width: 50%;
+#topo-p-summary td.label {
+    width: 65%;
 }
 
 #topo-p-detail  div.actionBtns {
diff --git a/web/gui/src/main/webapp/app/view/topo/topo.js b/web/gui/src/main/webapp/app/view/topo/topo.js
index 3e9a0cc..ba0bc7d 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.js
+++ b/web/gui/src/main/webapp/app/view/topo/topo.js
@@ -728,6 +728,7 @@
                     tfs.setLionBundle(topoLion);
                     tis.setLionBundle(topoLion);
                     tms.setLionBundle(topoLion);
+                    tps.setLionBundle(topoLion);
 
                     // now we have the map projection, we are ready for
                     //  the server to send us device/host data...
diff --git a/web/gui/src/main/webapp/app/view/topo/topoInst.js b/web/gui/src/main/webapp/app/view/topo/topoInst.js
index 4e89822..63d49fa 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoInst.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoInst.js
@@ -47,7 +47,7 @@
 
     // function to be replaced by the localization bundle function
     var topoLion = function (x) {
-        return '#tinst#' + x + '#';
+        return '#tis#' + x + '#';
     };
 
 
@@ -317,11 +317,6 @@
         return on;
     }
 
-    // invoked after the localization bundle has been received from the server
-    function setLionBundle(bundle) {
-        topoLion = bundle;
-    }
-
     // ==========================
 
     angular.module('ovTopo')
@@ -353,7 +348,7 @@
                 hide: hideInsts,
                 toggle: toggleInsts,
                 showMaster: function () { return oiShowMaster; },
-                setLionBundle: setLionBundle,
+                setLionBundle: function (bundle) { topoLion = bundle; },
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topoPanel.js b/web/gui/src/main/webapp/app/view/topo/topoPanel.js
index b25f02e..eac6a89 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoPanel.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoPanel.js
@@ -25,6 +25,11 @@
     // injected refs
     var $log, $window, $rootScope, fs, ps, gs, flash, wss, bns, mast, ns;
 
+    // function to be replaced by the localization bundle function
+    var topoLion = function (x) {
+        return '#tps#' + x + '#';
+    };
+
     // constants
     var pCls = 'topo-p',
         idSum = 'topo-p-summary',
@@ -175,17 +180,26 @@
     function listProps(tbody, data) {
 
         // Suppress Lat Long in details panel if null
-        if (data.props.Latitude === null ||
-            data.props.Longitude === null) {
-            var idx = data.propOrder.indexOf('Latitude');
+        if (data.propLabels.latitude === null ||
+            data.propLabels.longitude === null) {
+            var idx = data.propOrder.indexOf('latitude');
             data.propOrder.splice(idx, 3);
         }
 
         data.propOrder.forEach(function (p) {
+            // TODO: remove after topo view fully i18n'd
+            var foo = data.props && data.props[p];
+
             if (p === '-') {
                 addSep(tbody);
+
             } else {
-                addProp(tbody, p, data.props[p]);
+                // TODO: remove this if/else once DETAILS panel fixed for i18n
+                if (foo !== undefined) {
+                    addProp(tbody, p, foo);
+                } else {
+                    addProp(tbody, data.propLabels[p], data.propValues[p]);
+                }
             }
         });
     }
@@ -392,7 +406,8 @@
     function toggleSummary(x) {
         var kev = (x === 'keyev'),
             on = kev ? !summary.panel().isVisible() : !!x,
-            verb = on ? 'Show' : 'Hide';
+            verb = on ? topoLion('show') : topoLion('hide'),
+            sumpan = topoLion('fl_panel_summary');
 
         if (on) {
             // ask server to start sending summary data.
@@ -401,7 +416,7 @@
         } else {
             hideSummaryPanel();
         }
-        flash.flash(verb + ' summary panel');
+        flash.flash(verb + ' ' + sumpan);
         return on;
     }
 
@@ -553,6 +568,8 @@
 
                 detailVisible: function () { return detail.panel().isVisible(); },
                 summaryVisible: function () { return summary.panel().isVisible(); },
+
+                setLionBundle: function (bundle) { topoLion = bundle; },
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topoSelect.js b/web/gui/src/main/webapp/app/view/topo/topoSelect.js
index 1309a66..5d23f1e 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoSelect.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoSelect.js
@@ -256,7 +256,7 @@
     function showDetails(data) {
         var buttons = fs.isA(data.buttons) || [];
         tps.displaySingle(data);
-        tov.installButtons(buttons, data, data.props['URI']);
+        tov.installButtons(buttons, data, data.propValues['uri']);
         tov.hooks.singleSelect(data);
         tps.displaySomething();
     }
diff --git a/web/gui/src/main/webapp/tests/app/view/topo/topoPanel-spec.js b/web/gui/src/main/webapp/tests/app/view/topo/topoPanel-spec.js
index 16b67af..e48c27c 100644
--- a/web/gui/src/main/webapp/tests/app/view/topo/topoPanel-spec.js
+++ b/web/gui/src/main/webapp/tests/app/view/topo/topoPanel-spec.js
@@ -76,7 +76,9 @@
             'addAction',
 
             'detailVisible',
-            'summaryVisible'
+            'summaryVisible',
+
+            'setLionBundle',
         ])).toBeTruthy();
     });