mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 00:53:21 +00:00 
			
		
		
		
	GUAC-1053: Pull language from preferences when configuring the translate service. Fallback to US English if there is no such translation file.
This commit is contained in:
		| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright (C) 2014 Glyptodon LLC | ||||
|  * Copyright (C) 2015 Glyptodon LLC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
| @@ -23,21 +23,25 @@ | ||||
| /** | ||||
|  * The configuration block for setting up everything having to do with i18n. | ||||
|  */ | ||||
| angular.module('index').config(['$translateProvider', function($translateProvider) { | ||||
| angular.module('index').config(['$injector', function($injector) { | ||||
|  | ||||
|     // TODONT: Use US English by default (this should come from preferences) | ||||
|     $translateProvider.preferredLanguage('en_US'); | ||||
|     // Required providers | ||||
|     var $translateProvider        = $injector.get('$translateProvider'); | ||||
|     var preferenceServiceProvider = $injector.get('preferenceServiceProvider'); | ||||
|  | ||||
|     // Use US English for any undefined strings  | ||||
|     $translateProvider.fallbackLanguage('en_US'); | ||||
|     // Fallback to US English | ||||
|     var fallbackLanguages = ['en_US']; | ||||
|  | ||||
|     // Load translations from static JSON files | ||||
|     $translateProvider.useStaticFilesLoader({ | ||||
|         prefix: 'translations/', | ||||
|         suffix: '.json' | ||||
|     // Prefer chosen language, use fallback languages if necessary | ||||
|     $translateProvider.fallbackLanguage(fallbackLanguages); | ||||
|     $translateProvider.preferredLanguage(preferenceServiceProvider.preferences.language); | ||||
|  | ||||
|     // Load translations via translationLoader service | ||||
|     $translateProvider.useLoader('translationLoader', { | ||||
|         fallbackLanguages : fallbackLanguages | ||||
|     }); | ||||
|  | ||||
|     // Provide pluralization, etc. via messageformat.js | ||||
|     $translateProvider.useMessageFormatInterpolation(); | ||||
|  | ||||
| }]); | ||||
| }]); | ||||
|   | ||||
| @@ -0,0 +1,114 @@ | ||||
| /* | ||||
|  * Copyright (C) 2015 Glyptodon LLC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Service for loading translation definition files, conforming to the | ||||
|  * angular-translate documentation for custom translation loaders: | ||||
|  *  | ||||
|  * https://github.com/angular-translate/angular-translate/wiki/Asynchronous-loading#using-custom-loader-service | ||||
|  */ | ||||
| angular.module('locale').factory('translationLoader', ['$injector', function translationLoader($injector) { | ||||
|  | ||||
|     // Required services | ||||
|     var $http        = $injector.get('$http'); | ||||
|     var $q           = $injector.get('$q'); | ||||
|     var cacheService = $injector.get('cacheService'); | ||||
|  | ||||
|     /** | ||||
|      * Satisfies a translation request for the given key by searching for the | ||||
|      * translation files for each key in the given array, in order. The request | ||||
|      * fails only if none of the files can be found. | ||||
|      * | ||||
|      * @param {Deferred} deferred | ||||
|      *     The Deferred object to resolve or reject depending on whether at | ||||
|      *     least one translation file can be successfully loaded. | ||||
|      * | ||||
|      * @param {String} requestedKey | ||||
|      *     The originally-requested language key. | ||||
|      * | ||||
|      * @param {String[]} remainingKeys | ||||
|      *     The keys of the languages to attempt to load, in order, where the | ||||
|      *     first key in this array is the language to try within this function | ||||
|      *     call. The first key in the array is not necessarily the originally- | ||||
|      *     requested language key. | ||||
|      */ | ||||
|     var satisfyTranslation = function satisfyTranslation(deferred, requestedKey, remainingKeys) { | ||||
|  | ||||
|         // Get current language key | ||||
|         var currentKey = remainingKeys.shift(); | ||||
|  | ||||
|         // If no languages to try, just fail | ||||
|         if (!currentKey) { | ||||
|             deferred.reject(requestedKey); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // Attempt to retrieve language | ||||
|         $http({ | ||||
|             cache   : cacheService.languages, | ||||
|             method  : 'GET', | ||||
|             url     : 'translations/' + encodeURIComponent(currentKey) + '.json' | ||||
|         }) | ||||
|  | ||||
|         // Resolve promise if translation retrieved successfully | ||||
|         .success(function translationFileRetrieved(translation) { | ||||
|             deferred.resolve(translation); | ||||
|         }) | ||||
|  | ||||
|         // Retry with remaining languages if translation file could not be retrieved | ||||
|         .error(function translationFileUnretrievable() { | ||||
|             satisfyTranslation(deferred, requestedKey, remainingKeys); | ||||
|         }); | ||||
|  | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Custom loader function for angular-translate which loads the desired | ||||
|      * language file dynamically via HTTP. If the language file cannot be | ||||
|      * found, the fallback language is used instead. | ||||
|      * | ||||
|      * @param {Object} options | ||||
|      *     Arbitrary options, containing at least a "key" property which | ||||
|      *     contains the requested language key. | ||||
|      * | ||||
|      * @returns {Promise.<Object>} | ||||
|      *     A promise which resolves to the requested translation string object. | ||||
|      */ | ||||
|     return function loadTranslationFile(options) { | ||||
|  | ||||
|         var translation = $q.defer(); | ||||
|  | ||||
|         // Get requested language from options | ||||
|         var requestedKey = options.key; | ||||
|  | ||||
|         // Append fallback languages to requested language | ||||
|         var keys = [requestedKey].concat(options.fallbackLanguages); | ||||
|  | ||||
|         // Satisfy the translation request | ||||
|         satisfyTranslation(translation, requestedKey, keys); | ||||
|  | ||||
|         // Return promise which is resolved only after the translation file is loaded | ||||
|         return translation.promise; | ||||
|  | ||||
|     }; | ||||
|  | ||||
| }]); | ||||
| @@ -24,16 +24,20 @@ | ||||
|  * A service for setting and retrieving browser-local preferences. Preferences | ||||
|  * may be any JSON-serializable type. | ||||
|  */ | ||||
| angular.module('settings').factory('preferenceService', ['$injector', | ||||
|         function preferenceService($injector) { | ||||
| angular.module('settings').provider('preferenceService', function preferenceServiceProvider() { | ||||
|  | ||||
|     // Required services | ||||
|     var $rootScope = $injector.get('$rootScope'); | ||||
|     var $window    = $injector.get('$window'); | ||||
|     /** | ||||
|      * Reference to the provider itself. | ||||
|      * | ||||
|      * @type preferenceServiceProvider | ||||
|      */ | ||||
|     var provider = this; | ||||
|  | ||||
|     var service = {}; | ||||
|  | ||||
|     // The parameter name for getting the history from local storage | ||||
|     /** | ||||
|      * The storage key of Guacamole preferences within local storage. | ||||
|      * | ||||
|      * @type String | ||||
|      */ | ||||
|     var GUAC_PREFERENCES_STORAGE_KEY = "GUAC_PREFERENCES"; | ||||
|  | ||||
|     /** | ||||
| @@ -41,7 +45,7 @@ angular.module('settings').factory('preferenceService', ['$injector', | ||||
|      * | ||||
|      * @type Object.<String, String> | ||||
|      */ | ||||
|     service.inputMethods = { | ||||
|     var inputMethods = { | ||||
|  | ||||
|         /** | ||||
|          * No input method is used. Keyboard events are generated from a | ||||
| @@ -97,7 +101,7 @@ angular.module('settings').factory('preferenceService', ['$injector', | ||||
|      * | ||||
|      * @type Object.<String, Object> | ||||
|      */ | ||||
|     service.preferences = { | ||||
|     this.preferences = { | ||||
|  | ||||
|         /** | ||||
|          * Whether translation of touch to mouse events should emulate an | ||||
| @@ -113,7 +117,7 @@ angular.module('settings').factory('preferenceService', ['$injector', | ||||
|          * | ||||
|          * @type String | ||||
|          */ | ||||
|         inputMethod : service.inputMethods.NONE, | ||||
|         inputMethod : inputMethods.NONE, | ||||
|          | ||||
|         /** | ||||
|          * The key of the desired display language. | ||||
| @@ -124,45 +128,71 @@ angular.module('settings').factory('preferenceService', ['$injector', | ||||
|  | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Persists the current values of all preferences, if possible. | ||||
|      */ | ||||
|     service.save = function save() { | ||||
|  | ||||
|         // Save updated preferences, ignore inability to use localStorage | ||||
|         try { | ||||
|             if (localStorage) | ||||
|                 localStorage.setItem(GUAC_PREFERENCES_STORAGE_KEY, JSON.stringify(service.preferences)); | ||||
|         } | ||||
|         catch (ignore) {} | ||||
|  | ||||
|     }; | ||||
|  | ||||
|     // Get stored preferences, ignore inability to use localStorage | ||||
|     try { | ||||
|  | ||||
|         if (localStorage) { | ||||
|             var preferencesJSON = localStorage.getItem(GUAC_PREFERENCES_STORAGE_KEY); | ||||
|             if (preferencesJSON) | ||||
|                 angular.extend(service.preferences, JSON.parse(preferencesJSON)); | ||||
|                 angular.extend(provider.preferences, JSON.parse(preferencesJSON)); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|     catch (ignore) {} | ||||
|  | ||||
|     // Persist settings when window is unloaded | ||||
|     $window.addEventListener('unload', service.save); | ||||
|     // Factory method required by provider | ||||
|     this.$get = ['$injector', function preferenceServiceFactory($injector) { | ||||
|  | ||||
|     // Persist settings upon navigation  | ||||
|     $rootScope.$on('$routeChangeSuccess', function handleNavigate() { | ||||
|         service.save(); | ||||
|     }); | ||||
|         // Required services | ||||
|         var $rootScope = $injector.get('$rootScope'); | ||||
|         var $window    = $injector.get('$window'); | ||||
|  | ||||
|     // Persist settings upon logout | ||||
|     $rootScope.$on('guacLogout', function handleLogout() { | ||||
|         service.save(); | ||||
|     }); | ||||
|         var service = {}; | ||||
|  | ||||
|     return service; | ||||
|         /** | ||||
|          * All valid input method type names. | ||||
|          * | ||||
|          * @type Object.<String, String> | ||||
|          */ | ||||
|         service.inputMethods = inputMethods; | ||||
|  | ||||
| }]); | ||||
|         /** | ||||
|          * All currently-set preferences, as name/value pairs. Each property name | ||||
|          * corresponds to the name of a preference. | ||||
|          * | ||||
|          * @type Object.<String, Object> | ||||
|          */ | ||||
|         service.preferences = provider.preferences; | ||||
|  | ||||
|         /** | ||||
|          * Persists the current values of all preferences, if possible. | ||||
|          */ | ||||
|         service.save = function save() { | ||||
|  | ||||
|             // Save updated preferences, ignore inability to use localStorage | ||||
|             try { | ||||
|                 if (localStorage) | ||||
|                     localStorage.setItem(GUAC_PREFERENCES_STORAGE_KEY, JSON.stringify(service.preferences)); | ||||
|             } | ||||
|             catch (ignore) {} | ||||
|  | ||||
|         }; | ||||
|  | ||||
|         // Persist settings when window is unloaded | ||||
|         $window.addEventListener('unload', service.save); | ||||
|  | ||||
|         // Persist settings upon navigation  | ||||
|         $rootScope.$on('$routeChangeSuccess', function handleNavigate() { | ||||
|             service.save(); | ||||
|         }); | ||||
|  | ||||
|         // Persist settings upon logout | ||||
|         $rootScope.$on('guacLogout', function handleLogout() { | ||||
|             service.save(); | ||||
|         }); | ||||
|  | ||||
|         return service; | ||||
|  | ||||
|     }]; | ||||
|  | ||||
| }); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user