Merge 1.0.0 changes back to master.
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java
index 91ad11d..939280e 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java
@@ -96,8 +96,8 @@
                 String identifier = record.getUUID().toString();
                 permissions.add(new ObjectPermission(ObjectPermission.Type.READ, identifier));
 
-                // If we're and admin, then we also have DELETE
-                if (isAdmin)
+                // If we're an admin, or the connection is ours, then we can DELETE
+                if (isAdmin || targetUser.getIdentifier().equals(record.getUsername()))
                     permissions.add(new ObjectPermission(ObjectPermission.Type.DELETE, identifier));
 
             }
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionService.java
index 5e459b1..1d3344d 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionService.java
@@ -34,6 +34,8 @@
 import org.apache.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService;
 import org.apache.guacamole.net.GuacamoleTunnel;
 import org.apache.guacamole.net.auth.ActiveConnection;
+import org.apache.guacamole.net.auth.permission.ObjectPermission;
+import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
 
 /**
  * Service which provides convenience methods for creating, retrieving, and
@@ -111,13 +113,12 @@
     public void deleteObject(ModeledAuthenticatedUser user, String identifier)
         throws GuacamoleException {
 
-        // Only administrators may delete active connections
-        if (!user.getUser().isAdministrator())
-            throw new GuacamoleSecurityException("Permission denied.");
-
-        // Close connection, if it exists (and we have permission)
+        // Close connection, if it exists and we have permission
         ActiveConnection activeConnection = retrieveObject(user, identifier);
-        if (activeConnection != null) {
+        if (activeConnection == null)
+            return;
+        
+        if (hasObjectPermissions(user, identifier, ObjectPermission.Type.DELETE)) {
 
             // Close connection if not already closed
             GuacamoleTunnel tunnel = activeConnection.getTunnel();
@@ -125,6 +126,8 @@
                 tunnel.close();
 
         }
+        else
+            throw new GuacamoleSecurityException("Permission denied.");
         
     }
 
@@ -162,4 +165,54 @@
 
     }
 
+    /**
+     * Retrieve the permission set for the specified user that relates
+     * to access to active connections.
+     * 
+     * @param user
+     *     The user for which to retrieve the permission set.
+     * 
+     * @return
+     *     A permission set associated with the given user that specifies
+     *     the permissions available for active connection objects.
+     * 
+     * @throws GuacamoleException
+     *     If permission to read permissions for the user is denied.
+     */
+    private ObjectPermissionSet getPermissionSet(ModeledAuthenticatedUser user) 
+            throws GuacamoleException {
+        return user.getUser().getActiveConnectionPermissions();
+    }
+
+    /**
+     * Return a boolean value representing whether or not a user has the given
+     * permission available to them on the active connection with the given
+     * identifier.
+     * 
+     * @param user
+     *     The user for which the permissions are being queried.
+     * 
+     * @param identifier
+     *     The identifier of the active connection we are wondering about.
+     * 
+     * @param type
+     *     The type of permission being requested.
+     * 
+     * @return
+     *     True if the user has the necessary permission; otherwise false.
+     * 
+     * @throws GuacamoleException 
+     *     If the user does not have access to read permissions.
+     */
+    private boolean hasObjectPermissions(ModeledAuthenticatedUser user,
+            String identifier, ObjectPermission.Type type)
+            throws GuacamoleException {
+        
+        ObjectPermissionSet permissionSet = getPermissionSet(user);
+        
+        return user.getUser().isAdministrator() 
+                || permissionSet.hasPermission(type, identifier);
+        
+    }
+
 }
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledAuthenticatedUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledAuthenticatedUser.java
index 8c201d0..f51d086 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledAuthenticatedUser.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledAuthenticatedUser.java
@@ -79,6 +79,7 @@
         super(authenticatedUser.getAuthenticationProvider(), authenticatedUser.getCredentials());
         this.modelAuthenticationProvider = modelAuthenticationProvider;
         this.user = user;
+        super.setAttributes(authenticatedUser.getAttributes());
     }
 
     /**
@@ -93,7 +94,7 @@
      *     A ModeledUser object which is backed by the data associated with
      *     this user in the database.
      *
-     * @param credentials 
+     * @param credentials
      *     The credentials given by the user when they authenticated.
      */
     public ModeledAuthenticatedUser(AuthenticationProvider authenticationProvider,
@@ -107,7 +108,7 @@
      * Returns a ModeledUser object which is backed by the data associated with
      * this user within the database.
      *
-     * @return 
+     * @return
      *     A ModeledUser object which is backed by the data associated with
      *     this user in the database.
      */
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/RemoteAuthenticatedUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/RemoteAuthenticatedUser.java
index 24118af..3b16a99 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/RemoteAuthenticatedUser.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/RemoteAuthenticatedUser.java
@@ -19,6 +19,8 @@
 
 package org.apache.guacamole.auth.jdbc.user;
 
+import java.util.HashMap;
+import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import javax.servlet.http.HttpServletRequest;
@@ -68,6 +70,21 @@
     private static final Pattern X_FORWARDED_FOR = Pattern.compile("^" + IP_ADDRESS_REGEX + "(, " + IP_ADDRESS_REGEX + ")*$");
 
     /**
+     * Arbitrary attributes associated with this RemoteAuthenticatedUser object.
+     */
+    private Map<String, String> attributes = new HashMap<String, String>();
+
+    @Override
+    public Map<String, String> getAttributes() {
+        return attributes;
+    }
+
+    @Override
+    public void setAttributes(Map<String, String> attributes) {
+        this.attributes = attributes;
+    }
+
+    /**
      * Derives the remote host of the authenticating user from the given
      * credentials object. The remote host is derived from X-Forwarded-For
      * in addition to the actual source IP of the request, and thus is not
@@ -98,7 +115,7 @@
         return request.getRemoteAddr();
 
     }
-    
+
     /**
      * Creates a new RemoteAuthenticatedUser, deriving the associated remote
      * host from the given credentials.
@@ -106,7 +123,7 @@
      * @param authenticationProvider
      *     The AuthenticationProvider that has authenticated the given user.
      *
-     * @param credentials 
+     * @param credentials
      *     The credentials given by the user when they authenticated.
      */
     public RemoteAuthenticatedUser(AuthenticationProvider authenticationProvider,
diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/AuthenticationProviderService.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/AuthenticationProviderService.java
index a25c697..e359221 100644
--- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/AuthenticationProviderService.java
+++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/AuthenticationProviderService.java
@@ -21,11 +21,19 @@
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
+import com.novell.ldap.LDAPAttribute;
+import com.novell.ldap.LDAPAttributeSet;
 import com.novell.ldap.LDAPConnection;
+import com.novell.ldap.LDAPEntry;
+import com.novell.ldap.LDAPException;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import org.apache.guacamole.auth.ldap.user.AuthenticatedUser;
 import org.apache.guacamole.auth.ldap.user.UserContext;
 import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.GuacamoleServerException;
 import org.apache.guacamole.auth.ldap.user.UserService;
 import org.apache.guacamole.net.auth.Credentials;
 import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
@@ -189,7 +197,8 @@
 
     /**
      * Returns an AuthenticatedUser representing the user authenticated by the
-     * given credentials.
+     * given credentials. Also adds custom LDAP attributes to the
+     * AuthenticatedUser.
      *
      * @param credentials
      *     The credentials to use for authentication.
@@ -221,14 +230,16 @@
             throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD);
 
         try {
-
             // Return AuthenticatedUser if bind succeeds
             AuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
             authenticatedUser.init(credentials);
+
+            // Set attributes
+            authenticatedUser.setAttributes(getLDAPAttributes(ldapConnection, credentials.getUsername()));
+
             return authenticatedUser;
 
         }
-
         // Always disconnect
         finally {
             ldapService.disconnect(ldapConnection);
@@ -237,6 +248,66 @@
     }
 
     /**
+     * Returns all custom LDAP attributes on the user currently bound under
+     * the given LDAP connection. The custom attributes are specified in
+     * guacamole.properties.  If no attributes are specified or none are
+     * found on the LDAP user object, an empty map is returned.
+     *
+     * @param ldapConnection
+     *     LDAP connection to find the custom LDAP attributes.
+     *
+     * @param username
+     *     The username of the user whose attributes are queried.
+     *
+     * @return
+     *     All attributes on the user currently bound under the
+     *     given LDAP connection, as a map of attribute name to
+     *     corresponding attribute value, or an empty map if no
+     *     attributes are specified or none are found on the user
+     *     object.
+     *
+     * @throws GuacamoleException
+     *     If an error occurs retrieving the user DN or the attributes.
+     */
+    private Map<String, String> getLDAPAttributes(LDAPConnection ldapConnection,
+            String username) throws GuacamoleException {
+
+        // Get attributes from configuration information
+        List<String> attrList = confService.getAttributes();
+
+        // If there are no attributes there is no reason to search LDAP
+        if (attrList == null || attrList.isEmpty())
+            return Collections.<String, String>emptyMap();
+
+        // Build LDAP query parameters
+        String[] attrArray = attrList.toArray(new String[attrList.size()]);
+        String userDN = getUserBindDN(username);
+
+        Map<String, String> attrMap = new HashMap<String, String>();
+        try {
+            // Get LDAP attributes by querying LDAP
+            LDAPEntry userEntry = ldapConnection.read(userDN, attrArray);
+            if (userEntry == null)
+                return Collections.<String, String>emptyMap();
+
+            LDAPAttributeSet attrSet = userEntry.getAttributeSet();
+            if (attrSet == null)
+                return Collections.<String, String>emptyMap();
+
+            // Add each attribute into Map
+            for (Object attrObj : attrSet) {
+                LDAPAttribute attr = (LDAPAttribute)attrObj;
+                attrMap.put(attr.getName(), attr.getStringValue());
+            }
+        }
+        catch (LDAPException e) {
+            throw new GuacamoleServerException("Error while querying for User Attributes.", e);
+        }
+
+        return attrMap;
+    }
+
+    /**
      * Returns a UserContext object initialized with data accessible to the
      * given AuthenticatedUser.
      *
diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/ConfigurationService.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/ConfigurationService.java
index 2ab7aad..de7c71c 100644
--- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/ConfigurationService.java
+++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/ConfigurationService.java
@@ -227,7 +227,7 @@
     private int getMaxResults() throws GuacamoleException {
         return environment.getProperty(
             LDAPGuacamoleProperties.LDAP_MAX_SEARCH_RESULTS,
-            1000 
+            1000
         );
     }
 
@@ -344,4 +344,19 @@
         );
     }
 
+    /**
+     * Returns names for custom LDAP user attributes.
+     *
+     * @return
+     *     Custom LDAP user attributes as configured in guacamole.properties.
+     *
+     * @throws GuacamoleException
+     *     If guacamole.properties cannot be parsed.
+     */
+    public List<String> getAttributes() throws GuacamoleException {
+        return environment.getProperty(
+            LDAPGuacamoleProperties.LDAP_USER_ATTRIBUTES
+        );
+    }
+
 }
diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/LDAPGuacamoleProperties.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/LDAPGuacamoleProperties.java
index 0d3823f..6372d81 100644
--- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/LDAPGuacamoleProperties.java
+++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/LDAPGuacamoleProperties.java
@@ -205,4 +205,14 @@
 
     };
 
+    /**
+     * Custom attribute or attributes to query from Guacamole user's record in
+     * the LDAP directory.
+     */
+    public static final StringListProperty LDAP_USER_ATTRIBUTES = new StringListProperty() {
+
+        @Override
+        public String getName() { return "ldap-user-attributes"; }
+
+    };
 }
diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/connection/ConnectionService.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/connection/ConnectionService.java
index 3ce00e3..a282f30 100644
--- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/connection/ConnectionService.java
+++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/connection/ConnectionService.java
@@ -295,4 +295,3 @@
     }
 
 }
-
diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/user/AuthenticatedUser.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/user/AuthenticatedUser.java
index 669efcd..8e99267 100644
--- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/user/AuthenticatedUser.java
+++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/user/AuthenticatedUser.java
@@ -20,6 +20,8 @@
 package org.apache.guacamole.auth.ldap.user;
 
 import com.google.inject.Inject;
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.guacamole.net.auth.AbstractAuthenticatedUser;
 import org.apache.guacamole.net.auth.AuthenticationProvider;
 import org.apache.guacamole.net.auth.Credentials;
@@ -43,6 +45,11 @@
     private Credentials credentials;
 
     /**
+     * Arbitrary attributes associated with this AuthenticatedUser object.
+     */
+    private Map<String, String> attributes = new HashMap<String, String>();
+
+    /**
      * Initializes this AuthenticatedUser using the given credentials.
      *
      * @param credentials
@@ -54,6 +61,16 @@
     }
 
     @Override
+    public Map<String, String> getAttributes() {
+        return attributes;
+    }
+
+    @Override
+    public void setAttributes(Map<String, String> attributes) {
+        this.attributes = attributes;
+    }
+
+    @Override
     public AuthenticationProvider getAuthenticationProvider() {
         return authProvider;
     }
diff --git a/guacamole-docker/bin/start.sh b/guacamole-docker/bin/start.sh
index 6309265..9054a08 100755
--- a/guacamole-docker/bin/start.sh
+++ b/guacamole-docker/bin/start.sh
@@ -329,7 +329,7 @@
 start_guacamole() {
 
     # Install webapp
-    ln -sf /opt/guacamole/guacamole.war /usr/local/tomcat/webapps/
+    ln -sf /opt/guacamole/guacamole.war /usr/local/tomcat/webapps/${WEBAPP_CONTEXT:-guacamole}.war
 
     # Start tomcat
     cd /usr/local/tomcat
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractAuthenticatedUser.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractAuthenticatedUser.java
index 36c4571..828ad89 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractAuthenticatedUser.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractAuthenticatedUser.java
@@ -20,6 +20,7 @@
 package org.apache.guacamole.net.auth;
 
 import java.util.Collections;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -41,4 +42,14 @@
         // Nothing to invalidate
     }
 
+    @Override
+    public Map<String, String> getAttributes() {
+        return Collections.<String, String>emptyMap();
+    }
+
+    @Override
+    public void setAttributes(Map<String, String> attributes) {
+        //do nothing
+    }
+
 }
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AuthenticatedUser.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AuthenticatedUser.java
index a799937..14f2597 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AuthenticatedUser.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AuthenticatedUser.java
@@ -25,7 +25,7 @@
  * A user of the Guacamole web application who has been authenticated by an
  * AuthenticationProvider.
  */
-public interface AuthenticatedUser extends Identifiable {
+public interface AuthenticatedUser extends Identifiable, Attributes {
 
     /**
      * The identifier reserved for representing a user that has authenticated
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/token/StandardTokens.java b/guacamole-ext/src/main/java/org/apache/guacamole/token/StandardTokens.java
index b1b280b..8faca15 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/token/StandardTokens.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/token/StandardTokens.java
@@ -21,6 +21,8 @@
 
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.Map;
+import java.util.Set;
 import org.apache.guacamole.net.auth.AuthenticatedUser;
 import org.apache.guacamole.net.auth.Credentials;
 
@@ -75,6 +77,11 @@
     private static final String TIME_FORMAT = "HHmmss";
 
     /**
+     * The prefix of the arbitrary attribute tokens.
+     */
+    public static final String ATTR_TOKEN_PREFIX = "GUAC_ATTR_";
+
+    /**
      * This utility class should not be instantiated.
      */
     private StandardTokens() {}
@@ -143,10 +150,11 @@
      * Adds tokens which are standardized by guacamole-ext to the given
      * TokenFilter using the values from the given AuthenticatedUser object,
      * including any associated credentials. These standardized tokens include
-     * the current username (GUAC_USERNAME), password (GUAC_PASSWORD), and the
-     * server date and time (GUAC_DATE and GUAC_TIME respectively). If either
-     * the username or password are not set within the given user or their
-     * provided credentials, the corresponding token(s) will remain unset.
+     * the current username (GUAC_USERNAME), password (GUAC_PASSWORD), the
+     * server date and time (GUAC_DATE and GUAC_TIME respectively), and custom
+     * user attributes. If either the username or password are not set within
+     * the given user or their provided credentials, the corresponding token(s)
+     * will remain unset.
      *
      * @param filter
      *     The TokenFilter to add standard tokens to.
@@ -164,6 +172,33 @@
         // Add tokens specific to credentials
         addStandardTokens(filter, user.getCredentials());
 
+        // Add custom attribute tokens
+        addAttributeTokens(filter, user.getAttributes());
+    }
+
+    /**
+     * Add attribute tokens to StandardTokens.  These are arbitrary
+     * key/value pairs that may be configured by the various authentication
+     * extensions.
+     *
+     * @param filter
+     *     The TokenFilter to add attribute tokens to.
+     *
+     * @param attributes
+     *     The map of key/value pairs to add tokens for.
+     */
+    public static void addAttributeTokens(TokenFilter filter,
+            Map<String, String> attributes) {
+
+        if (attributes != null) {
+            for (Map.Entry entry : attributes.entrySet()) {
+                String key = entry.getKey().toString();
+                String tokenName = ATTR_TOKEN_PREFIX + key.toUpperCase();
+                String tokenValue = entry.getValue().toString();
+                filter.setToken(tokenName, tokenValue);
+            }
+        }
+
     }
 
 }
diff --git a/guacamole/src/main/webapp/app/home/controllers/homeController.js b/guacamole/src/main/webapp/app/home/controllers/homeController.js
index f0e753d..1cedead 100644
--- a/guacamole/src/main/webapp/app/home/controllers/homeController.js
+++ b/guacamole/src/main/webapp/app/home/controllers/homeController.js
@@ -70,7 +70,7 @@
      */
     $scope.isLoaded = function isLoaded() {
 
-        return $scope.rootConnectionGroup !== null;
+        return $scope.rootConnectionGroups !== null;
 
     };
 
diff --git a/guacamole/src/main/webapp/app/navigation/services/userPageService.js b/guacamole/src/main/webapp/app/navigation/services/userPageService.js
index 4d1e612..bd401da 100644
--- a/guacamole/src/main/webapp/app/navigation/services/userPageService.js
+++ b/guacamole/src/main/webapp/app/navigation/services/userPageService.js
@@ -72,9 +72,11 @@
 
         // If user has access to settings pages, return home page and skip
         // evaluation for automatic connections.  The Preferences page is
-        // a Settings page and is always visible, so we look for more than
-        // one to indicate access to administrative pages.
-        if (settingsPages.length > 1)
+        // a Settings page and is always visible, and the Session management
+        // page is also available to all users so that they can kill their
+        // own session.  We look for more than those two pages to determine
+        // if we should go to the home page.
+        if (settingsPages.length > 2)
             return SYSTEM_HOME_PAGE;
 
         // Determine whether a connection or balancing group should serve as
@@ -194,7 +196,6 @@
         var canManageUsers = [];
         var canManageConnections = [];
         var canViewConnectionRecords = [];
-        var canManageSessions = [];
 
         // Inspect the contents of each provided permission set
         angular.forEach(authenticationService.getAvailableDataSources(), function inspectPermissions(dataSource) {
@@ -257,24 +258,21 @@
                 canManageConnections.push(dataSource);
             }
 
-            // Determine whether the current user needs access to the session management UI or view connection history
+            // Determine whether the current user needs access to view connection history
             if (
-                    // A user must be a system administrator to manage sessions
+                    // A user must be a system administrator to view connection records
                     PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER)
             ) {
-                canManageSessions.push(dataSource);
                 canViewConnectionRecords.push(dataSource);
             }
 
         });
 
-        // If user can manage sessions, add link to sessions management page
-        if (canManageSessions.length) {
-            pages.push(new PageDefinition({
-                name : 'USER_MENU.ACTION_MANAGE_SESSIONS',
-                url  : '/settings/sessions'
-            }));
-        }
+        // Add link to Session management (always accessible)
+        pages.push(new PageDefinition({
+            name : 'USER_MENU.ACTION_MANAGE_SESSIONS',
+            url  : '/settings/sessions'
+        }));
 
         // If user can manage connections, add links for connection management pages
         angular.forEach(canViewConnectionRecords, function addConnectionHistoryLink(dataSource) {
diff --git a/guacamole/src/main/webapp/app/settings/directives/guacSettingsSessions.js b/guacamole/src/main/webapp/app/settings/directives/guacSettingsSessions.js
index 67776f0..ccb75c9 100644
--- a/guacamole/src/main/webapp/app/settings/directives/guacSettingsSessions.js
+++ b/guacamole/src/main/webapp/app/settings/directives/guacSettingsSessions.js
@@ -189,12 +189,14 @@
                         var connection = allConnections[dataSource][activeConnection.connectionIdentifier];
 
                         // Add wrapper
-                        $scope.wrappers.push(new ActiveConnectionWrapper({
-                            dataSource       : dataSource,
-                            name             : connection.name,
-                            startDate        : $filter('date')(activeConnection.startDate, sessionDateFormat),
-                            activeConnection : activeConnection
-                        }));
+                        if (activeConnection.username !== null) {
+                            $scope.wrappers.push(new ActiveConnectionWrapper({
+                                dataSource       : dataSource,
+                                name             : connection.name,
+                                startDate        : $filter('date')(activeConnection.startDate, sessionDateFormat),
+                                activeConnection : activeConnection
+                            }));
+                        }
 
                     });
                 });
diff --git a/guacamole/src/main/webapp/layouts/es-es-qwerty.json b/guacamole/src/main/webapp/layouts/es-es-qwerty.json
index 0a1e7d7..dc330e5 100644
--- a/guacamole/src/main/webapp/layouts/es-es-qwerty.json
+++ b/guacamole/src/main/webapp/layouts/es-es-qwerty.json
@@ -1,4 +1,4 @@
-{

+{

 

     "language" : "es_ES",

     "type"     : "qwerty",

diff --git a/guacamole/src/main/webapp/translations/de.json b/guacamole/src/main/webapp/translations/de.json
index 90953e5..9e24ba7 100644
--- a/guacamole/src/main/webapp/translations/de.json
+++ b/guacamole/src/main/webapp/translations/de.json
@@ -621,7 +621,7 @@
         
         "FORMAT_STARTDATE" : "@:APP.FORMAT_DATE_TIME_PRECISE",
 
-        "HELP_SESSIONS" : "Alle aktiven Guacamole Sitzungen werden hier aufgelistet. Wenn Sie eine oder mehrere Sitzungen beenden wollen, wählen Sie diese Sitzung durch Aktivierung der nebenstehende Box und klicken auf \"Beende Sitzung\". Beendung einer Sitzung trennt den Benutzer von dessen Verbindung unverzüglich.",
+        "HELP_SESSIONS" : "Diese Seite wird mit derzeit aktiven Verbindungen gefüllt. Die aufgelisteten Verbindungen und die Möglichkeit, diese Verbindungen zu beenden, hängen von Ihrer Zugriffsebene ab. Wenn Sie eine oder mehrere Sitzungen beenden wollen, wählen Sie diese Sitzung durch Aktivierung der nebenstehende Box und klicken auf \"Beende Sitzung\". Beendung einer Sitzung trennt den Benutzer von dessen Verbindung unverzüglich.",
         
         "INFO_NO_SESSIONS" : "Keine aktiven Sitzungen",
 
diff --git a/guacamole/src/main/webapp/translations/en.json b/guacamole/src/main/webapp/translations/en.json
index 0f242f9..c247ffa 100644
--- a/guacamole/src/main/webapp/translations/en.json
+++ b/guacamole/src/main/webapp/translations/en.json
@@ -94,7 +94,7 @@
 
         "ERROR_UPLOAD_100"     : "File transfer is either not supported or not enabled. Please contact your system administrator, or check your system logs.",
         "ERROR_UPLOAD_201"     : "Too many files are currently being transferred. Please wait for existing transfers to complete, and then try again.",
-        "ERROR_UPLOAD_202"     : "The file cannot be transferred because the remote desktop server is taking too long to respond. Please try again or or contact your system administrator.",
+        "ERROR_UPLOAD_202"     : "The file cannot be transferred because the remote desktop server is taking too long to respond. Please try again or contact your system administrator.",
         "ERROR_UPLOAD_203"     : "The remote desktop server encountered an error during transfer. Please try again or contact your system administrator.",
         "ERROR_UPLOAD_204"     : "The destination for the file transfer does not exist. Please check that the destination exists and try again.",
         "ERROR_UPLOAD_205"     : "The destination for the file transfer is currently locked. Please wait for any in-progress tasks to complete and try again.",
@@ -753,7 +753,7 @@
         
         "FORMAT_STARTDATE" : "@:APP.FORMAT_DATE_TIME_PRECISE",
 
-        "HELP_SESSIONS" : "All currently-active Guacamole sessions are listed here. If you wish to kill one or more sessions, check the box next to those sessions and click \"Kill Sessions\". Killing a session will immediately disconnect the user from the associated connection.",
+        "HELP_SESSIONS" : "This page will be populated with currently-active connections. The connections listed and the ability to kill those connections is dependent upon your access level. If you wish to kill one or more sessions, check the box next to those sessions and click \"Kill Sessions\". Killing a session will immediately disconnect the user from the associated connection.",
         
         "INFO_NO_SESSIONS" : "No active sessions",
 
diff --git a/guacamole/src/main/webapp/translations/es.json b/guacamole/src/main/webapp/translations/es.json
index 283779a..f2545bb 100644
--- a/guacamole/src/main/webapp/translations/es.json
+++ b/guacamole/src/main/webapp/translations/es.json
@@ -695,7 +695,7 @@
         
         "FORMAT_STARTDATE" : "@:APP.FORMAT_DATE_TIME_PRECISE",
 
-        "HELP_SESSIONS" : "Aquí se listan todas las sesiones activas que tiene actualmente Guacamole. Si quiere finalizar una o mas sesiones, marque la casilla correspondiente a esa/s sesión/es y haga clic en \"Finalizar Sesiones\". Si finaliza una sesión desconectará inmediatamente al usuario de la conexión asociada.",
+        "HELP_SESSIONS" : "Esta página se completará con las conexiones actualmente activas. Las conexiones enumeradas y la capacidad de eliminar esas conexiones dependen de su nivel de acceso. Si quiere finalizar una o mas sesiones, marque la casilla correspondiente a esa/s sesión/es y haga clic en \"Finalizar Sesiones\". Si finaliza una sesión desconectará inmediatamente al usuario de la conexión asociada.",
         
         "INFO_NO_SESSIONS" : "No hay sesiones activas",
 
diff --git a/guacamole/src/main/webapp/translations/fr.json b/guacamole/src/main/webapp/translations/fr.json
index 8ebbd36..9407178 100644
--- a/guacamole/src/main/webapp/translations/fr.json
+++ b/guacamole/src/main/webapp/translations/fr.json
@@ -624,7 +624,7 @@
         
         "FORMAT_STARTDATE" : "@:APP.FORMAT_DATE_TIME_PRECISE",
 
-        "HELP_SESSIONS" : "Toutes les connexions actives Guacamole sont listées ici. Si vous souhaitez en fermer une ou plusieurs, sélectionner les et cliquer sur \"Fermer Sessions\". La fermeture d'une session déconnectera immédiatement l'utilisateur.", 
+        "HELP_SESSIONS" : "Cette page sera remplie avec des connexions actuellement actives. Les connexions répertoriées et la possibilité de supprimer ces connexions dépendent de votre niveau d'accès. Si vous souhaitez en fermer une ou plusieurs, sélectionner les et cliquer sur \"Fermer Sessions\". La fermeture d'une session déconnectera immédiatement l'utilisateur.", 
         
         "INFO_NO_SESSIONS" : "Pas de session ouverte",
 
diff --git a/guacamole/src/main/webapp/translations/it.json b/guacamole/src/main/webapp/translations/it.json
index 5b3f641..442e709 100644
--- a/guacamole/src/main/webapp/translations/it.json
+++ b/guacamole/src/main/webapp/translations/it.json
@@ -566,7 +566,7 @@
         
         "FORMAT_STARTDATE" : "@:APP.FORMAT_DATE_TIME_PRECISE",
 
-        "HELP_SESSIONS" : "All currently-active Guacamole sessions are listed here. If you wish to kill one or more sessions, check the box next to those sessions and click \"Kill Sessions\". Killing a session will immediately disconnect the user from the associated connection.",
+        "HELP_SESSIONS" : "Questa pagina verrà popolata con connessioni attualmente attive. Le connessioni elencate e la possibilità di uccidere tali connessioni dipende dal tuo livello di accesso. Se desideri uccidere una o più sessioni, seleziona la casella accanto a quelle sessioni e fai clic su \"Uccidi sessioni \". L'uccisione di una sessione interromperà immediatamente l'utente dalla connessione associata.",
         
         "INFO_NO_SESSIONS" : "Nessuna sessione attiva",
 
diff --git a/guacamole/src/main/webapp/translations/nl.json b/guacamole/src/main/webapp/translations/nl.json
index 69a789a..00ed1f6 100644
--- a/guacamole/src/main/webapp/translations/nl.json
+++ b/guacamole/src/main/webapp/translations/nl.json
@@ -654,7 +654,7 @@
 
         "FORMAT_STARTDATE" : "@:APP.FORMAT_DATE_TIME_PRECISE",
 
-        "HELP_SESSIONS" : "Alle Guacamole sessies die op dit moment actief zijn worden hier getoond. Als u een of meerdere sessies wilt beeindigen, vink die sessie(s) dan aan en klik op \"Beeindig Sessies\". Door het verbreken van een sessie verliest de gebruiker ogenblikkelijk het contact met die sessie(s).",
+        "HELP_SESSIONS" : "Deze pagina wordt gevuld met momenteel actieve verbindingen. De vermelde verbindingen en de mogelijkheid om die verbindingen te doden, zijn afhankelijk van uw toegangsniveau. Als u een of meerdere sessies wilt beeindigen, vink die sessie(s) dan aan en klik op \"Beeindig Sessies\". Door het verbreken van een sessie verliest de gebruiker ogenblikkelijk het contact met die sessie(s).",
 
         "INFO_NO_SESSIONS" : "Geen actieve sessies",
 
diff --git a/guacamole/src/main/webapp/translations/no.json b/guacamole/src/main/webapp/translations/no.json
index 30ea871..bdec130 100644
--- a/guacamole/src/main/webapp/translations/no.json
+++ b/guacamole/src/main/webapp/translations/no.json
@@ -635,7 +635,7 @@
         
         "FORMAT_STARTDATE" : "@:APP.FORMAT_DATE_TIME_PRECISE",
 
-        "HELP_SESSIONS" : "Alle aktive Guacamolesesjoner er listet opp her. Dersom du ønsker å avbryte en eller flere sesjoner haker du av boksen ved siden av sesjonen og klikker \"Avbryt sesjoner\". Avbrytes en sesjon vil brukeren umiddelbart kobles av den aktuelle sesjonen.",
+        "HELP_SESSIONS" : "Denne siden vil bli fylt med nåværende aktive forbindelser. Tilkoblingene oppført og evnen til å drepe disse tilkoblingene er avhengig av tilgangsnivået ditt. Dersom du ønsker å avbryte en eller flere sesjoner haker du av boksen ved siden av sesjonen og klikker \"Avbryt sesjoner\". Avbrytes en sesjon vil brukeren umiddelbart kobles av den aktuelle sesjonen.",
         
         "INFO_NO_SESSIONS" : "Ingen aktive sesjoner",
 
diff --git a/guacamole/src/main/webapp/translations/ru.json b/guacamole/src/main/webapp/translations/ru.json
index 4f04525..d6b2d47 100644
--- a/guacamole/src/main/webapp/translations/ru.json
+++ b/guacamole/src/main/webapp/translations/ru.json
@@ -547,7 +547,7 @@
 
         "FORMAT_STARTDATE" : "@:APP.FORMAT_DATE_TIME_PRECISE",
 
-        "HELP_SESSIONS" : "Все активные в настоящий момент сессии Guacamole представлены здесь. Если вы хотите завершить одну или несколько сессий, выберите нужные сессии и нажмите на \"Завершить сессии\". Принудительное завершение сессий приведет к немедленному отключению пользователей, которые ими пользуются.",
+        "HELP_SESSIONS" : "Эта страница будет заполнена активными в настоящее время соединениями. Перечисленные соединения и возможность убивать эти соединения зависят от вашего уровня доступа. Если вы хотите завершить одну или несколько сессий, выберите нужные сессии и нажмите на \"Завершить сессии\". Принудительное завершение сессий приведет к немедленному отключению пользователей, которые ими пользуются.",
 
         "INFO_NO_SESSIONS" : "Нет активных сессий",
 
diff --git a/guacamole/src/main/webapp/translations/zh.json b/guacamole/src/main/webapp/translations/zh.json
new file mode 100644
index 0000000..dae03ec
--- /dev/null
+++ b/guacamole/src/main/webapp/translations/zh.json
@@ -0,0 +1,772 @@
+{
+    
+    "NAME" : "简体中文",
+    
+    "APP" : {
+
+        "NAME"    : "Apache Guacamole",
+        "VERSION" : "${project.version}",
+
+        "ACTION_ACKNOWLEDGE"        : "确定",
+        "ACTION_CANCEL"             : "取消",
+        "ACTION_CLONE"              : "克隆",
+        "ACTION_CONTINUE"           : "继续",
+        "ACTION_DELETE"             : "删除",
+        "ACTION_DELETE_SESSIONS"    : "删除会话",
+        "ACTION_DOWNLOAD"           : "下载",
+        "ACTION_LOGIN"              : "登录",
+        "ACTION_LOGOUT"             : "登出",
+        "ACTION_MANAGE_CONNECTIONS" : "连接",
+        "ACTION_MANAGE_PREFERENCES" : "偏好",
+        "ACTION_MANAGE_SETTINGS"    : "设置",
+        "ACTION_MANAGE_SESSIONS"    : "活动会话",
+        "ACTION_MANAGE_USERS"       : "用户",
+        "ACTION_NAVIGATE_BACK"      : "返回",
+        "ACTION_NAVIGATE_HOME"      : "首页",
+        "ACTION_SAVE"               : "保存",
+        "ACTION_SEARCH"             : "搜索",
+        "ACTION_SHARE"              : "共享",
+        "ACTION_UPDATE_PASSWORD"    : "更新密码",
+        "ACTION_VIEW_HISTORY"       : "历史",
+
+        "DIALOG_HEADER_ERROR" : "出错",
+
+        "ERROR_PASSWORD_BLANK"    : "密码不能留空。",
+        "ERROR_PASSWORD_MISMATCH" : "输入的密码不吻合。",
+        
+        "FIELD_HEADER_PASSWORD"       : "密码:",
+        "FIELD_HEADER_PASSWORD_AGAIN" : "重输密码:",
+
+        "FIELD_PLACEHOLDER_FILTER" : "过滤",
+
+        "FORMAT_DATE_TIME_PRECISE" : "yyyy-MM-dd HH:mm:ss",
+
+        "INFO_ACTIVE_USER_COUNT" : "正在被{USERS}用户使用。",
+
+        "TEXT_ANONYMOUS_USER"   : "匿名",
+        "TEXT_HISTORY_DURATION" : "{VALUE} {UNIT, select, second{秒} minute{分} hour{小时} day{天} other{}}"
+
+    },
+
+    "CLIENT" : {
+
+        "ACTION_ACKNOWLEDGE"               : "@:APP.ACTION_ACKNOWLEDGE",
+        "ACTION_CLEAR_COMPLETED_TRANSFERS" : "清除",
+        "ACTION_DISCONNECT"                : "断开连接",
+        "ACTION_LOGOUT"                    : "@:APP.ACTION_LOGOUT",
+        "ACTION_NAVIGATE_BACK"             : "@:APP.ACTION_NAVIGATE_BACK",
+        "ACTION_NAVIGATE_HOME"             : "@:APP.ACTION_NAVIGATE_HOME",
+        "ACTION_RECONNECT"                 : "重新连接",
+        "ACTION_SAVE_FILE"                 : "@:APP.ACTION_SAVE",
+        "ACTION_SHARE"                     : "@:APP.ACTION_SHARE",
+        "ACTION_UPLOAD_FILES"              : "上传文件",
+
+        "DIALOG_HEADER_CONNECTING"       : "正在连接",
+        "DIALOG_HEADER_CONNECTION_ERROR" : "连接出错",
+        "DIALOG_HEADER_DISCONNECTED"     : "已断开连接",
+
+        "ERROR_CLIENT_201"     : "因服务器繁忙,本连接已被关闭。请稍候几分钟再重试。",
+        "ERROR_CLIENT_202"     : "因远程桌面太久没有应答,Guacamole服务器关闭了本连接。请重试或联系您的系统管理员。",
+        "ERROR_CLIENT_203"     : "远程桌面服务器因为出错而关闭了本连接。请重试或联系您的系统管理员。",
+        "ERROR_CLIENT_207"     : "联系不上远程桌面服务器。如果问题持续,请通知您的系统管理员,或检查您的系统日志。",
+        "ERROR_CLIENT_208"     : "远程桌面服务器不在线。如果问题持续,请通知您的系统管理员,或检查您的系统日志。",
+        "ERROR_CLIENT_209"     : "因与另一个连接冲突,远程桌面服务器关闭了本连接。请稍后重试。",
+        "ERROR_CLIENT_20A"     : "因长时间没有活动,远程桌面服务器关闭了本连接。如果这不是期望的设置,请通知您的系统管理员,或检查您的系统设置。",
+        "ERROR_CLIENT_20B"     : "远程桌面服务器强制关闭了本连接。如果这不是期望的配置,请通知您的系统管理员,或检查您的系统日志。",
+        "ERROR_CLIENT_301"     : "登录失败。请先重新连接再重试。",
+        "ERROR_CLIENT_303"     : "远程桌面服务器拒绝了本连接。如果需要使用本连接,请联系您的系统管理员开放权限,或者检查您的系统设置。",
+        "ERROR_CLIENT_308"     : "因为您的浏览器长时间没有应答,Guacamole服务器关闭了本连接。这通常是因为网络问题(如不稳定的无线连接或网速太慢等)而导致的。请先检查您的网络连接再重试。",
+        "ERROR_CLIENT_31D"     : "因为您已超出了单一用户可同时使用的连接数量,Guacamole服务器拒绝了本连接。请先关闭至少一个连接再重试。",
+        "ERROR_CLIENT_DEFAULT" : "本连接因为Guacamole服务器出现了内部错误而被终止。如果问题持续,请通知您的系统管理员,或检查您的系统日志。",
+
+        "ERROR_TUNNEL_201"     : "因为正在使用的活动连接太多,Guacamole服务器拒绝了本连接。请稍后再重试。",
+        "ERROR_TUNNEL_202"     : "因服务器太久没有应答,本连续已被关闭。这通常是因为网络问题(如不稳定的无线连接或网速太慢等)而导致的。请先检查您的网络连接再重试,或者联系您的系统管理员。",
+        "ERROR_TUNNEL_203"     : "服务器出错并关闭了本连接。请重试,或联系您的系统管理员。",
+        "ERROR_TUNNEL_204"     : "请求的连接不存在。请先检查连接的名字再重试。",
+        "ERROR_TUNNEL_205"     : "本连接正在使用中,并且不允许共享连接。请稍后重试。",
+        "ERROR_TUNNEL_207"     : "联系不上Guacamole服务器。请先检查您的网络连接再重试。",
+        "ERROR_TUNNEL_208"     : "Guacamole服务器不接受连接请求。请先检查您的网络连接再重试。",
+        "ERROR_TUNNEL_301"     : "您还未登录,所以没有使用此连接的权限。请先登录再重试。",
+        "ERROR_TUNNEL_303"     : "您没有使用此连接的权限。如果您的确需要使用此连接,请联系您的系统管理员开通权限,或检查您的系统设置。",
+        "ERROR_TUNNEL_308"     : "因为您的浏览器长时间没有应答,Guacamole服务器关闭了本连接。这通常是因为网络问题(如不稳定的无线连接或网速太慢等)而导致的。请先检查您的网络连接再重试。",
+        "ERROR_TUNNEL_31D"     : "因为您已超出了单一用户可同时使用的连接数量,Guacamole服务器拒绝了本连接。请先关闭至少一个连接再重试。",
+        "ERROR_TUNNEL_DEFAULT" : "本连接因为Guacamole服务器出现了内部错误而被终止。如果问题持续,请通知您的系统管理员,或检查您的系统日志。",
+
+        "ERROR_UPLOAD_100"     : "不支持或不允许使用文件传输。请联系您的系统管理员,或检查您的系统日志。",
+        "ERROR_UPLOAD_201"     : "正在同时传输太多文件。请等待当前的文件传输任务完成后,再重试。",
+        "ERROR_UPLOAD_202"     : "因远程桌面服务器太久没有应答,文件不能传输。请重试或联系您的系统管理员。",
+        "ERROR_UPLOAD_203"     : "远程桌面服务器在文件传输时出错。请重试或联系您的系统管理员。",
+        "ERROR_UPLOAD_204"     : "文件传输的接收目录不存在。请先检查接收目录再重试。",
+        "ERROR_UPLOAD_205"     : "文件传输的接收目录正被锁定。请等待正在进行的操作完成后,再重试。",
+        "ERROR_UPLOAD_301"     : "您还未登录,所以没有上传此文件的权限。请先登录再重试。",
+        "ERROR_UPLOAD_303"     : "您没有上传此文件的权限。如果您需要权限,请检查您的系统设置,或联系您的系统管理员。",
+        "ERROR_UPLOAD_308"     : "文件传输已停止。这通常是因为网络问题(如不稳定的无线连接或网速太慢等)而导致的。请先检查您的网络连接再重试。",
+        "ERROR_UPLOAD_31D"     : "正在同时传输太多文件。请等待当前的传输任务完成后,再重试。",
+        "ERROR_UPLOAD_DEFAULT" : "本连接因为Guacamole服务器出现了内部错误而被终止。如果问题持续,请通知您的系统管理员,或检查您的系统日志。",
+
+        "HELP_CLIPBOARD"           : "复制/剪切的文本将出现在这里。对下面文本内容所作的修改将会影响远程电脑上的剪贴板。",
+        "HELP_INPUT_METHOD_NONE"   : "没有选择任何输入法。将从连接的物理键盘接受键盘输入。",
+        "HELP_INPUT_METHOD_OSK"    : "显示并从内建的Guacamole屏幕键盘接受输入。屏幕键盘可以输入平常无法输入的按键组合(如Ctrl-Alt-Del等)。",
+        "HELP_INPUT_METHOD_TEXT"   : "允许输入文本,并根据所输入的文本模拟键盘事件。可用于没有物理键盘的设备,如手机等。",
+        "HELP_MOUSE_MODE"          : "设置远程电脑上的鼠标对触控行为的反应。",
+        "HELP_MOUSE_MODE_ABSOLUTE" : "点击时立即触发按键。在点击的位置触发鼠标按键事件。",
+        "HELP_MOUSE_MODE_RELATIVE" : "拖拽时移动鼠标,再点击时触发按键。在鼠标当前所在的位置触发按键事件。",
+        "HELP_SHARE_LINK"          : "正在共享当前连接,并可被使用以下链接的任何人使用:",
+
+        "INFO_CONNECTION_SHARED" : "此连接已被共享。",
+        "INFO_NO_FILE_TRANSFERS" : "无文件传输任务。",
+
+        "NAME_INPUT_METHOD_NONE"   : "无输入法",
+        "NAME_INPUT_METHOD_OSK"    : "屏幕键盘",
+        "NAME_INPUT_METHOD_TEXT"   : "文本输入",
+        "NAME_KEY_CTRL"            : "Ctrl",
+        "NAME_KEY_ALT"             : "Alt",
+        "NAME_KEY_ESC"             : "Esc",
+        "NAME_KEY_TAB"             : "Tab",
+        "NAME_MOUSE_MODE_ABSOLUTE" : "触控屏",
+        "NAME_MOUSE_MODE_RELATIVE" : "触控板",
+
+        "SECTION_HEADER_CLIPBOARD"      : "剪贴板",
+        "SECTION_HEADER_DEVICES"        : "设备",
+        "SECTION_HEADER_DISPLAY"        : "显示",
+        "SECTION_HEADER_FILE_TRANSFERS" : "文件传输",
+        "SECTION_HEADER_INPUT_METHOD"   : "输入法",
+        "SECTION_HEADER_MOUSE_MODE"     : "模拟鼠标模式",
+
+        "TEXT_ZOOM_AUTO_FIT"              : "自适应浏览器窗口大小",
+        "TEXT_CLIENT_STATUS_IDLE"         : "空闲。",
+        "TEXT_CLIENT_STATUS_CONNECTING"   : "正在连接Guacamole……",
+        "TEXT_CLIENT_STATUS_DISCONNECTED" : "您的连接已断开。",
+        "TEXT_CLIENT_STATUS_UNSTABLE"     : "到Guacamole服务器的网络连接似乎不太稳定。",
+        "TEXT_CLIENT_STATUS_WAITING"      : "已连接到Guacamole。正在等候应答……",
+        "TEXT_RECONNECT_COUNTDOWN"        : "在{REMAINING}秒后重连……",
+        "TEXT_FILE_TRANSFER_PROGRESS"     : "{PROGRESS} {UNIT, select, b{B} kb{KB} mb{MB} gb{GB} other{}}",
+
+        "URL_OSK_LAYOUT" : "layouts/en-us-qwerty.json"
+
+    },
+
+    "DATA_SOURCE_DEFAULT" : {
+        "NAME" : "缺省(XML)"
+    },
+
+    "FORM" : {
+
+        "FIELD_PLACEHOLDER_DATE" : "YYYY-MM-DD",
+        "FIELD_PLACEHOLDER_TIME" : "HH:MM:SS",
+
+        "HELP_SHOW_PASSWORD" : "点击显示密码",
+        "HELP_HIDE_PASSWORD" : "点击隐藏密码"
+
+    },
+
+    "HOME" : {
+
+        "FIELD_PLACEHOLDER_FILTER" : "@:APP.FIELD_PLACEHOLDER_FILTER",
+
+        "INFO_ACTIVE_USER_COUNT" : "@:APP.INFO_ACTIVE_USER_COUNT",
+
+        "INFO_NO_RECENT_CONNECTIONS" : "无最近使用过的连接。",
+        
+        "PASSWORD_CHANGED" : "密码已修改。",
+
+        "SECTION_HEADER_ALL_CONNECTIONS"    : "全部连接",
+        "SECTION_HEADER_RECENT_CONNECTIONS" : "最近使用过的连接"
+
+    },
+
+    "LIST" : {
+
+        "TEXT_ANONYMOUS_USER" : "匿名"
+
+    },
+
+    "LOGIN": {
+
+        "ACTION_ACKNOWLEDGE" : "@:APP.ACTION_ACKNOWLEDGE",
+        "ACTION_CONTINUE"    : "@:APP.ACTION_CONTINUE",
+        "ACTION_LOGIN"       : "@:APP.ACTION_LOGIN",
+
+        "DIALOG_HEADER_ERROR" : "@:APP.DIALOG_HEADER_ERROR",
+
+        "ERROR_INVALID_LOGIN" : "非法登录",
+
+        "FIELD_HEADER_USERNAME" : "用户名",
+        "FIELD_HEADER_PASSWORD" : "密码"
+
+    },
+
+    "MANAGE_CONNECTION" : {
+
+        "ACTION_ACKNOWLEDGE"          : "@:APP.ACTION_ACKNOWLEDGE",
+        "ACTION_CANCEL"               : "@:APP.ACTION_CANCEL",
+        "ACTION_CLONE"                : "@:APP.ACTION_CLONE",
+        "ACTION_DELETE"               : "@:APP.ACTION_DELETE",
+        "ACTION_SAVE"                 : "@:APP.ACTION_SAVE",
+
+        "DIALOG_HEADER_CONFIRM_DELETE" : "删除连接",
+        "DIALOG_HEADER_ERROR"          : "@:APP.DIALOG_HEADER_ERROR",
+
+        "FIELD_HEADER_LOCATION" : "位置:",
+        "FIELD_HEADER_NAME"     : "名称:",
+        "FIELD_HEADER_PROTOCOL" : "协议:",
+
+        "FORMAT_HISTORY_START" : "@:APP.FORMAT_DATE_TIME_PRECISE",
+
+        "INFO_CONNECTION_DURATION_UNKNOWN" : "--",
+        "INFO_CONNECTION_ACTIVE_NOW"       : "活动中",
+        "INFO_CONNECTION_NOT_USED"         : "此连接未被使用过。",
+
+        "SECTION_HEADER_EDIT_CONNECTION" : "编辑连接",
+        "SECTION_HEADER_HISTORY"         : "使用历史",
+        "SECTION_HEADER_PARAMETERS"      : "参数",
+
+        "TABLE_HEADER_HISTORY_USERNAME"   : "用户名",
+        "TABLE_HEADER_HISTORY_START"      : "开始时间",
+        "TABLE_HEADER_HISTORY_DURATION"   : "持续时间",
+        "TABLE_HEADER_HISTORY_REMOTEHOST" : "远程主机",
+
+        "TEXT_CONFIRM_DELETE"   : "将无法恢复已被删除的连接。确定要删除这个连接吗?",
+        "TEXT_HISTORY_DURATION" : "@:APP.TEXT_HISTORY_DURATION"
+
+    },
+
+    "MANAGE_CONNECTION_GROUP" : {
+
+        "ACTION_ACKNOWLEDGE"   : "@:APP.ACTION_ACKNOWLEDGE",
+        "ACTION_CANCEL"        : "@:APP.ACTION_CANCEL",
+        "ACTION_CLONE"         : "@:APP.ACTION_CLONE",
+        "ACTION_DELETE"        : "@:APP.ACTION_DELETE",
+        "ACTION_SAVE"          : "@:APP.ACTION_SAVE",
+
+        "DIALOG_HEADER_CONFIRM_DELETE" : "删除连接组",
+        "DIALOG_HEADER_ERROR"          : "@:APP.DIALOG_HEADER_ERROR",
+
+        "FIELD_HEADER_LOCATION" : "位置:",
+        "FIELD_HEADER_NAME"     : "名字:",
+        "FIELD_HEADER_TYPE"     : "类型:",
+
+        "NAME_TYPE_BALANCING"       : "负载平衡",
+        "NAME_TYPE_ORGANIZATIONAL"  : "组织架构",
+
+        "SECTION_HEADER_EDIT_CONNECTION_GROUP" : "编辑连接组",
+
+        "TEXT_CONFIRM_DELETE" : "将不能恢复已被删除的连接组。确定要删除这个连接组吗?"
+
+    },
+
+    "MANAGE_SHARING_PROFILE" : {
+
+        "ACTION_ACKNOWLEDGE" : "@:APP.ACTION_ACKNOWLEDGE",
+        "ACTION_CANCEL"      : "@:APP.ACTION_CANCEL",
+        "ACTION_CLONE"       : "@:APP.ACTION_CLONE",
+        "ACTION_DELETE"      : "@:APP.ACTION_DELETE",
+        "ACTION_SAVE"        : "@:APP.ACTION_SAVE",
+
+        "DIALOG_HEADER_CONFIRM_DELETE" : "删除共享设定",
+        "DIALOG_HEADER_ERROR"          : "@:APP.DIALOG_HEADER_ERROR",
+
+        "FIELD_HEADER_NAME"               : "名字:",
+        "FIELD_HEADER_PRIMARY_CONNECTION" : "主连接:",
+
+        "SECTION_HEADER_EDIT_SHARING_PROFILE" : "编辑共享设定",
+        "SECTION_HEADER_PARAMETERS"           : "参数",
+
+        "TEXT_CONFIRM_DELETE" : "将不能恢复已被删除的共享设定。确定要删除这个共享设定吗?"
+
+    },
+
+    "MANAGE_USER" : {
+
+        "ACTION_ACKNOWLEDGE"   : "@:APP.ACTION_ACKNOWLEDGE",
+        "ACTION_CANCEL"        : "@:APP.ACTION_CANCEL",
+        "ACTION_CLONE"         : "@:APP.ACTION_CLONE",
+        "ACTION_DELETE"        : "@:APP.ACTION_DELETE",
+        "ACTION_SAVE"          : "@:APP.ACTION_SAVE",
+
+        "DIALOG_HEADER_CONFIRM_DELETE" : "删除用户",
+        "DIALOG_HEADER_ERROR"          : "@:APP.DIALOG_HEADER_ERROR",
+
+        "ERROR_PASSWORD_MISMATCH" : "@:APP.ERROR_PASSWORD_MISMATCH",
+
+        "FIELD_HEADER_ADMINISTER_SYSTEM"             : "授权管理系统:",
+        "FIELD_HEADER_CHANGE_OWN_PASSWORD"           : "修改自己的密码:",
+        "FIELD_HEADER_CREATE_NEW_USERS"              : "新建用户:",
+        "FIELD_HEADER_CREATE_NEW_CONNECTIONS"        : "新建连接:",
+        "FIELD_HEADER_CREATE_NEW_CONNECTION_GROUPS"  : "新建连接组:",
+        "FIELD_HEADER_CREATE_NEW_SHARING_PROFILES"   : "新建共享设定:",
+        "FIELD_HEADER_PASSWORD"                      : "@:APP.FIELD_HEADER_PASSWORD",
+        "FIELD_HEADER_PASSWORD_AGAIN"                : "@:APP.FIELD_HEADER_PASSWORD_AGAIN",
+        "FIELD_HEADER_USERNAME"                      : "用户名:",
+
+        "FIELD_PLACEHOLDER_FILTER" : "@:APP.FIELD_PLACEHOLDER_FILTER",
+
+        "INFO_READ_ONLY" : "对不起,不能编辑此用户的账户。",
+
+        "SECTION_HEADER_CONNECTIONS" : "连接",
+        "SECTION_HEADER_EDIT_USER"   : "编辑用户",
+        "SECTION_HEADER_PERMISSIONS" : "使用权限",
+
+        "TEXT_CONFIRM_DELETE" : "将不能恢复已被删除的用户。确定要删除这个用户吗?"
+
+    },
+    
+    "PROTOCOL_RDP" : {
+
+        "FIELD_HEADER_CLIENT_NAME"     : "客户端:",
+        "FIELD_HEADER_COLOR_DEPTH"     : "色彩深度:",
+        "FIELD_HEADER_CONSOLE"         : "管理员控制台:",
+        "FIELD_HEADER_CONSOLE_AUDIO"   : "在控制台内支持音频:",
+        "FIELD_HEADER_CREATE_DRIVE_PATH" : "自动建立虚拟盘:",
+        "FIELD_HEADER_CREATE_RECORDING_PATH" : "自动建立录像目录:",
+        "FIELD_HEADER_DISABLE_AUDIO"   : "禁用音频:",
+        "FIELD_HEADER_DISABLE_AUTH"    : "禁用认证:",
+        "FIELD_HEADER_DOMAIN"          : "域:",
+        "FIELD_HEADER_DPI"             : "分辨率(DPI):",
+        "FIELD_HEADER_DRIVE_PATH"      : "虚拟盘路径:",
+        "FIELD_HEADER_ENABLE_AUDIO_INPUT"         : "启用音频输入(话筒):",
+        "FIELD_HEADER_ENABLE_DESKTOP_COMPOSITION" : "启用桌面合成效果(Aero):",
+        "FIELD_HEADER_ENABLE_DRIVE"               : "启用虚拟盘:",
+        "FIELD_HEADER_ENABLE_FONT_SMOOTHING"      : "启用字体平滑(ClearType):",
+        "FIELD_HEADER_ENABLE_FULL_WINDOW_DRAG"    : "启用全窗口拖拽:",
+        "FIELD_HEADER_ENABLE_MENU_ANIMATIONS"     : "启用菜单动画:",
+        "FIELD_HEADER_DISABLE_BITMAP_CACHING"     : "启用位图缓存:",
+        "FIELD_HEADER_DISABLE_OFFSCREEN_CACHING"  : "启用离屏缓存:",
+        "FIELD_HEADER_DISABLE_GLYPH_CACHING"      : "禁用字形缓存:",
+        "FIELD_HEADER_ENABLE_PRINTING"            : "启用打印功能:",
+        "FIELD_HEADER_ENABLE_SFTP"     : "启用SFTP:",
+        "FIELD_HEADER_ENABLE_THEMING"             : "启用桌面主题:",
+        "FIELD_HEADER_ENABLE_WALLPAPER"           : "启用桌面墙纸:",
+        "FIELD_HEADER_GATEWAY_DOMAIN"   : "域:",
+        "FIELD_HEADER_GATEWAY_HOSTNAME" : "主机名:",
+        "FIELD_HEADER_GATEWAY_PASSWORD" : "密码:",
+        "FIELD_HEADER_GATEWAY_PORT"     : "端口:",
+        "FIELD_HEADER_GATEWAY_USERNAME" : "用户名:",
+        "FIELD_HEADER_HEIGHT"          : "高度:",
+        "FIELD_HEADER_HOSTNAME"        : "主机名:",
+        "FIELD_HEADER_IGNORE_CERT"     : "忽略服务器证书:",
+        "FIELD_HEADER_INITIAL_PROGRAM" : "初始程序:",
+        "FIELD_HEADER_LOAD_BALANCE_INFO" : "负载平衡信息/cookie:",
+        "FIELD_HEADER_PASSWORD"        : "密码:",
+        "FIELD_HEADER_PORT"            : "端口:",
+        "FIELD_HEADER_PRECONNECTION_BLOB" : "预连接BLOB(VM标识):",
+        "FIELD_HEADER_PRECONNECTION_ID"   : "RDP源标识:",
+        "FIELD_HEADER_READ_ONLY"      : "只读:",
+        "FIELD_HEADER_RECORDING_EXCLUDE_MOUSE"  : "排除鼠标:",
+        "FIELD_HEADER_RECORDING_EXCLUDE_OUTPUT" : "排除图像/数据流:",
+        "FIELD_HEADER_RECORDING_INCLUDE_KEYS"   : "包含按键事件:",
+        "FIELD_HEADER_RECORDING_NAME" : "录像名:",
+        "FIELD_HEADER_RECORDING_PATH" : "录像路径:",
+        "FIELD_HEADER_RESIZE_METHOD" : "缩放方法:",
+        "FIELD_HEADER_REMOTE_APP_ARGS" : "参数:",
+        "FIELD_HEADER_REMOTE_APP_DIR"  : "工作目录:",
+        "FIELD_HEADER_REMOTE_APP"      : "程序:",
+        "FIELD_HEADER_SECURITY"        : "安全模式:",
+        "FIELD_HEADER_SERVER_LAYOUT"   : "键盘布局:",
+        "FIELD_HEADER_SFTP_DIRECTORY"             : "缺省文件上传目录:",
+        "FIELD_HEADER_SFTP_HOSTNAME"              : "主机名:",
+        "FIELD_HEADER_SFTP_SERVER_ALIVE_INTERVAL" : "SFTP keepalive时间间隔:",
+        "FIELD_HEADER_SFTP_PASSPHRASE"            : "口令:",
+        "FIELD_HEADER_SFTP_PASSWORD"              : "密码:",
+        "FIELD_HEADER_SFTP_PORT"                  : "端口:",
+        "FIELD_HEADER_SFTP_PRIVATE_KEY"           : "私钥:",
+        "FIELD_HEADER_SFTP_ROOT_DIRECTORY"        : "文件浏览器根目录:",
+        "FIELD_HEADER_SFTP_USERNAME"              : "用户名:",
+        "FIELD_HEADER_STATIC_CHANNELS" : "静态通道名:",
+        "FIELD_HEADER_USERNAME"        : "用户名:",
+        "FIELD_HEADER_WIDTH"           : "宽度:",
+
+        "FIELD_OPTION_COLOR_DEPTH_16"    : "低色(16位)",
+        "FIELD_OPTION_COLOR_DEPTH_24"    : "真彩(24位)",
+        "FIELD_OPTION_COLOR_DEPTH_32"    : "真彩(32位)",
+        "FIELD_OPTION_COLOR_DEPTH_8"     : "256色",
+        "FIELD_OPTION_COLOR_DEPTH_EMPTY" : "",
+
+        "FIELD_OPTION_RESIZE_METHOD_DISPLAY_UPDATE" : "“显示更新”虚拟通道(RDP 8.1+)",
+        "FIELD_OPTION_RESIZE_METHOD_EMPTY"          : "",
+        "FIELD_OPTION_RESIZE_METHOD_RECONNECT"      : "重新连接",
+
+        "FIELD_OPTION_SECURITY_ANY"   : "任意",
+        "FIELD_OPTION_SECURITY_EMPTY" : "",
+        "FIELD_OPTION_SECURITY_NLA"   : "NLA(网络级别认证)",
+        "FIELD_OPTION_SECURITY_RDP"   : "RDP加密",
+        "FIELD_OPTION_SECURITY_TLS"   : "TLS加密",
+
+        "FIELD_OPTION_SERVER_LAYOUT_DE_DE_QWERTZ" : "German (Qwertz)",
+        "FIELD_OPTION_SERVER_LAYOUT_EMPTY"        : "",
+        "FIELD_OPTION_SERVER_LAYOUT_EN_GB_QWERTY" : "UK English (Qwerty)",
+        "FIELD_OPTION_SERVER_LAYOUT_EN_US_QWERTY" : "US English (Qwerty)",
+        "FIELD_OPTION_SERVER_LAYOUT_ES_ES_QWERTY" : "Spanish (Qwerty)",
+        "FIELD_OPTION_SERVER_LAYOUT_FAILSAFE"     : "Unicode",
+        "FIELD_OPTION_SERVER_LAYOUT_FR_CH_QWERTZ" : "Swiss French (Qwertz)",
+        "FIELD_OPTION_SERVER_LAYOUT_FR_FR_AZERTY" : "French (Azerty)",
+        "FIELD_OPTION_SERVER_LAYOUT_IT_IT_QWERTY" : "Italian (Qwerty)",
+        "FIELD_OPTION_SERVER_LAYOUT_JA_JP_QWERTY" : "Japanese (Qwerty)",
+        "FIELD_OPTION_SERVER_LAYOUT_PT_BR_QWERTY" : "Portuguese Brazilian (Qwerty)",
+        "FIELD_OPTION_SERVER_LAYOUT_SV_SE_QWERTY" : "Swedish (Qwerty)",
+        "FIELD_OPTION_SERVER_LAYOUT_TR_TR_QWERTY" : "Turkish-Q (Qwerty)",
+
+        "NAME" : "RDP",
+
+        "SECTION_HEADER_AUTHENTICATION"     : "认证",
+        "SECTION_HEADER_BASIC_PARAMETERS"   : "基础设置",
+        "SECTION_HEADER_DEVICE_REDIRECTION" : "设备重定向",
+        "SECTION_HEADER_DISPLAY"            : "显示",
+        "SECTION_HEADER_GATEWAY"            : "远程桌面网关",
+        "SECTION_HEADER_LOAD_BALANCING"     : "负载平衡",
+        "SECTION_HEADER_NETWORK"            : "网络",
+        "SECTION_HEADER_PERFORMANCE"        : "性能",
+        "SECTION_HEADER_PRECONNECTION_PDU"  : "预连接PDU / Hyper-V",
+        "SECTION_HEADER_RECORDING"          : "屏幕录像",
+        "SECTION_HEADER_REMOTEAPP"          : "RemoteApp",
+        "SECTION_HEADER_SFTP"               : "SFTP"
+
+    },
+
+    "PROTOCOL_SSH" : {
+
+        "FIELD_HEADER_BACKSPACE"    : "退格键发送:",
+        "FIELD_HEADER_COLOR_SCHEME" : "配色方案:",
+        "FIELD_HEADER_COMMAND"      : "运行命令:",
+        "FIELD_HEADER_CREATE_RECORDING_PATH" : "自动建立录像目录:",
+        "FIELD_HEADER_CREATE_TYPESCRIPT_PATH" : "自动建立打字稿目录:",
+        "FIELD_HEADER_FONT_NAME"   : "字体名:",
+        "FIELD_HEADER_FONT_SIZE"   : "字体大小:",
+        "FIELD_HEADER_ENABLE_SFTP" : "启用SFTP:",
+        "FIELD_HEADER_HOSTNAME"    : "主机名:",
+        "FIELD_HEADER_USERNAME"    : "用户名:",
+        "FIELD_HEADER_PASSWORD"    : "密码:",
+        "FIELD_HEADER_PASSPHRASE"  : "口令:",
+        "FIELD_HEADER_PORT"        : "端口:",
+        "FIELD_HEADER_PRIVATE_KEY" : "私钥:",
+        "FIELD_HEADER_READ_ONLY"   : "只读:",
+        "FIELD_HEADER_RECORDING_EXCLUDE_MOUSE"  : "排除鼠标:",
+        "FIELD_HEADER_RECORDING_EXCLUDE_OUTPUT" : "排除图像/数据流:",
+        "FIELD_HEADER_RECORDING_INCLUDE_KEYS"   : "包含按键事件:",
+        "FIELD_HEADER_RECORDING_NAME" : "录像名:",
+        "FIELD_HEADER_RECORDING_PATH" : "录像路径:",
+        "FIELD_HEADER_SERVER_ALIVE_INTERVAL" : "服务器keepalive时间间隔:",
+        "FIELD_HEADER_SFTP_ROOT_DIRECTORY"   : "文件浏览器根目录:",
+        "FIELD_HEADER_TYPESCRIPT_NAME" : "打字稿名:",
+        "FIELD_HEADER_TYPESCRIPT_PATH" : "打字稿路径:",
+
+        "FIELD_OPTION_BACKSPACE_EMPTY" : "",
+        "FIELD_OPTION_BACKSPACE_8"     : "退格键(Ctrl-H)",
+        "FIELD_OPTION_BACKSPACE_127"   : "删除键(Ctrl-?)",
+
+        "FIELD_OPTION_COLOR_SCHEME_BLACK_WHITE" : "白底黑字",
+        "FIELD_OPTION_COLOR_SCHEME_EMPTY"       : "",
+        "FIELD_OPTION_COLOR_SCHEME_GRAY_BLACK"  : "黑底灰字",
+        "FIELD_OPTION_COLOR_SCHEME_GREEN_BLACK" : "黑底绿字",
+        "FIELD_OPTION_COLOR_SCHEME_WHITE_BLACK" : "黑底白字",
+
+        "FIELD_OPTION_FONT_SIZE_8"     : "8",
+        "FIELD_OPTION_FONT_SIZE_9"     : "9",
+        "FIELD_OPTION_FONT_SIZE_10"    : "10",
+        "FIELD_OPTION_FONT_SIZE_11"    : "11",
+        "FIELD_OPTION_FONT_SIZE_12"    : "12",
+        "FIELD_OPTION_FONT_SIZE_14"    : "14",
+        "FIELD_OPTION_FONT_SIZE_18"    : "18",
+        "FIELD_OPTION_FONT_SIZE_24"    : "24",
+        "FIELD_OPTION_FONT_SIZE_30"    : "30",
+        "FIELD_OPTION_FONT_SIZE_36"    : "36",
+        "FIELD_OPTION_FONT_SIZE_48"    : "48",
+        "FIELD_OPTION_FONT_SIZE_60"    : "60",
+        "FIELD_OPTION_FONT_SIZE_72"    : "72",
+        "FIELD_OPTION_FONT_SIZE_96"    : "96",
+        "FIELD_OPTION_FONT_SIZE_EMPTY" : "",
+
+        "NAME" : "SSH",
+
+        "SECTION_HEADER_AUTHENTICATION" : "认证",
+        "SECTION_HEADER_BEHAVIOR"       : "终端行为",
+        "SECTION_HEADER_DISPLAY"        : "显示",
+        "SECTION_HEADER_NETWORK"        : "网络",
+        "SECTION_HEADER_RECORDING"      : "屏幕录像",
+        "SECTION_HEADER_SESSION"        : "会话 / 环境",
+        "SECTION_HEADER_TYPESCRIPT"     : "打字稿(文本会话录像)",
+        "SECTION_HEADER_SFTP"           : "SFTP"
+
+    },
+
+    "PROTOCOL_TELNET" : {
+
+        "FIELD_HEADER_BACKSPACE"      : "退格键发送:",
+        "FIELD_HEADER_COLOR_SCHEME"   : "配色方案:",
+        "FIELD_HEADER_CREATE_RECORDING_PATH" : "自动建立录像目录:",
+        "FIELD_HEADER_CREATE_TYPESCRIPT_PATH" : "自动建立打字稿目录:",
+        "FIELD_HEADER_FONT_NAME"      : "字体名:",
+        "FIELD_HEADER_FONT_SIZE"      : "字体大小:",
+        "FIELD_HEADER_HOSTNAME"       : "主机名:",
+        "FIELD_HEADER_USERNAME"       : "用户名:",
+        "FIELD_HEADER_PASSWORD"       : "密码:",
+        "FIELD_HEADER_PASSWORD_REGEX" : "密码规则正则表达式:",
+        "FIELD_HEADER_PORT"           : "端口:",
+        "FIELD_HEADER_READ_ONLY"      : "只读:",
+        "FIELD_HEADER_RECORDING_EXCLUDE_MOUSE"  : "排除鼠标:",
+        "FIELD_HEADER_RECORDING_EXCLUDE_OUTPUT" : "排除图像/数据流:",
+        "FIELD_HEADER_RECORDING_INCLUDE_KEYS"   : "包含按键事件:",
+        "FIELD_HEADER_RECORDING_NAME" : "录像名:",
+        "FIELD_HEADER_RECORDING_PATH" : "录像路径:",
+        "FIELD_HEADER_TYPESCRIPT_NAME" : "打字稿名:",
+        "FIELD_HEADER_TYPESCRIPT_PATH" : "打字稿路径:",
+
+        "FIELD_OPTION_BACKSPACE_EMPTY" : "",
+        "FIELD_OPTION_BACKSPACE_8"     : "退格键(Ctrl-H)",
+        "FIELD_OPTION_BACKSPACE_127"   : "删除键(Ctrl-?)",
+
+        "FIELD_OPTION_COLOR_SCHEME_BLACK_WHITE" : "白底黑字",
+        "FIELD_OPTION_COLOR_SCHEME_EMPTY"       : "",
+        "FIELD_OPTION_COLOR_SCHEME_GRAY_BLACK"  : "黑底灰字",
+        "FIELD_OPTION_COLOR_SCHEME_GREEN_BLACK" : "黑底绿字",
+        "FIELD_OPTION_COLOR_SCHEME_WHITE_BLACK" : "黑底白字",
+
+        "FIELD_OPTION_FONT_SIZE_8"     : "8",
+        "FIELD_OPTION_FONT_SIZE_9"     : "9",
+        "FIELD_OPTION_FONT_SIZE_10"    : "10",
+        "FIELD_OPTION_FONT_SIZE_11"    : "11",
+        "FIELD_OPTION_FONT_SIZE_12"    : "12",
+        "FIELD_OPTION_FONT_SIZE_14"    : "14",
+        "FIELD_OPTION_FONT_SIZE_18"    : "18",
+        "FIELD_OPTION_FONT_SIZE_24"    : "24",
+        "FIELD_OPTION_FONT_SIZE_30"    : "30",
+        "FIELD_OPTION_FONT_SIZE_36"    : "36",
+        "FIELD_OPTION_FONT_SIZE_48"    : "48",
+        "FIELD_OPTION_FONT_SIZE_60"    : "60",
+        "FIELD_OPTION_FONT_SIZE_72"    : "72",
+        "FIELD_OPTION_FONT_SIZE_96"    : "96",
+        "FIELD_OPTION_FONT_SIZE_EMPTY" : "",
+
+        "NAME" : "Telnet",
+
+        "SECTION_HEADER_AUTHENTICATION" : "认证",
+        "SECTION_HEADER_BEHAVIOR"       : "终端行为",
+        "SECTION_HEADER_DISPLAY"        : "显示",
+        "SECTION_HEADER_RECORDING"      : "屏幕录像",
+        "SECTION_HEADER_TYPESCRIPT"     : "打字稿(文本会话录像)",
+        "SECTION_HEADER_NETWORK"        : "网络"
+
+    },
+
+    "PROTOCOL_VNC" : {
+
+        "FIELD_HEADER_AUDIO_SERVERNAME" : "音频服务器名:",
+        "FIELD_HEADER_CLIPBOARD_ENCODING" : "编码:",
+        "FIELD_HEADER_COLOR_DEPTH"      : "色彩深度:",
+        "FIELD_HEADER_CREATE_RECORDING_PATH" : "自动建立录像目录:",
+        "FIELD_HEADER_CURSOR"           : "光标:",
+        "FIELD_HEADER_DEST_HOST"        : "目标主机:",
+        "FIELD_HEADER_DEST_PORT"        : "目标端口:",
+        "FIELD_HEADER_ENABLE_AUDIO"     : "启用音频:",
+        "FIELD_HEADER_ENABLE_SFTP"      : "启用SFTP:",
+        "FIELD_HEADER_HOSTNAME"         : "主机名:",
+        "FIELD_HEADER_PASSWORD"         : "密码:",
+        "FIELD_HEADER_PORT"             : "端口:",
+        "FIELD_HEADER_READ_ONLY"        : "只读:",
+        "FIELD_HEADER_RECORDING_EXCLUDE_MOUSE"  : "排除鼠标:",
+        "FIELD_HEADER_RECORDING_EXCLUDE_OUTPUT" : "排除图像/数据流:",
+        "FIELD_HEADER_RECORDING_INCLUDE_KEYS"   : "包含按键事件:",
+        "FIELD_HEADER_RECORDING_NAME" : "录像名:",
+        "FIELD_HEADER_RECORDING_PATH" : "录像路径:",
+        "FIELD_HEADER_SFTP_DIRECTORY"             : "缺省文件上传目录:",
+        "FIELD_HEADER_SFTP_HOSTNAME"              : "主机名:",
+        "FIELD_HEADER_SFTP_SERVER_ALIVE_INTERVAL" : "SFTP keepalive时间间隔:",
+        "FIELD_HEADER_SFTP_PASSPHRASE"            : "口令:",
+        "FIELD_HEADER_SFTP_PASSWORD"              : "密码:",
+        "FIELD_HEADER_SFTP_PORT"                  : "端口:",
+        "FIELD_HEADER_SFTP_PRIVATE_KEY"           : "私钥:",
+        "FIELD_HEADER_SFTP_ROOT_DIRECTORY"        : "文件浏览器根目录:",
+        "FIELD_HEADER_SFTP_USERNAME"              : "用户名:",
+        "FIELD_HEADER_SWAP_RED_BLUE"    : "交换红/蓝成分:",
+
+        "FIELD_OPTION_COLOR_DEPTH_8"     : "256色",
+        "FIELD_OPTION_COLOR_DEPTH_16"    : "低色(16位)",
+        "FIELD_OPTION_COLOR_DEPTH_24"    : "真彩(24位)",
+        "FIELD_OPTION_COLOR_DEPTH_32"    : "真彩(32位)",
+        "FIELD_OPTION_COLOR_DEPTH_EMPTY" : "",
+
+        "FIELD_OPTION_CURSOR_EMPTY"  : "",
+        "FIELD_OPTION_CURSOR_LOCAL"  : "本地",
+        "FIELD_OPTION_CURSOR_REMOTE" : "远程",
+
+        "FIELD_OPTION_CLIPBOARD_ENCODING_CP1252"    : "CP1252",
+        "FIELD_OPTION_CLIPBOARD_ENCODING_EMPTY"     : "",
+        "FIELD_OPTION_CLIPBOARD_ENCODING_ISO8859_1" : "ISO 8859-1",
+        "FIELD_OPTION_CLIPBOARD_ENCODING_UTF_8"     : "UTF-8",
+        "FIELD_OPTION_CLIPBOARD_ENCODING_UTF_16"    : "UTF-16",
+
+        "NAME" : "VNC",
+
+        "SECTION_HEADER_AUDIO"          : "音频",
+        "SECTION_HEADER_AUTHENTICATION" : "认证",
+        "SECTION_HEADER_CLIPBOARD"      : "剪贴板",
+        "SECTION_HEADER_DISPLAY"        : "显示",
+        "SECTION_HEADER_NETWORK"        : "网络",
+        "SECTION_HEADER_RECORDING"      : "屏幕录像",
+        "SECTION_HEADER_REPEATER"       : "VNC中继",
+        "SECTION_HEADER_SFTP"           : "SFTP"
+
+    },
+
+    "SETTINGS" : {
+
+        "SECTION_HEADER_SETTINGS" : "设置"
+
+    },
+
+    "SETTINGS_CONNECTION_HISTORY" : {
+
+        "ACTION_DOWNLOAD" : "@:APP.ACTION_DOWNLOAD",
+        "ACTION_SEARCH"   : "@:APP.ACTION_SEARCH",
+
+        "FIELD_PLACEHOLDER_FILTER" : "@:APP.FIELD_PLACEHOLDER_FILTER",
+
+        "FILENAME_HISTORY_CSV" : "历史.csv",
+
+        "FORMAT_DATE" : "@:APP.FORMAT_DATE_TIME_PRECISE",
+
+        "HELP_CONNECTION_HISTORY" : "下表中是过往的连接历史,可以点击列头来进行排序。如需搜索特定的记录,输入一个过滤字符串并点击”搜索“。列表中将只显示符合过滤条件的记录。",
+
+        "INFO_CONNECTION_DURATION_UNKNOWN" : "--",
+        "INFO_NO_HISTORY"                  : "无符合条件的记录",
+
+        "TABLE_HEADER_SESSION_CONNECTION_NAME" : "连接名",
+        "TABLE_HEADER_SESSION_DURATION"        : "持续时间",
+        "TABLE_HEADER_SESSION_REMOTEHOST"      : "远程主机",
+        "TABLE_HEADER_SESSION_STARTDATE"       : "起始时间",
+        "TABLE_HEADER_SESSION_USERNAME"        : "用户名",
+
+        "TEXT_HISTORY_DURATION" : "@:APP.TEXT_HISTORY_DURATION"
+
+    },
+
+    "SETTINGS_CONNECTIONS" : {
+
+        "ACTION_ACKNOWLEDGE"          : "@:APP.ACTION_ACKNOWLEDGE",
+        "ACTION_NEW_CONNECTION"       : "新建连接",
+        "ACTION_NEW_CONNECTION_GROUP" : "新建连接组",
+        "ACTION_NEW_SHARING_PROFILE"  : "新建共享设定",
+
+        "DIALOG_HEADER_ERROR" : "@:APP.DIALOG_HEADER_ERROR",
+
+        "FIELD_PLACEHOLDER_FILTER" : "@:APP.FIELD_PLACEHOLDER_FILTER",
+
+        "HELP_CONNECTIONS"   : "点击下列连接,以管理该连接。基于您的权限,可以新建和删除连接,或修改连接的属性(如协议、主机名、端口等)。",
+        
+        "INFO_ACTIVE_USER_COUNT" : "@:APP.INFO_ACTIVE_USER_COUNT",
+
+        "SECTION_HEADER_CONNECTIONS"     : "连接"
+
+    },
+
+    "SETTINGS_PREFERENCES" : {
+
+        "ACTION_ACKNOWLEDGE"        : "@:APP.ACTION_ACKNOWLEDGE",
+        "ACTION_CANCEL"             : "@:APP.ACTION_CANCEL",
+        "ACTION_UPDATE_PASSWORD"    : "@:APP.ACTION_UPDATE_PASSWORD",
+
+        "DIALOG_HEADER_ERROR"    : "@:APP.DIALOG_HEADER_ERROR",
+
+        "ERROR_PASSWORD_BLANK"    : "@:APP.ERROR_PASSWORD_BLANK",
+        "ERROR_PASSWORD_MISMATCH" : "@:APP.ERROR_PASSWORD_MISMATCH",
+
+        "FIELD_HEADER_LANGUAGE"           : "界面语言:",
+        "FIELD_HEADER_PASSWORD"           : "密码:",
+        "FIELD_HEADER_PASSWORD_OLD"       : "当前密码:",
+        "FIELD_HEADER_PASSWORD_NEW"       : "新密码:",
+        "FIELD_HEADER_PASSWORD_NEW_AGAIN" : "确认新密码:",
+        "FIELD_HEADER_USERNAME"           : "用户名:",
+        
+        "HELP_DEFAULT_INPUT_METHOD" : "缺省输入法决定了Guacamole如何接收键盘事件。当使用移动设备或使用IME输入时,有可能需要更改设置。本设置可在Guacamole菜单内被单个连接的设定覆盖。",
+        "HELP_DEFAULT_MOUSE_MODE"   : "缺省鼠标模拟方式决定了新连接内的远程鼠标如何响应屏幕触控。本设置可在Guacamole菜单内被单个连接的设定覆盖。",
+        "HELP_INPUT_METHOD_NONE"    : "@:CLIENT.HELP_INPUT_METHOD_NONE",
+        "HELP_INPUT_METHOD_OSK"     : "@:CLIENT.HELP_INPUT_METHOD_OSK",
+        "HELP_INPUT_METHOD_TEXT"    : "@:CLIENT.HELP_INPUT_METHOD_TEXT",
+        "HELP_LANGUAGE"             : "在下方列表中选择Guacamole界面所使用的语言。可选用的语言决定于系统安装了什么语言。",
+        "HELP_MOUSE_MODE_ABSOLUTE"  : "@:CLIENT.HELP_MOUSE_MODE_ABSOLUTE",
+        "HELP_MOUSE_MODE_RELATIVE"  : "@:CLIENT.HELP_MOUSE_MODE_RELATIVE",
+        "HELP_UPDATE_PASSWORD"      : "如需改变密码,请在下面输入您的当前密码与希望使用的新密码,并点击“更新密码” 。密码的改动会立即生效。",
+
+        "INFO_PASSWORD_CHANGED" : "密码已更改。",
+
+        "NAME_INPUT_METHOD_NONE" : "@:CLIENT.NAME_INPUT_METHOD_NONE",
+        "NAME_INPUT_METHOD_OSK"  : "@:CLIENT.NAME_INPUT_METHOD_OSK",
+        "NAME_INPUT_METHOD_TEXT" : "@:CLIENT.NAME_INPUT_METHOD_TEXT",
+
+        "SECTION_HEADER_DEFAULT_INPUT_METHOD" : "缺省输入法",
+        "SECTION_HEADER_DEFAULT_MOUSE_MODE"   : "缺省鼠标模拟方式",
+        "SECTION_HEADER_UPDATE_PASSWORD"      : "更改密码"
+
+    },
+
+    "SETTINGS_USERS" : {
+
+        "ACTION_ACKNOWLEDGE"   : "@:APP.ACTION_ACKNOWLEDGE",
+        "ACTION_NEW_USER"      : "新用户",
+
+        "DIALOG_HEADER_ERROR" : "@:APP.DIALOG_HEADER_ERROR",
+
+        "FIELD_PLACEHOLDER_FILTER" : "@:APP.FIELD_PLACEHOLDER_FILTER",
+
+        "FORMAT_DATE" : "@:APP.FORMAT_DATE_TIME_PRECISE",
+
+        "HELP_USERS" : "点击下面的用户以管理该用户。基于您的权限,可以新增和删除用户,也可以更改他们的密码。",
+
+        "SECTION_HEADER_USERS"       : "用户",
+
+        "TABLE_HEADER_LAST_ACTIVE" : "最近活动",
+        "TABLE_HEADER_USERNAME"    : "用户名"
+
+    },
+    
+    "SETTINGS_SESSIONS" : {
+        
+        "ACTION_ACKNOWLEDGE" : "@:APP.ACTION_ACKNOWLEDGE",
+        "ACTION_CANCEL"      : "@:APP.ACTION_CANCEL",
+        "ACTION_DELETE"      : "终止会话",
+        
+        "DIALOG_HEADER_CONFIRM_DELETE" : "终止会话",
+        "DIALOG_HEADER_ERROR"          : "@:APP.DIALOG_HEADER_ERROR",
+        
+        "FIELD_PLACEHOLDER_FILTER" : "@:APP.FIELD_PLACEHOLDER_FILTER",
+        
+        "FORMAT_STARTDATE" : "@:APP.FORMAT_DATE_TIME_PRECISE",
+
+        "HELP_SESSIONS" : "该页面将填充当前活动的连接。 列出的连接和终止连接的能力取决于您的访问级别。如需终止一个或多个会话,勾选目标会话并点击“终止会话”。终止会话会立即断开对应用户的连接。",
+        
+        "INFO_NO_SESSIONS" : "无活动会话",
+
+        "SECTION_HEADER_SESSIONS" : "活动会话",
+        
+        "TABLE_HEADER_SESSION_CONNECTION_NAME" : "连接名",
+        "TABLE_HEADER_SESSION_REMOTEHOST"      : "远程主机",
+        "TABLE_HEADER_SESSION_STARTDATE"       : "开始时间",
+        "TABLE_HEADER_SESSION_USERNAME"        : "用户名",
+        
+        "TEXT_CONFIRM_DELETE" : "确定要终止所选定的会话?对应的用户会被立即断开连接。"
+
+    },
+
+    "USER_ATTRIBUTES" : {
+
+        "FIELD_HEADER_GUAC_EMAIL_ADDRESS"       : "电邮地址:",
+        "FIELD_HEADER_GUAC_FULL_NAME"           : "全名:",
+        "FIELD_HEADER_GUAC_ORGANIZATION"        : "组织:",
+        "FIELD_HEADER_GUAC_ORGANIZATIONAL_ROLE" : "职位:"
+
+    },
+
+    "USER_MENU" : {
+
+        "ACTION_LOGOUT"             : "@:APP.ACTION_LOGOUT",
+        "ACTION_MANAGE_CONNECTIONS" : "@:APP.ACTION_MANAGE_CONNECTIONS",
+        "ACTION_MANAGE_PREFERENCES" : "@:APP.ACTION_MANAGE_PREFERENCES",
+        "ACTION_MANAGE_SESSIONS"    : "@:APP.ACTION_MANAGE_SESSIONS",
+        "ACTION_MANAGE_SETTINGS"    : "@:APP.ACTION_MANAGE_SETTINGS",
+        "ACTION_MANAGE_USERS"       : "@:APP.ACTION_MANAGE_USERS",
+        "ACTION_NAVIGATE_HOME"      : "@:APP.ACTION_NAVIGATE_HOME",
+        "ACTION_VIEW_HISTORY"       : "@:APP.ACTION_VIEW_HISTORY"
+
+    }
+
+}