Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.

AEM Content Fragments: Links Localization. Part 2 | AEM Community Blog Seeding

Avatar

Administrator

BlogImage.jpg

AEM Content Fragments: Links Localization. Part 2 by Exadel

Abstract

In the previous article, we took a look at how to set up a translation project and correctly configure links rewriting during New Lang copy creation. Now we’re going to look at more cases you might encounter during links localization and how to approach a variety of situations.

AEM’s ‘’DAM Update Language Copy” workflow is being triggered. We’ll have to introduce a new step for this WF to localize the links correctly.

ContentFragmentUpdateLanguageCopyProcess.java:

package com.wcm.site.workflow;

import com.adobe.acs.commons.util.WorkflowHelper;
import com.adobe.acs.commons.util.visitors.TraversalException;
import com.adobe.acs.commons.util.visitors.TreeFilteringResourceVisitor;
import com.adobe.granite.workflow.WorkflowException;
import com.adobe.granite.workflow.WorkflowSession;
import com.adobe.granite.workflow.exec.WorkItem;
import com.adobe.granite.workflow.exec.WorkflowData;
import com.adobe.granite.workflow.exec.WorkflowProcess;
import com.adobe.granite.workflow.metadata.MetaDataMap;
import com.day.cq.dam.commons.util.DamLanguageUtil;
import com.day.cq.wcm.api.PageManagerFactory;
import com.day.cq.wcm.msm.api.LiveRelationshipManager;
import com.wcm.site.util.AssetUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Session;
import java.util.Arrays;

import static com.wcm.site.util.CFMUtils.isContentFragment;
import static com.wcm.site.workflow.WorkflowProcessBase.WORKFLOW_PROCESS_LABEL;

@Component(immediate = true, service = WorkflowProcess.class, property = {
WORKFLOW_PROCESS_LABEL + "=Site.com Content Fragment Update Language Copy" })
public class ContentFragmentUpdateLanguageCopyProcess extends WorkflowProcessBase implements WorkflowProcess {
private static final Logger LOG = LoggerFactory.getLogger(ContentFragmentUpdateLanguageCopyProcess.class);
private static final String TRANSLATE_LANGUAGES_KEY_NAME = "translateLanguages";

@Reference
private WorkflowHelper workflowHelper;

@Reference
private PageManagerFactory pageManagerFactory;

@Reference
private LiveRelationshipManager liveRelationshipManager;

@Override
public void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap metaData) throws WorkflowException {
ResourceResolver resourceResolver = getResourceResolver(workflowHelper, workflowSession);
String sourcePath = getTargetPath(workItem, true);
Resource source = resourceResolver.getResource(sourcePath);
WorkflowData data = workItem.getWorkflowData();
MetaDataMap metaDataMap = data.getMetaDataMap();

if (AssetUtils.isFolder(source)) {
processFolder(workItem, workflowSession, source, metaDataMap);
workflowSession.terminateWorkflow(workItem.getWorkflow());
return;
}

if (source == null || !isContentFragment(source)) {
LOG.error("Resource not found or not content fragment {}", sourcePath);
return;
}

String updateLanguages = metaDataMap.get(TRANSLATE_LANGUAGES_KEY_NAME, StringUtils.EMPTY);
if (StringUtils.isEmpty(updateLanguages)) {
LOG.error("Update languages list is empty, exiting");
return;
}
String[] updateLanguagesArr = StringUtils.split(updateLanguages, ";");

Arrays.stream(updateLanguagesArr).forEach(language ->
DamLanguageUtil.replaceUpdatedAsset(sourcePath,
getTargetLanguageCopyPath(sourcePath, language, resourceResolver, null),
resourceResolver.adaptTo(Session.class),
pageManagerFactory,
resourceResolver

)
);
}


private void processFolder(WorkItem workItem, WorkflowSession workflowSession, Resource source, MetaDataMap metaData) {
try {
TreeFilteringResourceVisitor cfVisitor = new TreeFilteringResourceVisitor();
cfVisitor.setTraversalFilter(resource -> cfVisitor.isFolder(resource) || isContentFragment(resource));
cfVisitor.setResourceVisitor((resource, level) -> {
if (isContentFragment(resource)) {
startWorkflow(workflowSession, workItem.getWorkflow().getWorkflowModel().getId(), resource.getPath(), metaData);
}
});

cfVisitor.accept(source);
} catch (TraversalException e) {
LOG.error("Exception", e);
}
}


public static Resource getTargetLanguageCopyResource(String sourcePath, String language, ResourceResolver resolver) {
return Optional.ofNullable(DamLanguageUtil.getLanguageCopy(sourcePath, language, resolver))
.map(asset -> asset.adaptTo(Resource.class))
.orElse(null);
}

public static String getTargetLanguageCopyPath(String sourcePath, String language, ResourceResolver resolver, String fallback) {
if (isFolder(resolver.getResource(sourcePath))) {
PathContext context = new PathContext(sourcePath);
String targetPath = StringUtils.removeEnd(context.getPathWithLocale(language), "/");
return resolver.getResource(targetPath) != null ? targetPath : fallback;
}
return Optional.ofNullable(getTargetLanguageCopyResource(sourcePath, language, resolver))
.map(Resource::getPath)
.orElse(fallback);
}


}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package com.wcm.site.workflow;

import com.adobe.acs.commons.util.WorkflowHelper;
import com.adobe.acs.commons.util.visitors.TraversalException;
import com.adobe.acs.commons.util.visitors.TreeFilteringResourceVisitor;
import com.adobe.granite.workflow.WorkflowException;
import com.adobe.granite.workflow.WorkflowSession;
import com.adobe.granite.workflow.exec.WorkItem;
import com.adobe.granite.workflow.exec.WorkflowData;
import com.adobe.granite.workflow.exec.WorkflowProcess;
import com.adobe.granite.workflow.metadata.MetaDataMap;
import com.day.cq.dam.commons.util.DamLanguageUtil;
import com.day.cq.wcm.api.PageManagerFactory;
import com.day.cq.wcm.msm.api.LiveRelationshipManager;
import com.wcm.site.util.AssetUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Session;
import java.util.Arrays;

import static com.wcm.site.util.CFMUtils.isContentFragment;
import static com.wcm.site.workflow.WorkflowProcessBase.WORKFLOW_PROCESS_LABEL;

@Component(immediate = true, service = WorkflowProcess.class, property = {
WORKFLOW_PROCESS_LABEL + "=Site.com Content Fragment Update Language Copy" })
public class ContentFragmentUpdateLanguageCopyProcess extends WorkflowProcessBase implements WorkflowProcess {
private static final Logger LOG = LoggerFactory.getLogger(ContentFragmentUpdateLanguageCopyProcess.class);
private static final String TRANSLATE_LANGUAGES_KEY_NAME = "translateLanguages";

@Reference
private WorkflowHelper workflowHelper;

@Reference
private PageManagerFactory pageManagerFactory;

@Reference
private LiveRelationshipManager liveRelationshipManager;

@Override
public void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap metaData) throws WorkflowException {
ResourceResolver resourceResolver = getResourceResolver(workflowHelper, workflowSession);
String sourcePath = getTargetPath(workItem, true);
Resource source = resourceResolver.getResource(sourcePath);
WorkflowData data = workItem.getWorkflowData();
MetaDataMap metaDataMap = data.getMetaDataMap();

if (AssetUtils.isFolder(source)) {
processFolder(workItem, workflowSession, source, metaDataMap);
workflowSession.terminateWorkflow(workItem.getWorkflow());
return;
}

if (source == null || !isContentFragment(source)) {
LOG.error("Resource not found or not content fragment {}", sourcePath);
return;
}

String updateLanguages = metaDataMap.get(TRANSLATE_LANGUAGES_KEY_NAME, StringUtils.EMPTY);
if (StringUtils.isEmpty(updateLanguages)) {
LOG.error("Update languages list is empty, exiting");
return;
}
String[] updateLanguagesArr = StringUtils.split(updateLanguages, ";");

Arrays.stream(updateLanguagesArr).forEach(language ->
DamLanguageUtil.replaceUpdatedAsset(sourcePath,
getTargetLanguageCopyPath(sourcePath, language, resourceResolver, null),
resourceResolver.adaptTo(Session.class),
pageManagerFactory,
resourceResolver

)
);
}


private void processFolder(WorkItem workItem, WorkflowSession workflowSession, Resource source, MetaDataMap metaData) {
try {
TreeFilteringResourceVisitor cfVisitor = new TreeFilteringResourceVisitor();
cfVisitor.setTraversalFilter(resource -> cfVisitor.isFolder(resource) || isContentFragment(resource));
cfVisitor.setResourceVisitor((resource, level) -> {
if (isContentFragment(resource)) {
startWorkflow(workflowSession, workItem.getWorkflow().getWorkflowModel().getId(), resource.getPath(), metaData);
}
});

cfVisitor.accept(source);
} catch (TraversalException e) {
LOG.error("Exception", e);
}
}


public static Resource getTargetLanguageCopyResource(String sourcePath, String language, ResourceResolver resolver) {
return Optional.ofNullable(DamLanguageUtil.getLanguageCopy(sourcePath, language, resolver))
.map(asset -> asset.adaptTo(Resource.class))
.orElse(null);
}

public static String getTargetLanguageCopyPath(String sourcePath, String language, ResourceResolver resolver, String fallback) {
if (isFolder(resolver.getResource(sourcePath))) {
PathContext context = new PathContext(sourcePath);
String targetPath = StringUtils.removeEnd(context.getPathWithLocale(language), "/");
return resolver.getResource(targetPath) != null ? targetPath : fallback;
}
return Optional.ofNullable(getTargetLanguageCopyResource(sourcePath, language, resolver))
.map(Resource::getPath)
.orElse(fallback);
}


}

Read Full Blog

AEM Content Fragments: Links Localization. Part 2

Q&A

Please use this thread to ask the related questions.



Kautuk Sahni
0 Replies