From e1f769fcbcdbba6519ca3f843b9a7976ab4fe883 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 15 Apr 2015 15:56:20 -0700 Subject: [PATCH] GUAC-1160: Generate localized field headers and option values within "form" module. --- .../main/webapp/app/form/directives/form.js | 40 +++++++++++++- .../webapp/app/form/directives/formField.js | 53 +++++++++++++++++-- .../src/main/webapp/app/form/formModule.js | 2 +- .../main/webapp/app/form/templates/form.html | 4 +- .../webapp/app/form/templates/formField.html | 2 +- .../controllers/manageConnectionController.js | 36 ++++++++++++- .../manage/templates/manageConnection.html | 4 +- .../src/main/webapp/translations/en_US.json | 9 +++- 8 files changed, 136 insertions(+), 14 deletions(-) diff --git a/guacamole/src/main/webapp/app/form/directives/form.js b/guacamole/src/main/webapp/app/form/directives/form.js index 099f4a1d6..fbe5af881 100644 --- a/guacamole/src/main/webapp/app/form/directives/form.js +++ b/guacamole/src/main/webapp/app/form/directives/form.js @@ -32,6 +32,17 @@ angular.module('form').directive('guacForm', [function form() { replace: true, scope: { + /** + * The translation namespace of the translation strings that will + * be generated for all fields. This namespace is absolutely + * required. If this namespace is omitted, all generated + * translation strings will be placed within the MISSING_NAMESPACE + * namespace, as a warning. + * + * @type String + */ + namespace : '=', + /** * The fields to display. * @@ -50,7 +61,10 @@ angular.module('form').directive('guacForm', [function form() { }, templateUrl: 'app/form/templates/form.html', - controller: ['$scope', function formController($scope) { + controller: ['$scope', '$injector', function formController($scope, $injector) { + + // Required services + var translationStringService = $injector.get('translationStringService'); /** * The object which will receive all field values. Normally, this @@ -63,6 +77,30 @@ angular.module('form').directive('guacForm', [function form() { */ $scope.values = {}; + /** + * Produces the translation string for the header of the given + * field. The translation string will be of the form: + * + * NAMESPACE.FIELD_HEADER_NAME + * + * where NAMESPACE is the namespace provided to the + * directive and NAME is the field name transformed + * via translationStringService.canonicalize(). + * + * @param {Field} field + * The field for which to produce the translation string. + * + * @returns {String} + * The translation string which produces the translated header + * of the field. + */ + $scope.getFieldHeader = function getFieldHeader(field) { + + return translationStringService.canonicalize($scope.namespace || 'MISSING_NAMESPACE') + + '.FIELD_HEADER_' + translationStringService.canonicalize(field.name); + + }; + // Update string value and re-assign to model when field is changed $scope.$watch('model', function setModel(model) { diff --git a/guacamole/src/main/webapp/app/form/directives/formField.js b/guacamole/src/main/webapp/app/form/directives/formField.js index ff296f0b2..bf9b35434 100644 --- a/guacamole/src/main/webapp/app/form/directives/formField.js +++ b/guacamole/src/main/webapp/app/form/directives/formField.js @@ -32,6 +32,17 @@ angular.module('form').directive('guacFormField', [function formField() { replace: true, scope: { + /** + * The translation namespace of the translation strings that will + * be generated for this field. This namespace is absolutely + * required. If this namespace is omitted, all generated + * translation strings will be placed within the MISSING_NAMESPACE + * namespace, as a warning. + * + * @type String + */ + namespace : '=', + /** * The field to display. * @@ -51,6 +62,9 @@ angular.module('form').directive('guacFormField', [function formField() { templateUrl: 'app/form/templates/formField.html', controller: ['$scope', '$injector', function formFieldController($scope, $injector) { + // Required services + var translationStringService = $injector.get('translationStringService'); + /** * The type to use for password input fields. By default, password * input fields have type 'password', and are thus masked. @@ -72,10 +86,10 @@ angular.module('form').directive('guacFormField', [function formField() { // If password is hidden, togglePassword() will show the password if ($scope.passwordInputType === 'password') - return 'MANAGE.HELP_SHOW_PASSWORD'; + return 'FORM.HELP_SHOW_PASSWORD'; // If password is shown, togglePassword() will hide the password - return 'MANAGE.HELP_HIDE_PASSWORD'; + return 'FORM.HELP_HIDE_PASSWORD'; }; @@ -96,6 +110,37 @@ angular.module('form').directive('guacFormField', [function formField() { }; + /** + * Produces the translation string for the given field option + * value. The translation string will be of the form: + * + * NAMESPACE.FIELD_OPTION_NAME_VALUE + * + * where NAMESPACE is the namespace provided to the + * directive, NAME is the field name transformed + * via translationStringService.canonicalize(), and + * VALUE is the option value transformed via + * translationStringService.canonicalize() + * + * @param {String} value + * The name of the option value. + * + * @returns {String} + * The translation string which produces the translated name of the + * value specified. + */ + $scope.getFieldOption = function getFieldOption(value) { + + // Don't bother if the model is not yet defined + if (!$scope.field) + return ''; + + return translationStringService.canonicalize($scope.namespace || 'MISSING_NAMESPACE') + + '.FIELD_OPTION_' + translationStringService.canonicalize($scope.field.name) + + '_' + translationStringService.canonicalize(value || 'EMPTY'); + + }; + /** * Translates the given string field value into an appropriately- * typed value as dictated by the attributes of the field, @@ -107,7 +152,7 @@ angular.module('form').directive('guacFormField', [function formField() { */ var setTypedValue = function setTypedValue(modelValue) { - // Don't bother if the modelValue is not yet defined + // Don't bother if the model is not yet defined if (!$scope.field) return; @@ -148,7 +193,7 @@ angular.module('form').directive('guacFormField', [function formField() { $scope.model = typedValue.toString(); } - // Convert boolean values back into strings based on protocol description + // Convert boolean values back into strings based on field description else if ($scope.field.type === 'BOOLEAN') $scope.model = (typedValue ? $scope.field.value : ''); diff --git a/guacamole/src/main/webapp/app/form/formModule.js b/guacamole/src/main/webapp/app/form/formModule.js index fe75b659c..a3e1f4a33 100644 --- a/guacamole/src/main/webapp/app/form/formModule.js +++ b/guacamole/src/main/webapp/app/form/formModule.js @@ -23,4 +23,4 @@ /** * Module for displaying dynamic forms. */ -angular.module('form', []); +angular.module('form', ['locale']); diff --git a/guacamole/src/main/webapp/app/form/templates/form.html b/guacamole/src/main/webapp/app/form/templates/form.html index e8b29eb58..5f93f52cf 100644 --- a/guacamole/src/main/webapp/app/form/templates/form.html +++ b/guacamole/src/main/webapp/app/form/templates/form.html @@ -23,9 +23,9 @@ - {{field.title | translate}} + {{getFieldHeader(field) | translate}} - + diff --git a/guacamole/src/main/webapp/app/form/templates/formField.html b/guacamole/src/main/webapp/app/form/templates/formField.html index 8a51e79a7..ebcf3573f 100644 --- a/guacamole/src/main/webapp/app/form/templates/formField.html +++ b/guacamole/src/main/webapp/app/form/templates/formField.html @@ -37,6 +37,6 @@ - + \ No newline at end of file diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js index cee4d7315..08700c893 100644 --- a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js +++ b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js @@ -266,9 +266,41 @@ angular.module('manage').controller('manageConnectionController', ['$scope', '$i $scope.parameters = {}; } + /** + * Returns the translation string namespace for the protocol having the + * given name. The namespace will be of the form: + * + * PROTOCOL_NAME + * + * where NAME is the protocol name transformed via + * translationStringService.canonicalize(). + * + * @param {String} protocolName + * The name of the protocol. + * + * @returns {String} + * The translation namespace for the protocol specified, or null if no + * namespace could be generated. + */ + $scope.getNamespace = function getNamespace(protocolName) { + + // Do not generate a namespace if no protocol is selected + if (!protocolName) + return null; + + return 'PROTOCOL_' + translationStringService.canonicalize(protocolName); + + }; + /** * Given the internal name of a protocol, produces the translation string - * for the localized version of that protocol's name. + * for the localized version of that protocol's name. The translation + * string will be of the form: + * + * NAMESPACE.NAME + * + * where NAMESPACE is the namespace generated from + * $scope.getNamespace(). * * @param {String} protocolName * The name of the protocol. @@ -278,7 +310,7 @@ angular.module('manage').controller('manageConnectionController', ['$scope', '$i * protocol specified. */ $scope.getProtocolName = function getProtocolName(protocolName) { - return 'PROTOCOL_' + translationStringService.canonicalize(protocolName) + '.NAME'; + return $scope.getNamespace(protocolName) + '.NAME'; }; /** diff --git a/guacamole/src/main/webapp/app/manage/templates/manageConnection.html b/guacamole/src/main/webapp/app/manage/templates/manageConnection.html index 3e2fdf3d8..0a8635b56 100644 --- a/guacamole/src/main/webapp/app/manage/templates/manageConnection.html +++ b/guacamole/src/main/webapp/app/manage/templates/manageConnection.html @@ -60,7 +60,9 @@ THE SOFTWARE.

{{'MANAGE_CONNECTION.SECTION_HEADER_PARAMETERS' | translate}}

- +
diff --git a/guacamole/src/main/webapp/translations/en_US.json b/guacamole/src/main/webapp/translations/en_US.json index bee9e7896..c3d07bee5 100644 --- a/guacamole/src/main/webapp/translations/en_US.json +++ b/guacamole/src/main/webapp/translations/en_US.json @@ -117,6 +117,13 @@ }, + "FORM" : { + + "HELP_SHOW_PASSWORD" : "Click to show password", + "HELP_HIDE_PASSWORD" : "Click to hide password" + + }, + "HOME" : { "INFO_ACTIVE_USER_COUNT" : "@:APP.INFO_ACTIVE_USER_COUNT", @@ -161,8 +168,6 @@ "FORMAT_HISTORY_START" : "@:APP.FORMAT_DATE_TIME_PRECISE", "HELP_CONNECTIONS" : "Click or tap on a connection below to manage that connection. Depending on your access level, connections can be added and deleted, and their properties (protocol, hostname, port, etc.) can be changed.", - "HELP_SHOW_PASSWORD" : "Click to show password", - "HELP_HIDE_PASSWORD" : "Click to hide password", "INFO_ACTIVE_USER_COUNT" : "@:APP.INFO_ACTIVE_USER_COUNT", "INFO_CONNECTION_DURATION_UNKNOWN" : "--",