From 96b5937a9b45caf65da23f93d746bcdbf3265211 Mon Sep 17 00:00:00 2001 From: Boubaker Khanfir Date: Tue, 7 May 2024 15:14:59 +0100 Subject: [PATCH] feat: Display Builtin Page Names in Layout editor - MEED-6796 - Meeds-io/MIPs#131 (#57) Prior to this change, the builtin pages uses I18N labels instead of Translated labels. This change allows to retrieve all translated labels of the page while editing the node or while editing the page to display the page name switch user language. --- .../service/NavigationLayoutService.java | 67 +++++++++++++------ .../service/NavigationLayoutServiceTest.java | 12 +++- .../components/toolbar/Toolbar.vue | 3 + 3 files changed, 60 insertions(+), 22 deletions(-) diff --git a/layout-service/src/main/java/io/meeds/layout/service/NavigationLayoutService.java b/layout-service/src/main/java/io/meeds/layout/service/NavigationLayoutService.java index 8983f403c..2d099da3d 100644 --- a/layout-service/src/main/java/io/meeds/layout/service/NavigationLayoutService.java +++ b/layout-service/src/main/java/io/meeds/layout/service/NavigationLayoutService.java @@ -22,18 +22,20 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.ResourceBundle; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.exoplatform.commons.exception.ObjectNotFoundException; -import org.exoplatform.commons.utils.I18N; +import org.exoplatform.commons.utils.ExpressionUtil; import org.exoplatform.portal.application.PortalRequestHandler; import org.exoplatform.portal.mop.SiteKey; import org.exoplatform.portal.mop.State; @@ -46,8 +48,8 @@ import org.exoplatform.portal.mop.service.DescriptionService; import org.exoplatform.portal.mop.service.LayoutService; import org.exoplatform.portal.mop.service.NavigationService; -import org.exoplatform.services.resources.LocaleConfig; import org.exoplatform.services.resources.LocaleConfigService; +import org.exoplatform.services.resources.ResourceBundleManager; import org.exoplatform.web.WebAppController; import org.exoplatform.web.controller.QualifiedName; import org.exoplatform.web.controller.router.Router; @@ -73,6 +75,9 @@ public class NavigationLayoutService { @Autowired private PageLayoutService pageLayoutService; + @Autowired + private ResourceBundleManager resourceBundleManager; + @Autowired private LocaleConfigService localeConfigService; @@ -243,17 +248,37 @@ public NodeData getNode(long nodeId, return nodeData; } - public NodeLabel getNodeLabels(long nodeId, - String username) throws ObjectNotFoundException, - IllegalAccessException { + public NodeLabel getNodeLabels(long nodeId, String username) throws ObjectNotFoundException, IllegalAccessException { NodeData nodeData = navigationService.getNodeById(nodeId); if (nodeData == null) { throw new ObjectNotFoundException(String.format(NODE_DATA_WITH_NODE_ID_IS_NOT_FOUND, nodeId)); - } else if (!aclService.canViewNavigation(nodeData.getSiteKey(), nodeData.getState().getPageRef(), username)) { - throw new IllegalAccessException(); + } else { + SiteKey siteKey = nodeData.getSiteKey(); + if (!aclService.canViewNavigation(siteKey, nodeData.getState().getPageRef(), username)) { + throw new IllegalAccessException(); + } } Map nodeLabels = descriptionService.getDescriptions(String.valueOf(nodeId)); - return toNodeLabel(nodeLabels); + if (MapUtils.isEmpty(nodeLabels)) { + Map nodeLocalizedLabels = new HashMap<>(); + localeConfigService.getLocalConfigs().forEach(localeConfig -> { + Locale locale = localeConfig.getLocale(); + String label = nodeData.getState().getLabel(); + if (ExpressionUtil.isResourceBindingExpression(label)) { + SiteKey siteKey = nodeData.getSiteKey(); + ResourceBundle nodeLabelResourceBundle = resourceBundleManager.getNavigationResourceBundle(locale.toLanguageTag(), + siteKey.getTypeName(), + siteKey.getName()); + if (nodeLabelResourceBundle != null) { + label = ExpressionUtil.getExpressionValue(nodeLabelResourceBundle, label); + } + } + nodeLocalizedLabels.put(locale, new State(label, null)); + }); + return toNodeLabel(nodeLocalizedLabels); + } else { + return toNodeLabel(nodeLabels); + } } public String getNodeUri(long nodeId, String username) throws IllegalAccessException, ObjectNotFoundException { @@ -392,25 +417,27 @@ public NodeLabel toNodeLabel(Map nodeLabels) { String defaultLanguage = defaultLocale.getLanguage(); Map supportedLanguages = CollectionUtils.isEmpty(localeConfigService.getLocalConfigs()) ? - Collections.singletonMap(defaultLocale.getLanguage(), - defaultLocale.getDisplayName()) : - localeConfigService.getLocalConfigs() - .stream() - .filter(localeConfig -> !StringUtils.equals(localeConfig.getLocaleName(), - "ma")) - .collect(Collectors.toMap(LocaleConfig::getLocaleName, - localeConfig -> localeConfig.getLocale() - .getDisplayName())); + Collections.singletonMap(defaultLocale.toLanguageTag(), + defaultLocale.getDisplayName()) : + localeConfigService.getLocalConfigs() + .stream() + .filter(localeConfig -> !StringUtils.equals(localeConfig.getLocale() + .toLanguageTag(), + "ma")) + .collect(Collectors.toMap(c -> c.getLocale() + .toLanguageTag(), + localeConfig -> localeConfig.getLocale() + .getDisplayName())); Map localized = new HashMap<>(); NodeLabel nodeLabel = new NodeLabel(); - if (nodeLabels != null && nodeLabels.size() != 0) { + if (MapUtils.isNotEmpty(nodeLabels)) { for (Map.Entry entry : nodeLabels.entrySet()) { Locale locale = entry.getKey(); State state = entry.getValue(); - localized.put(I18N.toTagIdentifier(locale), state.getName()); + localized.put(locale.toLanguageTag(), state.getName()); } if (!nodeLabels.containsKey(defaultLocale) && !localized.isEmpty()) { - localized.put(I18N.toTagIdentifier(defaultLocale), localized.values().iterator().next()); + localized.put(defaultLocale.toLanguageTag(), localized.values().iterator().next()); } nodeLabel.setLabels(localized); } diff --git a/layout-service/src/test/java/io/meeds/layout/service/NavigationLayoutServiceTest.java b/layout-service/src/test/java/io/meeds/layout/service/NavigationLayoutServiceTest.java index d6a943262..beaa056d3 100644 --- a/layout-service/src/test/java/io/meeds/layout/service/NavigationLayoutServiceTest.java +++ b/layout-service/src/test/java/io/meeds/layout/service/NavigationLayoutServiceTest.java @@ -55,6 +55,7 @@ import org.exoplatform.portal.mop.service.NavigationService; import org.exoplatform.services.resources.LocaleConfig; import org.exoplatform.services.resources.LocaleConfigService; +import org.exoplatform.services.resources.ResourceBundleManager; import org.exoplatform.web.WebAppController; import org.exoplatform.web.controller.router.Router; @@ -90,6 +91,9 @@ public class NavigationLayoutServiceTest { @MockBean private WebAppController webController; + @MockBean + private ResourceBundleManager resourceBundleManager; + @MockBean private LocaleConfigService localeConfigService; @@ -148,6 +152,9 @@ public void createDraftNode() throws IllegalAccessException, ObjectNotFoundExcep when(nodeData.getState()).thenReturn(nodeState); when(nodeData.getSiteKey()).thenReturn(SITE_KEY); when(nodeState.getPageRef()).thenReturn(PAGE_KEY); + when(localeConfigService.getDefaultLocaleConfig()).thenReturn(defaultLocaleConfig); + when(defaultLocaleConfig.getLocale()).thenReturn(Locale.FRENCH); + assertThrows(ObjectNotFoundException.class, () -> navigationLayoutService.createDraftNode(2l, TEST_USER)); when(navigationService.getNodeById(2l)).thenReturn(nodeData); @@ -258,6 +265,9 @@ public void getNodeLabels() throws IllegalAccessException, ObjectNotFoundExcepti when(nodeData.getSiteKey()).thenReturn(SITE_KEY); when(nodeData.getState()).thenReturn(nodeState); when(nodeState.getPageRef()).thenReturn(PAGE_KEY); + when(localeConfigService.getDefaultLocaleConfig()).thenReturn(defaultLocaleConfig); + when(defaultLocaleConfig.getLocale()).thenReturn(Locale.FRENCH); + assertThrows(IllegalAccessException.class, () -> navigationLayoutService.getNodeLabels(2, TEST_USER)); verify(descriptionService, never()).getDescriptions("2"); @@ -267,11 +277,9 @@ public void getNodeLabels() throws IllegalAccessException, ObjectNotFoundExcepti when(localeConfigService.getDefaultLocaleConfig()).thenReturn(defaultLocaleConfig); when(defaultLocaleConfig.getLocale()).thenReturn(Locale.FRENCH); - when(defaultLocaleConfig.getLocaleName()).thenReturn(Locale.FRENCH.toLanguageTag()); LocaleConfig otherLocaleConfig = mock(LocaleConfig.class); when(otherLocaleConfig.getLocale()).thenReturn(Locale.ENGLISH); - when(otherLocaleConfig.getLocaleName()).thenReturn(Locale.ENGLISH.toLanguageTag()); when(localeConfigService.getLocalConfigs()).thenReturn(Arrays.asList(defaultLocaleConfig, otherLocaleConfig)); String nodeName = "testLabel"; when(descriptionService.getDescriptions("2")).thenReturn(Collections.singletonMap(Locale.ENGLISH, diff --git a/layout-webapp/src/main/webapp/vue-app/layout-editor/components/toolbar/Toolbar.vue b/layout-webapp/src/main/webapp/vue-app/layout-editor/components/toolbar/Toolbar.vue index d498e9b5b..a865a9598 100644 --- a/layout-webapp/src/main/webapp/vue-app/layout-editor/components/toolbar/Toolbar.vue +++ b/layout-webapp/src/main/webapp/vue-app/layout-editor/components/toolbar/Toolbar.vue @@ -55,6 +55,9 @@ export default { }, }, computed: { + defaultLanguage() { + return eXo.env.portal.defaultLanguage; + }, pageName() { return this.nodeLabels?.labels && (this.nodeLabels.labels[eXo.env.portal.language] || this.nodeLabels.labels[this.defaultLanguage]) || this.page?.title; },