GUAC-1160: Generate localized field headers and option values within "form" module.

This commit is contained in:
Michael Jumper
2015-04-15 15:56:20 -07:00
parent 32019e7cdf
commit e1f769fcbc
8 changed files with 136 additions and 14 deletions

View File

@@ -32,6 +32,17 @@ angular.module('form').directive('guacForm', [function form() {
replace: true, replace: true,
scope: { 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. * The fields to display.
* *
@@ -50,7 +61,10 @@ angular.module('form').directive('guacForm', [function form() {
}, },
templateUrl: 'app/form/templates/form.html', 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 * The object which will receive all field values. Normally, this
@@ -63,6 +77,30 @@ angular.module('form').directive('guacForm', [function form() {
*/ */
$scope.values = {}; $scope.values = {};
/**
* Produces the translation string for the header of the given
* field. The translation string will be of the form:
*
* <code>NAMESPACE.FIELD_HEADER_NAME<code>
*
* where <code>NAMESPACE</code> is the namespace provided to the
* directive and <code>NAME</code> 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 // Update string value and re-assign to model when field is changed
$scope.$watch('model', function setModel(model) { $scope.$watch('model', function setModel(model) {

View File

@@ -32,6 +32,17 @@ angular.module('form').directive('guacFormField', [function formField() {
replace: true, replace: true,
scope: { 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. * The field to display.
* *
@@ -51,6 +62,9 @@ angular.module('form').directive('guacFormField', [function formField() {
templateUrl: 'app/form/templates/formField.html', templateUrl: 'app/form/templates/formField.html',
controller: ['$scope', '$injector', function formFieldController($scope, $injector) { 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 * The type to use for password input fields. By default, password
* input fields have type 'password', and are thus masked. * 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 password is hidden, togglePassword() will show the password
if ($scope.passwordInputType === 'password') if ($scope.passwordInputType === 'password')
return 'MANAGE.HELP_SHOW_PASSWORD'; return 'FORM.HELP_SHOW_PASSWORD';
// If password is shown, togglePassword() will hide the 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:
*
* <code>NAMESPACE.FIELD_OPTION_NAME_VALUE<code>
*
* where <code>NAMESPACE</code> is the namespace provided to the
* directive, <code>NAME</code> is the field name transformed
* via translationStringService.canonicalize(), and
* <code>VALUE</code> 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- * Translates the given string field value into an appropriately-
* typed value as dictated by the attributes of the field, * 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) { 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) if (!$scope.field)
return; return;
@@ -148,7 +193,7 @@ angular.module('form').directive('guacFormField', [function formField() {
$scope.model = typedValue.toString(); $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') else if ($scope.field.type === 'BOOLEAN')
$scope.model = (typedValue ? $scope.field.value : ''); $scope.model = (typedValue ? $scope.field.value : '');

View File

@@ -23,4 +23,4 @@
/** /**
* Module for displaying dynamic forms. * Module for displaying dynamic forms.
*/ */
angular.module('form', []); angular.module('form', ['locale']);

View File

@@ -23,9 +23,9 @@
<!-- All fields in form --> <!-- All fields in form -->
<tr ng-repeat="field in fields"> <tr ng-repeat="field in fields">
<th>{{field.title | translate}}</th> <th>{{getFieldHeader(field) | translate}}</th>
<td> <td>
<guac-form-field field="field" model="values[field.name]"></guac-form-field> <guac-form-field namespace="namespace" field="field" model="values[field.name]"></guac-form-field>
</td> </td>
</tr> </tr>

View File

@@ -37,6 +37,6 @@
<textarea ng-show="field.type === 'MULTILINE'" ng-model="typedValue" autocorrect="off" autocapitalize="off"></textarea> <textarea ng-show="field.type === 'MULTILINE'" ng-model="typedValue" autocorrect="off" autocapitalize="off"></textarea>
<!-- Enumerated field --> <!-- Enumerated field -->
<select ng-show="field.type === 'ENUM'" ng-model="typedValue" ng-options="option.value as option.title | translate for option in field.options | orderBy: value"></select> <select ng-show="field.type === 'ENUM'" ng-model="typedValue" ng-options="option.value as getFieldOption(option.value) | translate for option in field.options | orderBy: value"></select>
</div> </div>

View File

@@ -266,9 +266,41 @@ angular.module('manage').controller('manageConnectionController', ['$scope', '$i
$scope.parameters = {}; $scope.parameters = {};
} }
/**
* Returns the translation string namespace for the protocol having the
* given name. The namespace will be of the form:
*
* <code>PROTOCOL_NAME</code>
*
* where <code>NAME</code> 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 * 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:
*
* <code>NAMESPACE.NAME<code>
*
* where <code>NAMESPACE</code> is the namespace generated from
* $scope.getNamespace().
* *
* @param {String} protocolName * @param {String} protocolName
* The name of the protocol. * The name of the protocol.
@@ -278,7 +310,7 @@ angular.module('manage').controller('manageConnectionController', ['$scope', '$i
* protocol specified. * protocol specified.
*/ */
$scope.getProtocolName = function getProtocolName(protocolName) { $scope.getProtocolName = function getProtocolName(protocolName) {
return 'PROTOCOL_' + translationStringService.canonicalize(protocolName) + '.NAME'; return $scope.getNamespace(protocolName) + '.NAME';
}; };
/** /**

View File

@@ -60,7 +60,9 @@ THE SOFTWARE.
<!-- Connection parameters --> <!-- Connection parameters -->
<h2 class="header">{{'MANAGE_CONNECTION.SECTION_HEADER_PARAMETERS' | translate}}</h2> <h2 class="header">{{'MANAGE_CONNECTION.SECTION_HEADER_PARAMETERS' | translate}}</h2>
<div class="section connection-parameters" ng-class="{loading: !parameters}"> <div class="section connection-parameters" ng-class="{loading: !parameters}">
<guac-form fields="protocols[connection.protocol].parameters" model="parameters"></guac-form> <guac-form namespace="getNamespace(connection.protocol)"
fields="protocols[connection.protocol].parameters"
model="parameters"></guac-form>
</div> </div>
<!-- Form action buttons --> <!-- Form action buttons -->

View File

@@ -117,6 +117,13 @@
}, },
"FORM" : {
"HELP_SHOW_PASSWORD" : "Click to show password",
"HELP_HIDE_PASSWORD" : "Click to hide password"
},
"HOME" : { "HOME" : {
"INFO_ACTIVE_USER_COUNT" : "@:APP.INFO_ACTIVE_USER_COUNT", "INFO_ACTIVE_USER_COUNT" : "@:APP.INFO_ACTIVE_USER_COUNT",
@@ -161,8 +168,6 @@
"FORMAT_HISTORY_START" : "@:APP.FORMAT_DATE_TIME_PRECISE", "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_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_ACTIVE_USER_COUNT" : "@:APP.INFO_ACTIVE_USER_COUNT",
"INFO_CONNECTION_DURATION_UNKNOWN" : "--", "INFO_CONNECTION_DURATION_UNKNOWN" : "--",