From 75f66c9811134c854a3062c2b3cbafd5876fe383 Mon Sep 17 00:00:00 2001 From: Stefan Klotz <35995139+StefanKlt@users.noreply.github.com> Date: Thu, 14 Mar 2019 12:43:47 +0100 Subject: [PATCH] Fix localization vaadin system messages (#807) * Add customized SystemMessagesProvider * Localize according to SystemMessagesInfo * Localize vaadin 'Server connection lost' message * Use available locale for system messages * Add license header * Fix PR findings * Fix Sonar issues Signed-off-by: Stefan Klotz --- .../java/org/eclipse/hawkbit/app/MyUI.java | 6 +- .../eclipse/hawkbit/ui/AbstractHawkbitUI.java | 8 ++- .../ui/AsyncVaadinServletConfiguration.java | 22 ++++++ .../ui/LocalizedSystemMessagesProvider.java | 68 +++++++++++++++++++ .../ui/login/AbstractHawkbitLoginUI.java | 2 +- .../hawkbit/ui/utils/HawkbitCommonUtil.java | 32 +++++++-- .../hawkbit/ui/utils/UIMessageIdProvider.java | 14 ++++ .../hawkbit/ui/utils/VaadinMessageSource.java | 20 +++++- .../src/main/resources/messages.properties | 9 +++ 9 files changed, 168 insertions(+), 13 deletions(-) create mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/LocalizedSystemMessagesProvider.java diff --git a/hawkbit-runtime/hawkbit-update-server/src/main/java/org/eclipse/hawkbit/app/MyUI.java b/hawkbit-runtime/hawkbit-update-server/src/main/java/org/eclipse/hawkbit/app/MyUI.java index 29ed12209..b873d513f 100644 --- a/hawkbit-runtime/hawkbit-update-server/src/main/java/org/eclipse/hawkbit/app/MyUI.java +++ b/hawkbit-runtime/hawkbit-update-server/src/main/java/org/eclipse/hawkbit/app/MyUI.java @@ -14,6 +14,7 @@ import org.eclipse.hawkbit.ui.UiProperties; import org.eclipse.hawkbit.ui.components.NotificationUnreadButton; import org.eclipse.hawkbit.ui.menu.DashboardMenu; import org.eclipse.hawkbit.ui.push.EventPushStrategy; +import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.vaadin.spring.events.EventBus.UIEventBus; @@ -44,9 +45,10 @@ public class MyUI extends AbstractHawkbitUI { @Autowired MyUI(final EventPushStrategy pushStrategy, final UIEventBus eventBus, final SpringViewProvider viewProvider, final ApplicationContext context, final DashboardMenu dashboardMenu, final ErrorView errorview, - final NotificationUnreadButton notificationUnreadButton, final UiProperties uiProperties) { + final NotificationUnreadButton notificationUnreadButton, final UiProperties uiProperties, + final VaadinMessageSource i18n) { super(pushStrategy, eventBus, viewProvider, context, dashboardMenu, errorview, notificationUnreadButton, - uiProperties); + uiProperties, i18n); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/AbstractHawkbitUI.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/AbstractHawkbitUI.java index abd1f4bd7..011ed0309 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/AbstractHawkbitUI.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/AbstractHawkbitUI.java @@ -17,6 +17,7 @@ import org.eclipse.hawkbit.ui.push.EventPushStrategy; import org.eclipse.hawkbit.ui.themes.HawkbitTheme; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.SpringContextHelper; +import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; @@ -76,10 +77,12 @@ public abstract class AbstractHawkbitUI extends UI implements DetachListener { private final UiProperties uiProperties; + private final VaadinMessageSource i18n; + protected AbstractHawkbitUI(final EventPushStrategy pushStrategy, final UIEventBus eventBus, final SpringViewProvider viewProvider, final ApplicationContext context, final DashboardMenu dashboardMenu, final ErrorView errorview, final NotificationUnreadButton notificationUnreadButton, - final UiProperties uiProperties) { + final UiProperties uiProperties, final VaadinMessageSource i18n) { this.pushStrategy = pushStrategy; this.eventBus = eventBus; this.viewProvider = viewProvider; @@ -88,6 +91,7 @@ public abstract class AbstractHawkbitUI extends UI implements DetachListener { this.errorview = errorview; this.notificationUnreadButton = notificationUnreadButton; this.uiProperties = uiProperties; + this.i18n = i18n; } @Override @@ -115,7 +119,7 @@ public abstract class AbstractHawkbitUI extends UI implements DetachListener { final HorizontalLayout rootLayout = new HorizontalLayout(); rootLayout.setSizeFull(); - setLocale(HawkbitCommonUtil.getLocaleToBeUsed(uiProperties.getLocalization(), getUI())); + HawkbitCommonUtil.initLocalization(this, uiProperties.getLocalization(), i18n); dashboardMenu.init(); dashboardMenu.setResponsive(true); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/AsyncVaadinServletConfiguration.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/AsyncVaadinServletConfiguration.java index 439a42a84..f69e442a8 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/AsyncVaadinServletConfiguration.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/AsyncVaadinServletConfiguration.java @@ -8,16 +8,21 @@ */ package org.eclipse.hawkbit.ui; +import javax.servlet.ServletException; + import org.atmosphere.container.JSR356AsyncSupport; import org.atmosphere.cpr.ApplicationConfig; +import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import com.vaadin.server.VaadinServlet; import com.vaadin.spring.boot.internal.VaadinServletConfiguration; import com.vaadin.spring.boot.internal.VaadinServletConfigurationProperties; +import com.vaadin.spring.server.SpringVaadinServlet; /** * {@link VaadinServletConfiguration} that sets the context path for @@ -29,6 +34,23 @@ import com.vaadin.spring.boot.internal.VaadinServletConfigurationProperties; @Import(VaadinServletConfiguration.class) public class AsyncVaadinServletConfiguration extends VaadinServletConfiguration { + @Bean + public LocalizedSystemMessagesProvider localizedSystemMessagesProvider(final UiProperties uiProperties, + final VaadinMessageSource i18n) { + return new LocalizedSystemMessagesProvider(uiProperties, i18n); + } + + @Bean + public VaadinServlet vaadinServlet(final LocalizedSystemMessagesProvider localizedSystemMessagesProvider) { + return new SpringVaadinServlet() { + @Override + public void servletInitialized() throws ServletException { + super.servletInitialized(); + getService().setSystemMessagesProvider(localizedSystemMessagesProvider); + } + }; + } + @Override @Bean protected ServletRegistrationBean vaadinServletRegistration() { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/LocalizedSystemMessagesProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/LocalizedSystemMessagesProvider.java new file mode 100644 index 000000000..c45c8d48d --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/LocalizedSystemMessagesProvider.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2019 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.ui; + +import java.util.Locale; + +import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; +import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider; +import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; + +import com.vaadin.server.CustomizedSystemMessages; +import com.vaadin.server.SystemMessages; +import com.vaadin.server.SystemMessagesInfo; +import com.vaadin.server.SystemMessagesProvider; + +/** + * {@link SystemMessagesProvider} that localizes Vaadin system messages. + * + */ +public class LocalizedSystemMessagesProvider implements SystemMessagesProvider { + private static final long serialVersionUID = 1L; + + private final VaadinMessageSource i18n; + private final UiProperties uiProperties; + + /** + * @param uiProperties + * Properties to determine the available Locales + * @param i18n + * Message source used for localization + */ + public LocalizedSystemMessagesProvider(final UiProperties uiProperties, final VaadinMessageSource i18n) { + this.i18n = i18n; + this.uiProperties = uiProperties; + } + + private SystemMessages getLocalizedSystemMessages(final VaadinMessageSource i18n, final Locale local) { + final CustomizedSystemMessages messages = new CustomizedSystemMessages(); + final Locale desiredLocale = HawkbitCommonUtil.getLocaleToBeUsed(uiProperties.getLocalization(), local); + + messages.setSessionExpiredCaption( + i18n.getMessage(desiredLocale, UIMessageIdProvider.VAADIN_SYSTEM_SESSIONEXPIRED_CAPTION)); + messages.setSessionExpiredMessage( + i18n.getMessage(desiredLocale, UIMessageIdProvider.VAADIN_SYSTEM_SESSIONEXPIRED_MESSAGE)); + messages.setCommunicationErrorCaption( + i18n.getMessage(desiredLocale, UIMessageIdProvider.VAADIN_SYSTEM_COMMUNICATIONERROR_CAPTION)); + messages.setCommunicationErrorMessage( + i18n.getMessage(desiredLocale, UIMessageIdProvider.VAADIN_SYSTEM_COMMUNICATIONERROR_MESSAGE)); + messages.setInternalErrorCaption( + i18n.getMessage(desiredLocale, UIMessageIdProvider.VAADIN_SYSTEM_INTERNALERROR_CAPTION)); + messages.setInternalErrorMessage( + i18n.getMessage(desiredLocale, UIMessageIdProvider.VAADIN_SYSTEM_INTERNALERROR_MESSAGE)); + + return messages; + } + + @Override + public SystemMessages getSystemMessages(final SystemMessagesInfo systemMessagesInfo) { + return getLocalizedSystemMessages(i18n, systemMessagesInfo.getLocale()); + } + +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/login/AbstractHawkbitLoginUI.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/login/AbstractHawkbitLoginUI.java index 9d52f028f..585ff6510 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/login/AbstractHawkbitLoginUI.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/login/AbstractHawkbitLoginUI.java @@ -120,7 +120,7 @@ public abstract class AbstractHawkbitLoginUI extends UI { @Override protected void init(final VaadinRequest request) { - setLocale(HawkbitCommonUtil.getLocaleToBeUsed(uiProperties.getLocalization(), getUI())); + HawkbitCommonUtil.initLocalization(this, uiProperties.getLocalization(), i18n); SpringContextHelper.setContext(context); params = UriComponentsBuilder.fromUri(Page.getCurrent().getLocation()).build().getQueryParams(); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/HawkbitCommonUtil.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/HawkbitCommonUtil.java index 0c958cec4..396b2309c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/HawkbitCommonUtil.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/HawkbitCommonUtil.java @@ -20,6 +20,7 @@ import org.eclipse.hawkbit.repository.model.PollStatus; import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.ui.UiProperties; +import org.eclipse.hawkbit.ui.UiProperties.Localization; import org.eclipse.hawkbit.ui.rollout.StatusFontIcon; import org.springframework.util.StringUtils; import org.vaadin.addons.lazyquerycontainer.AbstractBeanQuery; @@ -563,24 +564,41 @@ public final class HawkbitCommonUtil { /** * Determine the language that should be used considering localization - * properties and UI settings + * properties and a desired Locale * * @param localizationProperties * UI Localization settings - * @param ui - * UI which settings are considered + * @param desiredLocale + * desired Locale * @return Locale to be used according to UI and properties */ - public static Locale getLocaleToBeUsed(final UiProperties.Localization localizationProperties, final UI ui) { + public static Locale getLocaleToBeUsed(final UiProperties.Localization localizationProperties, + final Locale desiredLocale) { final List availableLocals = localizationProperties.getAvailableLocals(); - final Locale uiLocale = ui.getSession().getLocale(); // ckeck if language code of UI locale matches an available local. // Country, region and variant are ignored. "availableLocals" must only // contain language codes without country or other extensions. - if (availableLocals.contains(uiLocale.getLanguage())) { - return uiLocale; + if (availableLocals.contains(desiredLocale.getLanguage())) { + return desiredLocale; } return new Locale(localizationProperties.getDefaultLocal()); } + /** + * Set localization considering properties and UI settings. + * + * @param ui + * UI to setup + * @param localizationProperties + * UI localization settings + * @param i18n + * Localization message source + */ + public static void initLocalization(final UI ui, final Localization localizationProperties, + final VaadinMessageSource i18n) { + ui.setLocale(HawkbitCommonUtil.getLocaleToBeUsed(localizationProperties, ui.getSession().getLocale())); + ui.getReconnectDialogConfiguration() + .setDialogText(i18n.getMessage(UIMessageIdProvider.VAADIN_SYSTEM_TRYINGRECONNECT)); + } + } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIMessageIdProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIMessageIdProvider.java index 99bcd0e01..2efa408a5 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIMessageIdProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIMessageIdProvider.java @@ -183,6 +183,20 @@ public final class UIMessageIdProvider { public static final String MESSAGE_TARGET_BULKUPLOAD_RESULT_FAIL = "message.bulk.upload.result.fail"; + public static final String VAADIN_SYSTEM_SESSIONEXPIRED_CAPTION = "vaadin.system.sessionexpired.caption"; + + public static final String VAADIN_SYSTEM_SESSIONEXPIRED_MESSAGE = "vaadin.system.sessionexpired.message"; + + public static final String VAADIN_SYSTEM_COMMUNICATIONERROR_CAPTION = "vaadin.system.communicationerror.caption"; + + public static final String VAADIN_SYSTEM_COMMUNICATIONERROR_MESSAGE = "vaadin.system.communicationerror.message"; + + public static final String VAADIN_SYSTEM_INTERNALERROR_CAPTION = "vaadin.system.internalerror.caption"; + + public static final String VAADIN_SYSTEM_INTERNALERROR_MESSAGE = "vaadin.system.internalerror.message"; + + public static final String VAADIN_SYSTEM_TRYINGRECONNECT = "vaadin.system.tryingreconnect"; + public static final String TOOLTIP_ROLLOUT_STATUS_PREFIX = "tooltip.rollout.status."; /** diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/VaadinMessageSource.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/VaadinMessageSource.java index b6adac818..32bbf1788 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/VaadinMessageSource.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/VaadinMessageSource.java @@ -55,8 +55,26 @@ public class VaadinMessageSource implements Serializable { * @see HawkbitCommonUtil#getCurrentLocale() */ public String getMessage(final String code, final Object... args) { + return getMessage(HawkbitCommonUtil.getCurrentLocale(), code, args); + } + + /** + * Tries to resolve the message based on the provided Local. Returns message + * code if fitting message could not be found. + * + * @param local + * to determinate the Language. + * @param code + * the code to lookup up. + * @param args + * Array of arguments that will be filled in for params within + * the message. + * + * @return the resolved message, or the message code if the lookup fails. + */ + public String getMessage(final Locale local, final String code, final Object... args) { try { - return source.getMessage(code, args, HawkbitCommonUtil.getCurrentLocale()); + return source.getMessage(code, args, local); } catch (final NoSuchMessageException ex) { LOG.error("Failed to retrieve message!", ex); return code; diff --git a/hawkbit-ui/src/main/resources/messages.properties b/hawkbit-ui/src/main/resources/messages.properties index 492f248df..37bffcf5b 100644 --- a/hawkbit-ui/src/main/resources/messages.properties +++ b/hawkbit-ui/src/main/resources/messages.properties @@ -707,3 +707,12 @@ character.whitespace = whitespace character.digits = digits character.quotationMarks = quotation marks character.slashes = slashes + +# Vaadin system messages +vaadin.system.sessionexpired.caption=Session Expired +vaadin.system.sessionexpired.message=Take note of any unsaved data, and click here or press ESC key to continue. +vaadin.system.communicationerror.caption=Communication problem +vaadin.system.communicationerror.message=Take note of any unsaved data, and click here or press ESC to continue. +vaadin.system.internalerror.caption=Internal error +vaadin.system.internalerror.message=Please notify the administrator. Take note of any unsaved data, and click here or press ESC to continue. +vaadin.system.tryingreconnect=Server connection lost, trying to reconnect...