diff --git a/guacamole/src/main/frontend/src/app/import/directives/connectionImportErrors.js b/guacamole/src/main/frontend/src/app/import/directives/connectionImportErrors.js index 65b4403fe..aae51db63 100644 --- a/guacamole/src/main/frontend/src/app/import/directives/connectionImportErrors.js +++ b/guacamole/src/main/frontend/src/app/import/directives/connectionImportErrors.js @@ -155,6 +155,10 @@ angular.module('import').directive('connectionImportErrors', [ if (!patchFailure || !parseResult) return; + // All promises from all translation requests. The scope will not be + // updated until all translations are ready. + const translationPromises = []; + // Set up the list of connection errors based on the existing parse // result, with error messages fetched from the patch failure $scope.connectionErrors = parseResult.patches.map( @@ -166,10 +170,24 @@ angular.module('import').directive('connectionImportErrors', [ // Set the error from the PATCH request, if there is one const error = _.get(patchFailure, ['patches', index, 'error']); if (error) - connectionError.errors = new DisplayErrorList([error]); + + // Fetch the translation and update it when it's ready + translationPromises.push($translate( + error.key, error.variables) + .then(translatedError => + connectionError.errors.getArray().push(translatedError) + )); return connectionError; + }); + + // Once all the translations have been completed, update the + // connectionErrors all in one go, to ensure no excessive reloading + $q.all(translationPromises).then(() => { + $scope.connectionErrors = connectionErrors; + }); + }); // If a new parse result with errors is seen, update the display list diff --git a/guacamole/src/main/frontend/src/app/import/types/ParseError.js b/guacamole/src/main/frontend/src/app/import/types/ParseError.js index 33fd07765..b4b3dd647 100644 --- a/guacamole/src/main/frontend/src/app/import/types/ParseError.js +++ b/guacamole/src/main/frontend/src/app/import/types/ParseError.js @@ -61,6 +61,13 @@ angular.module('import').factory('ParseError', [function defineParseError() { */ this.variables = template.variables; + // If no translation key is available, fall back to the untranslated + // key, passing the raw message directly through the translation system + if (!this.key) { + this.key = 'APP.TEXT_UNTRANSLATED'; + this.variables = { MESSAGE: this.message }; + } + }; return ParseError; diff --git a/guacamole/src/main/frontend/src/app/rest/types/DirectoryPatchOutcome.js b/guacamole/src/main/frontend/src/app/rest/types/DirectoryPatchOutcome.js index e6710c2ca..324f1ae18 100644 --- a/guacamole/src/main/frontend/src/app/rest/types/DirectoryPatchOutcome.js +++ b/guacamole/src/main/frontend/src/app/rest/types/DirectoryPatchOutcome.js @@ -68,7 +68,7 @@ angular.module('rest').factory('DirectoryPatchOutcome', [ * The error message associated with the failure, if the patch failed to * apply. * - * @type {String} + * @type {TranslatableMessage} */ this.error = template.error; diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java index 0cfa8cb0f..0230051a9 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java @@ -21,10 +21,13 @@ package org.apache.guacamole.rest.directory; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.inject.Inject; import javax.ws.rs.Consumes; import javax.ws.rs.GET; @@ -39,6 +42,8 @@ import org.apache.guacamole.GuacamoleClientException; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleResourceNotFoundException; import org.apache.guacamole.GuacamoleUnsupportedException; +import org.apache.guacamole.language.Translatable; +import org.apache.guacamole.language.TranslatableMessage; import org.apache.guacamole.net.auth.AtomicDirectoryOperation; import org.apache.guacamole.net.auth.AuthenticatedUser; import org.apache.guacamole.net.auth.AuthenticationProvider; @@ -53,6 +58,7 @@ import org.apache.guacamole.net.auth.permission.SystemPermissionSet; import org.apache.guacamole.net.event.DirectoryEvent; import org.apache.guacamole.net.event.DirectoryFailureEvent; import org.apache.guacamole.net.event.DirectorySuccessEvent; +import org.apache.guacamole.rest.APIError; import org.apache.guacamole.rest.event.ListenerService; import org.apache.guacamole.rest.jsonpatch.APIPatch; import org.apache.guacamole.rest.jsonpatch.APIPatchError; @@ -415,6 +421,61 @@ public abstract class DirectoryResource patches) { - super(message ); + super(message); this.patches = patches; }