mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 00:53:21 +00:00 
			
		
		
		
	GUACAMOLE-1571: Check available translations rather than hardcoding which use the default.
This commit is contained in:
		| @@ -34,16 +34,16 @@ angular.module('client').directive('guacClientNotification', [function guacClien | ||||
|  | ||||
|         /** | ||||
|          * The client whose status should be displayed. | ||||
|          *  | ||||
|          * | ||||
|          * @type ManagedClient | ||||
|          */ | ||||
|         client : '=' | ||||
|          | ||||
|  | ||||
|     }; | ||||
|  | ||||
|     directive.controller = ['$scope', '$injector', '$element', | ||||
|         function guacClientNotificationController($scope, $injector, $element) { | ||||
|     | ||||
|  | ||||
|         // Required types | ||||
|         const ManagedClient      = $injector.get('ManagedClient'); | ||||
|         const ManagedClientState = $injector.get('ManagedClientState'); | ||||
| @@ -53,6 +53,7 @@ angular.module('client').directive('guacClientNotification', [function guacClien | ||||
|         const $location              = $injector.get('$location'); | ||||
|         const authenticationService  = $injector.get('authenticationService'); | ||||
|         const guacClientManager      = $injector.get('guacClientManager'); | ||||
|         const guacTranslate          = $injector.get('guacTranslate'); | ||||
|         const requestService         = $injector.get('requestService'); | ||||
|         const userPageService        = $injector.get('userPageService'); | ||||
|  | ||||
| @@ -65,26 +66,6 @@ angular.module('client').directive('guacClientNotification', [function guacClien | ||||
|          */ | ||||
|         $scope.status = false; | ||||
|  | ||||
|         /** | ||||
|          * All client error codes handled and passed off for translation. Any error | ||||
|          * code not present in this list will be represented by the "DEFAULT" | ||||
|          * translation. | ||||
|          */ | ||||
|         const CLIENT_ERRORS = { | ||||
|             0x0201: true, | ||||
|             0x0202: true, | ||||
|             0x0203: true, | ||||
|             0x0207: true, | ||||
|             0x0208: true, | ||||
|             0x0209: true, | ||||
|             0x020A: true, | ||||
|             0x020B: true, | ||||
|             0x0301: true, | ||||
|             0x0303: true, | ||||
|             0x0308: true, | ||||
|             0x031D: true | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * All error codes for which automatic reconnection is appropriate when a | ||||
|          * client error occurs. | ||||
| @@ -98,26 +79,7 @@ angular.module('client').directive('guacClientNotification', [function guacClien | ||||
|             0x0301: true, | ||||
|             0x0308: true | ||||
|         }; | ||||
|       | ||||
|         /** | ||||
|          * All tunnel error codes handled and passed off for translation. Any error | ||||
|          * code not present in this list will be represented by the "DEFAULT" | ||||
|          * translation. | ||||
|          */ | ||||
|         const TUNNEL_ERRORS = { | ||||
|             0x0201: true, | ||||
|             0x0202: true, | ||||
|             0x0203: true, | ||||
|             0x0204: true, | ||||
|             0x0205: true, | ||||
|             0x0207: true, | ||||
|             0x0208: true, | ||||
|             0x0301: true, | ||||
|             0x0303: true, | ||||
|             0x0308: true, | ||||
|             0x031D: true | ||||
|         }; | ||||
|       | ||||
|  | ||||
|         /** | ||||
|          * All error codes for which automatic reconnection is appropriate when a | ||||
|          * tunnel error occurs. | ||||
| @@ -239,7 +201,7 @@ angular.module('client').directive('guacClientNotification', [function guacClien | ||||
|             // Get any associated status code | ||||
|             const status = $scope.client.clientState.statusCode; | ||||
|  | ||||
|             // Connecting  | ||||
|             // Connecting | ||||
|             if (connectionState === ManagedClientState.ConnectionState.CONNECTING | ||||
|              || connectionState === ManagedClientState.ConnectionState.WAITING) { | ||||
|                 $scope.status = { | ||||
| @@ -254,44 +216,58 @@ angular.module('client').directive('guacClientNotification', [function guacClien | ||||
|             // Client error | ||||
|             else if (connectionState === ManagedClientState.ConnectionState.CLIENT_ERROR) { | ||||
|  | ||||
|                 // Determine translation name of error | ||||
|                 const errorName = (status in CLIENT_ERRORS) ? status.toString(16).toUpperCase() : "DEFAULT"; | ||||
|                 // Translation IDs for this error code | ||||
|                 const errorPrefix = "CLIENT.ERROR_CLIENT_"; | ||||
|                 const errorId = errorPrefix + status.toString(16).toUpperCase(); | ||||
|                 const defaultErrorId = errorPrefix + "DEFAULT"; | ||||
|  | ||||
|                 // Determine whether the reconnect countdown applies | ||||
|                 const countdown = (status in CLIENT_AUTO_RECONNECT) ? RECONNECT_COUNTDOWN : null; | ||||
|  | ||||
|                 // Show error status | ||||
|                 notifyConnectionClosed({ | ||||
|                     className : "error", | ||||
|                     title     : "CLIENT.DIALOG_HEADER_CONNECTION_ERROR", | ||||
|                     text      : { | ||||
|                         key : "CLIENT.ERROR_CLIENT_" + errorName | ||||
|                     }, | ||||
|                     countdown : countdown, | ||||
|                     actions   : actions | ||||
|                 }); | ||||
|                 // Use the guacTranslate service to determine if there is a translation for | ||||
|                 // this error code; if not, use the default | ||||
|                 guacTranslate(errorId, defaultErrorId).then( | ||||
|  | ||||
|                     // Show error status | ||||
|                     translationResult => notifyConnectionClosed({ | ||||
|                         className : "error", | ||||
|                         title     : "CLIENT.DIALOG_HEADER_CONNECTION_ERROR", | ||||
|                         text      : { | ||||
|                             key : translationResult.id | ||||
|                         }, | ||||
|                         countdown : countdown, | ||||
|                         actions   : actions | ||||
|                     }) | ||||
|                 ); | ||||
|  | ||||
|             } | ||||
|  | ||||
|             // Tunnel error | ||||
|             else if (connectionState === ManagedClientState.ConnectionState.TUNNEL_ERROR) { | ||||
|  | ||||
|                 // Determine translation name of error | ||||
|                 const errorName = (status in TUNNEL_ERRORS) ? status.toString(16).toUpperCase() : "DEFAULT"; | ||||
|                 // Translation IDs for this error code | ||||
|                 const errorPrefix = "CLIENT.ERROR_TUNNEL_"; | ||||
|                 const errorId = errorPrefix + status.toString(16).toUpperCase(); | ||||
|                 const defaultErrorId = errorPrefix + "DEFAULT"; | ||||
|  | ||||
|                 // Determine whether the reconnect countdown applies | ||||
|                 const countdown = (status in TUNNEL_AUTO_RECONNECT) ? RECONNECT_COUNTDOWN : null; | ||||
|  | ||||
|                 // Show error status | ||||
|                 notifyConnectionClosed({ | ||||
|                     className : "error", | ||||
|                     title     : "CLIENT.DIALOG_HEADER_CONNECTION_ERROR", | ||||
|                     text      : { | ||||
|                         key : "CLIENT.ERROR_TUNNEL_" + errorName | ||||
|                     }, | ||||
|                     countdown : countdown, | ||||
|                     actions   : actions | ||||
|                 }); | ||||
|                 // Use the guacTranslate service to determine if there is a translation for | ||||
|                 // this error code; if not, use the default | ||||
|                 guacTranslate(errorId, defaultErrorId).then( | ||||
|  | ||||
|                     // Show error status | ||||
|                     translationResult => notifyConnectionClosed({ | ||||
|                         className : "error", | ||||
|                         title     : "CLIENT.DIALOG_HEADER_CONNECTION_ERROR", | ||||
|                         text      : { | ||||
|                             key : translationResult.id | ||||
|                         }, | ||||
|                         countdown : countdown, | ||||
|                         actions   : actions | ||||
|                     }) | ||||
|                 ); | ||||
|  | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -30,7 +30,7 @@ angular.module('client').directive('guacFileTransfer', [function guacFileTransfe | ||||
|  | ||||
|             /** | ||||
|              * The file transfer to display. | ||||
|              *  | ||||
|              * | ||||
|              * @type ManagedFileUpload|ManagedFileDownload | ||||
|              */ | ||||
|             transfer : '=' | ||||
| @@ -40,27 +40,12 @@ angular.module('client').directive('guacFileTransfer', [function guacFileTransfe | ||||
|         templateUrl: 'app/client/templates/guacFileTransfer.html', | ||||
|         controller: ['$scope', '$injector', function guacFileTransferController($scope, $injector) { | ||||
|  | ||||
|             // Required services | ||||
|             const guacTranslate = $injector.get('guacTranslate'); | ||||
|  | ||||
|             // Required types | ||||
|             var ManagedFileTransferState = $injector.get('ManagedFileTransferState'); | ||||
|  | ||||
|             /** | ||||
|              * All upload error codes handled and passed off for translation. | ||||
|              * Any error code not present in this list will be represented by | ||||
|              * the "DEFAULT" translation. | ||||
|              */ | ||||
|             var UPLOAD_ERRORS = { | ||||
|                 0x0100: true, | ||||
|                 0x0201: true, | ||||
|                 0x0202: true, | ||||
|                 0x0203: true, | ||||
|                 0x0204: true, | ||||
|                 0x0205: true, | ||||
|                 0x0301: true, | ||||
|                 0x0303: true, | ||||
|                 0x0308: true, | ||||
|                 0x031D: true | ||||
|             }; | ||||
|  | ||||
|             /** | ||||
|              * Returns the unit string that is most appropriate for the | ||||
|              * number of bytes transferred thus far - either 'gb', 'mb', 'kb', | ||||
| @@ -193,7 +178,7 @@ angular.module('client').directive('guacFileTransfer', [function guacFileTransfe | ||||
|                     return; | ||||
|  | ||||
|                 // Save file | ||||
|                 saveAs($scope.transfer.blob, $scope.transfer.filename);  | ||||
|                 saveAs($scope.transfer.blob, $scope.transfer.filename); | ||||
|  | ||||
|             }; | ||||
|  | ||||
| @@ -210,23 +195,20 @@ angular.module('client').directive('guacFileTransfer', [function guacFileTransfe | ||||
|                 return $scope.transfer.transferState.streamState === ManagedFileTransferState.StreamState.ERROR; | ||||
|             }; | ||||
|  | ||||
|             /** | ||||
|              * Returns the text of the current error as a translation string. | ||||
|              * | ||||
|              * @returns {String} | ||||
|              *     The name of the translation string containing the text | ||||
|              *     associated with the current error. | ||||
|              */ | ||||
|             $scope.getErrorText = function getErrorText() { | ||||
|             // The translated error message for the current status code | ||||
|             $scope.translatedErrorMessage = ''; | ||||
|  | ||||
|             $scope.$watch('transfer.transferState.statusCode', function statusCodeChanged(statusCode) { | ||||
|  | ||||
|                 // Determine translation name of error | ||||
|                 var status = $scope.transfer.transferState.statusCode; | ||||
|                 var errorName = (status in UPLOAD_ERRORS) ? status.toString(16).toUpperCase() : "DEFAULT"; | ||||
|                 const errorName = 'CLIENT.ERROR_UPLOAD_' + statusCode.toString(16).toUpperCase(); | ||||
|  | ||||
|                 // Return translation string | ||||
|                 return 'CLIENT.ERROR_UPLOAD_' + errorName; | ||||
|                 // Use translation string, or the default if no translation is found for this error code | ||||
|                 guacTranslate(errorName, 'CLIENT.ERROR_UPLOAD_DEFAULT').then( | ||||
|                     translationResult => $scope.translatedErrorMessage = translationResult.message | ||||
|                 ); | ||||
|  | ||||
|             }; | ||||
|             }); | ||||
|  | ||||
|         }] // end file transfer controller | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,82 @@ | ||||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements.  See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership.  The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License.  You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied.  See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * A wrapper around the angular-translate $translate service that offers a | ||||
|  * convenient way to fall back to a default translation if the requested | ||||
|  * translation is not available. | ||||
|  */ | ||||
|  angular.module('client').factory('guacTranslate', ['$injector', function guacTranslate($injector) { | ||||
|  | ||||
|     // Required services | ||||
|     const $q = $injector.get('$q'); | ||||
|     const $translate = $injector.get('$translate'); | ||||
|  | ||||
|     // Required types | ||||
|     const TranslationResult = $injector.get('TranslationResult'); | ||||
|  | ||||
|     /** | ||||
|      * Returns a promise that will be resolved with a TranslationResult containg either the | ||||
|      * requested ID and message (if translated), or the default ID and message if translated, | ||||
|      * or the literal value of `defaultTranslationId` for both the ID and message if neither | ||||
|      * is translated. | ||||
|      * | ||||
|      * @param {String} translationId | ||||
|      *     The requested translation ID, which may or may not be translated. | ||||
|      * | ||||
|      * @param {Sting} defaultTranslationId | ||||
|      *     The translation ID that will be used if no translation is found for `translationId`. | ||||
|      * | ||||
|      * @returns {Promise.<TranslationResult>} | ||||
|      *     A promise which resolves with a TranslationResult containing the results from | ||||
|      *     the translation attempt. | ||||
|      */ | ||||
|     function translateWithFallback(translationId, defaultTranslationId) { | ||||
|         const deferredTranslation = $q.defer(); | ||||
|  | ||||
|         // Attempt to translate the requested translation ID | ||||
|         $translate(translationId).then( | ||||
|  | ||||
|             // If the requested translation is available, use that | ||||
|             translation => deferredTranslation.resolve(new TranslationResult({ | ||||
|                 id: translationId, message: translation | ||||
|             })), | ||||
|  | ||||
|             // Otherwise, try the default translation ID | ||||
|             () => $translate(defaultTranslationId).then( | ||||
|  | ||||
|                 // Default translation worked, so use that | ||||
|                 defaultTranslation => | ||||
|                     deferredTranslation.resolve(new TranslationResult({ | ||||
|                         id: defaultTranslationId, message: defaultTranslation | ||||
|                     })), | ||||
|  | ||||
|                 // Neither translation is available; as a fallback, return default ID for both | ||||
|                 () => deferredTranslation.resolve(new TranslationResult({ | ||||
|                     id: defaultTranslationId, message: defaultTranslationId | ||||
|                 })), | ||||
|             ) | ||||
|         ); | ||||
|  | ||||
|         return deferredTranslation.promise; | ||||
|     }; | ||||
|  | ||||
|     return translateWithFallback; | ||||
|  | ||||
| }]); | ||||
| @@ -10,7 +10,7 @@ | ||||
|         </div> | ||||
|  | ||||
|         <!-- Error text --> | ||||
|         <p class="error-text">{{getErrorText() | translate}}</p> | ||||
|         <p class="error-text">{{translatedErrorMessage}}</p> | ||||
|  | ||||
|     </div> | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,59 @@ | ||||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements.  See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership.  The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License.  You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied.  See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Provides the TranslationResult class used by the guacTranslate service. This class contains | ||||
|  * both the translated message and the translation ID that generated the message, in the case | ||||
|  * where it's unknown whether a translation is defined or not. | ||||
|  */ | ||||
|  angular.module('client').factory('TranslationResult', [function defineTranslationResult() { | ||||
|  | ||||
|     /** | ||||
|      * Object which represents the result of a translation as returned from | ||||
|      * the guacTranslate service. | ||||
|      * | ||||
|      * @constructor | ||||
|      * @param {TranslationResult|Object} [template={}] | ||||
|      *     The object whose properties should be copied within the new | ||||
|      *     TranslationResult. | ||||
|      */ | ||||
|     const TranslationResult = function TranslationResult(template) { | ||||
|  | ||||
|         // Use empty object by default | ||||
|         template = template || {}; | ||||
|  | ||||
|         /** | ||||
|          * The translation ID. | ||||
|          * | ||||
|          * @type {String} | ||||
|          */ | ||||
|         this.id = template.id; | ||||
|  | ||||
|         /** | ||||
|          * The translated message. | ||||
|          * | ||||
|          * @type {String} | ||||
|          */ | ||||
|         this.message = template.message; | ||||
|  | ||||
|     }; | ||||
|  | ||||
|     return TranslationResult; | ||||
|  | ||||
| }]); | ||||
		Reference in New Issue
	
	Block a user