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.cms.i18n;
35
36 import info.magnolia.cms.core.Content;
37 import info.magnolia.cms.core.NodeData;
38 import info.magnolia.cms.util.NodeDataUtil;
39 import info.magnolia.context.MgnlContext;
40
41 import java.util.Collection;
42 import java.util.HashSet;
43 import java.util.Iterator;
44 import java.util.LinkedHashMap;
45 import java.util.Locale;
46 import java.util.Map;
47 import java.util.Set;
48
49 import javax.jcr.RepositoryException;
50
51 import org.apache.commons.lang.StringUtils;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54
55
56
57
58
59
60
61
62
63
64 public abstract class AbstractI18nContentSupport implements I18nContentSupport {
65
66 private static final Logger log = LoggerFactory.getLogger(AbstractI18nContentSupport.class);
67
68
69
70
71 private Locale fallbackLocale = new Locale("en");
72
73
74
75
76 protected Locale defaultLocale;
77
78 private boolean enabled = false;
79
80
81
82
83 private Map<String, Locale> locales = new LinkedHashMap<String, Locale>();
84
85 public Locale getLocale() {
86 final Locale locale = MgnlContext.getAggregationState().getLocale();
87 if (locale == null) {
88 return fallbackLocale;
89 } else {
90 return locale;
91 }
92 }
93
94 public void setLocale(Locale locale) {
95 MgnlContext.getAggregationState().setLocale(locale);
96 }
97
98 public Locale getFallbackLocale() {
99 return this.fallbackLocale;
100 }
101
102 public void setFallbackLocale(Locale fallbackLocale) {
103 this.fallbackLocale = fallbackLocale;
104 }
105
106
107
108
109
110
111
112
113
114
115 protected Locale getNextLocale(Locale locale) {
116
117 if(StringUtils.isNotEmpty(locale.getCountry())){
118
119 Locale langOnlyLocale = new Locale(locale.getLanguage());
120 if(isLocaleSupported(langOnlyLocale)){
121 return langOnlyLocale;
122 }
123 }
124
125 for (Iterator<Locale> iter = getLocales().iterator(); iter.hasNext();) {
126 Locale otherCountryLocale = iter.next();
127
128 if(locale.getLanguage().equals(otherCountryLocale.getLanguage()) && !locale.equals(otherCountryLocale)){
129 return otherCountryLocale;
130 }
131 }
132 return getFallbackLocale();
133 }
134
135
136
137
138 public Locale determineLocale() {
139 Locale locale;
140
141 locale = onDetermineLocale();
142
143
144 if(locale == null){
145 locale = getDefaultLocale();
146 }
147
148 if(!isLocaleSupported(locale)){
149 locale = getNextLocale(locale);
150 }
151
152
153 if(locale.equals(getFallbackLocale())){
154 locale = getDefaultLocale();
155 }
156 return locale;
157 }
158
159 protected abstract Locale onDetermineLocale();
160
161 protected static Locale determineLocalFromString(String localeStr) {
162 if(StringUtils.isNotEmpty(localeStr)){
163 String[] localeArr = StringUtils.split(localeStr, "_");
164 if(localeArr.length ==1){
165 return new Locale(localeArr[0]);
166 }
167 else if(localeArr.length == 2){
168 return new Locale(localeArr[0],localeArr[1]);
169 }
170 }
171 return null;
172 }
173
174 public String toI18NURI(String uri) {
175 if (!isEnabled()) {
176 return uri;
177 }
178 Locale locale = getLocale();
179 if (isLocaleSupported(locale)) {
180 return toI18NURI(uri, locale);
181 }
182 return uri;
183 }
184
185 protected abstract String toI18NURI(String uri, Locale locale);
186
187
188
189
190 public String toRawURI(String i18nURI) {
191 if (!isEnabled()) {
192 return i18nURI;
193 }
194
195 Locale locale = getLocale();
196 if (isLocaleSupported(locale)) {
197 return toRawURI(i18nURI, locale);
198 }
199 return i18nURI;
200 }
201
202 protected abstract String toRawURI(String i18nURI, Locale locale);
203
204 public NodeData getNodeData(Content node, String name, Locale locale) throws RepositoryException {
205 String nodeDataName = name + "_" + locale;
206 if (node.hasNodeData(nodeDataName)) {
207 return node.getNodeData(nodeDataName);
208 }
209 return null;
210 }
211
212
213
214
215
216 public NodeData getNodeData(Content node, String name) {
217 NodeData nd = null;
218
219 if (isEnabled()) {
220 try {
221
222 Locale locale = getLocale();
223 Set<Locale> checkedLocales = new HashSet<Locale>();
224
225
226 while(locale != null){
227 nd = getNodeData(node, name, locale);
228 if (!isEmpty(nd)) {
229 return nd;
230 }
231 checkedLocales.add(locale);
232 locale = getNextContentLocale(locale, checkedLocales);
233 }
234 }
235 catch (RepositoryException e) {
236 log.error("can't read i18n nodeData " + name + " from node " + node, e);
237 }
238 }
239
240
241 return node.getNodeData(name);
242 }
243
244
245
246
247
248
249 protected Locale getNextContentLocale(Locale locale, Set<Locale> checkedLocales) {
250 if(locale.equals(getFallbackLocale())){
251 return null;
252 }
253 Locale candidate = getNextLocale(locale);
254 if(!checkedLocales.contains(candidate)){
255 return candidate;
256 }
257 return getFallbackLocale();
258 }
259
260 public boolean isEnabled() {
261 return this.enabled;
262 }
263
264 public void setEnabled(boolean enabled) {
265 this.enabled = enabled;
266 }
267
268 public Collection<Locale> getLocales() {
269 return this.locales.values();
270 }
271
272 public void addLocale(LocaleDefinition ld) {
273 if (ld.isEnabled()) {
274 this.locales.put(ld.getId(), ld.getLocale());
275 }
276 }
277
278 protected boolean isLocaleSupported(Locale locale) {
279 return locale != null && locales.containsKey(locale.toString());
280 }
281
282
283
284
285 protected boolean isEmpty(NodeData nd) {
286 if (nd != null && nd.isExist()) {
287
288 return StringUtils.isEmpty(NodeDataUtil.getValueString(nd));
289 }
290 return true;
291 }
292
293 public Locale getDefaultLocale() {
294 if(this.defaultLocale == null){
295 return getFallbackLocale();
296 }
297 return this.defaultLocale;
298 }
299
300 public void setDefaultLocale(Locale defaultLocale) {
301 this.defaultLocale = defaultLocale;
302 }
303 }