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 package info.magnolia.rest.delivery.jcr.i18n;
35
36 import info.magnolia.cms.i18n.I18nContentSupport;
37 import info.magnolia.objectfactory.Components;
38
39 import java.io.IOException;
40 import java.util.List;
41 import java.util.Locale;
42 import java.util.Locale.LanguageRange;
43
44 import javax.ws.rs.BadRequestException;
45 import javax.ws.rs.container.ContainerRequestContext;
46 import javax.ws.rs.container.ContainerRequestFilter;
47 import javax.ws.rs.core.MultivaluedMap;
48 import javax.ws.rs.core.Variant;
49 import javax.ws.rs.ext.Provider;
50
51 import org.apache.commons.collections4.CollectionUtils;
52 import org.apache.commons.lang3.LocaleUtils;
53 import org.apache.commons.lang3.StringUtils;
54
55
56
57
58
59
60 @Provider
61 @I18n
62 public class I18nContainerRequestFilter implements ContainerRequestFilter {
63 private static final String LANGUAGE_PARAM = "lang";
64 private static final String ALL_LANGUAGE_PARAM = "all";
65
66 private final I18nContentSupport i18nContentSupport;
67
68 public I18nContainerRequestFilter() {
69 this.i18nContentSupport = Components.getComponent(I18nContentSupport.class);
70 }
71
72 @Override
73 public void filter(ContainerRequestContext containerRequestContext) throws IOException {
74 if (ALL_LANGUAGE_PARAM.equalsIgnoreCase(containerRequestContext.getUriInfo().getQueryParameters().getFirst(LANGUAGE_PARAM))) {
75 return;
76 }
77 Locale preferredLocale = determineLocaleFromQueryParameter(containerRequestContext.getUriInfo().getQueryParameters());
78 if (preferredLocale == null) {
79 preferredLocale = determineLocaleFromRequest(containerRequestContext);
80 }
81
82 if (preferredLocale != null) {
83 i18nContentSupport.setLocale(preferredLocale);
84 }
85 }
86
87 private Locale determineLocaleFromQueryParameter(MultivaluedMap<String, String> queryParameters) {
88 if (!queryParameters.containsKey(LANGUAGE_PARAM)) {
89 return null;
90 }
91 String localeString = queryParameters.getFirst(LANGUAGE_PARAM);
92
93 if (!isValidLanguageTag(localeString)) {
94 throw new BadRequestException(String.format("Language parameter: %s is not allowed", localeString));
95 }
96 List<LanguageRange> ranges = LanguageRange.parse(localeString);
97 return Locale.lookup(ranges, i18nContentSupport.getLocales());
98 }
99
100 private Locale determineLocaleFromRequest(ContainerRequestContext request) {
101 if (CollectionUtils.isEmpty(i18nContentSupport.getLocales()) || CollectionUtils.isEmpty(request.getAcceptableLanguages())) {
102 return null;
103 }
104
105 List<Variant> variantList = Variant.VariantListBuilder.newInstance().languages(i18nContentSupport.getLocales().toArray(new Locale[] {})).build();
106 Variant bestMatch = request.getRequest().selectVariant(variantList);
107
108 if (bestMatch != null && bestMatch.getLanguage() != null) {
109 return bestMatch.getLanguage();
110 }
111 return null;
112 }
113
114 private boolean isValidLanguageTag(String languageTag) {
115 return StringUtils.isBlank(languageTag) ?
116 false :
117 LocaleUtils.availableLocaleList().stream()
118 .anyMatch(locale -> locale.toLanguageTag().equalsIgnoreCase(languageTag));
119 }
120 }