mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +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