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