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 <stefan.klotz@bosch-si.com>
This commit is contained in:
Stefan Klotz
2019-03-14 12:43:47 +01:00
committed by Stefan Behl
parent c3843416b9
commit 75f66c9811
9 changed files with 168 additions and 13 deletions

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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() {

View File

@@ -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());
}
}

View File

@@ -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();

View File

@@ -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<String> 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));
}
}

View File

@@ -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.";
/**

View File

@@ -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;

View File

@@ -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...