GUACAMOLE-36: Define REST API transfer mechanism for translatable messages.

This commit is contained in:
Michael Jumper
2016-08-16 19:31:48 -07:00
parent 30179c405f
commit 0671f18d40
5 changed files with 240 additions and 2 deletions

View File

@@ -0,0 +1,41 @@
/*
* 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.
*/
package org.apache.guacamole.language;
/**
* An interface which requires the definition of a translatable message that
* can be passed through an arbitrary translation service, producing a
* human-readable message in the user's native language.
*
* @author Michael Jumper
*/
public interface Translatable {
/**
* Returns a message which can be translated using a translation service,
* consisting of a translation key and optional set of substitution
* variables.
*
* @return
* A message which can be translated using a translation service.
*/
TranslatableMessage getTranslatableMessage();
}

View File

@@ -0,0 +1,96 @@
/*
* 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.
*/
package org.apache.guacamole.language;
/**
* A message which can be translated using a translation service, providing a
* translation key and optional set of values to be substituted into the
* translation string associated with that key.
*
* @author Michael Jumper
*/
public class TranslatableMessage {
/**
* The arbitrary key which can be used to look up the message to be
* displayed in the user's native language.
*/
private final String key;
/**
* An arbitrary object whose properties should be substituted for the
* corresponding placeholders within the string associated with the key.
*/
private final Object variables;
/**
* Creates a new TranslatableMessage associated with the given translation
* key, without any associated variables.
*
* @param key
* The translation key to associate with the TranslatableMessage.
*/
public TranslatableMessage(String key) {
this(key, null);
}
/**
* Creates a new TranslatableMessage associated with the given translation
* key and associated variables.
*
* @param key
* The translation key to associate with the TranslatableMessage.
*
* @param variables
* An arbitrary object whose properties should be substituted for the
* corresponding placeholders within the string associated with the
* given translation key.
*/
public TranslatableMessage(String key, Object variables) {
this.key = key;
this.variables = variables;
}
/**
* Returns the arbitrary key which can be used to look up the message to be
* displayed in the user's native language.
*
* @return
* The arbitrary key associated with the human-readable message.
*/
public String getKey() {
return key;
}
/**
* Returns an arbitrary object whose properties should be substituted for
* the corresponding placeholders within the string associated with the key.
* If not applicable, null is returned.
*
* @return
* An arbitrary object whose properties should be substituted for the
* corresponding placeholders within the string associated with the key,
* or null if not applicable.
*/
public Object getVariables() {
return variables;
}
}

View File

@@ -25,6 +25,8 @@ import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleResourceNotFoundException; import org.apache.guacamole.GuacamoleResourceNotFoundException;
import org.apache.guacamole.GuacamoleSecurityException; import org.apache.guacamole.GuacamoleSecurityException;
import org.apache.guacamole.form.Field; import org.apache.guacamole.form.Field;
import org.apache.guacamole.language.Translatable;
import org.apache.guacamole.language.TranslatableMessage;
import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException; import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException;
import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException; import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException; import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
@@ -39,10 +41,15 @@ import org.apache.guacamole.tunnel.GuacamoleStreamException;
public class APIError { public class APIError {
/** /**
* The error message. * The human-readable error message.
*/ */
private final String message; private final String message;
/**
* A translatable message representing the error that occurred.
*/
private final TranslatableMessage translatableMessage;
/** /**
* The associated Guacamole protocol status code. * The associated Guacamole protocol status code.
*/ */
@@ -148,7 +155,9 @@ public class APIError {
/** /**
* Creates a new APIError which exposes the details of the given * Creates a new APIError which exposes the details of the given
* GuacamoleException. * GuacamoleException. If the given GuacamoleException implements
* Translatable, then its translation string and values will be exposed as
* well.
* *
* @param exception * @param exception
* The GuacamoleException from which the details of the new APIError * The GuacamoleException from which the details of the new APIError
@@ -176,6 +185,14 @@ public class APIError {
else else
this.statusCode = null; this.statusCode = null;
// Pull translatable message and values if available
if (exception instanceof Translatable) {
Translatable translatable = (Translatable) exception;
this.translatableMessage = translatable.getTranslatableMessage();
}
else
this.translatableMessage = new TranslatableMessage(this.message);
} }
/** /**
@@ -223,4 +240,16 @@ public class APIError {
return message; return message;
} }
/**
* Returns a translatable message describing the error that occurred. If no
* translatable message is associated with the error, this will be null.
*
* @return
* A translatable message describing the error that occurred, or null
* if there is no such message defined.
*/
public TranslatableMessage getTranslatableMessage() {
return translatableMessage;
}
} }

View File

@@ -42,6 +42,15 @@ angular.module('rest').factory('Error', [function defineError() {
*/ */
this.message = template.message; this.message = template.message;
/**
* A message which can be translated using the translation service,
* consisting of a translation key and optional set of substitution
* variables.
*
* @type TranslatableMessage
*/
this.translatableMessage = template.translatableMessage;
/** /**
* The Guacamole protocol status code associated with the error that * The Guacamole protocol status code associated with the error that
* occurred. This is only valid for errors of type STREAM_ERROR. * occurred. This is only valid for errors of type STREAM_ERROR.

View File

@@ -0,0 +1,63 @@
/*
* 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.
*/
/**
* Service which defines the TranslatableMessage class.
*/
angular.module('rest').factory('TranslatableMessage', [function defineTranslatableMessage() {
/**
* The object returned by REST API calls when representing a message which
* can be translated using the translation service, providing a translation
* key and optional set of values to be substituted into the translation
* string associated with that key.
*
* @constructor
* @param {TranslatableMessage|Object} [template={}]
* The object whose properties should be copied within the new
* TranslatableMessage.
*/
var TranslatableMessage = function TranslatableMessage(template) {
// Use empty object by default
template = template || {};
/**
* The key associated with the translation string that used when
* displaying this message.
*
* @type String
*/
this.key = template.key;
/**
* The object which should be passed through to the translation service
* for the sake of variable substitution. Each property of the provided
* object will be substituted for the variable of the same name within
* the translation string.
*
* @type Object
*/
this.variables = template.variables;
};
return TranslatableMessage;
}]);