Your achievements

Level 1

0% to

Level 2

Tip /
Sign in

Sign in to Community

to gain points, level up, and earn exciting badges like the new
Bedrock Mission!

Learn more

View all

Sign in to view all badges

Adobe Summit 2023 [19th to 23rd March, Las Vegas and Virtual] | Complete AEM Session & Lab list

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.

0 Replies