001
014
015 package com.liferay.portal.util;
016
017 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
018 import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
019 import com.liferay.portal.kernel.json.JSONObject;
020 import com.liferay.portal.kernel.language.LanguageUtil;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.util.LocaleUtil;
024 import com.liferay.portal.kernel.util.Localization;
025 import com.liferay.portal.kernel.util.ParamUtil;
026 import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
027 import com.liferay.portal.kernel.util.PrefsParamUtil;
028 import com.liferay.portal.kernel.util.StringPool;
029 import com.liferay.portal.kernel.util.StringUtil;
030 import com.liferay.portal.kernel.util.Tuple;
031 import com.liferay.portal.kernel.util.Validator;
032
033 import java.util.HashMap;
034 import java.util.Locale;
035 import java.util.Map;
036
037 import javax.portlet.PortletPreferences;
038 import javax.portlet.PortletRequest;
039
040 import javax.xml.stream.XMLInputFactory;
041 import javax.xml.stream.XMLOutputFactory;
042 import javax.xml.stream.XMLStreamConstants;
043 import javax.xml.stream.XMLStreamException;
044 import javax.xml.stream.XMLStreamReader;
045 import javax.xml.stream.XMLStreamWriter;
046
047 import org.apache.commons.collections.map.ReferenceMap;
048
049
057 public class LocalizationImpl implements Localization {
058
059 public Object deserialize(JSONObject jsonObject) {
060 Locale[] locales = LanguageUtil.getAvailableLocales();
061
062 Map<Locale, String> map = new HashMap<Locale, String>();
063
064 for (Locale locale : locales) {
065 String languageId = LocaleUtil.toLanguageId(locale);
066
067 String value = jsonObject.getString(languageId);
068
069 if (Validator.isNotNull(value)) {
070 map.put(locale, value);
071 }
072 }
073
074 return map;
075 }
076
077 public String[] getAvailableLocales(String xml) {
078 String attributeValue = _getRootAttribute(
079 xml, _AVAILABLE_LOCALES, StringPool.BLANK);
080
081 return StringUtil.split(attributeValue);
082 }
083
084 public String getDefaultLocale(String xml) {
085 String defaultLanguageId = LocaleUtil.toLanguageId(
086 LocaleUtil.getDefault());
087
088 return _getRootAttribute(xml, _DEFAULT_LOCALE, defaultLanguageId);
089 }
090
091 public String getLocalization(String xml, String requestedLanguageId) {
092 return getLocalization(xml, requestedLanguageId, true);
093 }
094
095 public String getLocalization(
096 String xml, String requestedLanguageId, boolean useDefault) {
097
098 String value = _getCachedValue(xml, requestedLanguageId, useDefault);
099
100 if (value != null) {
101 return value;
102 }
103 else {
104 value = StringPool.BLANK;
105 }
106
107 String systemDefaultLanguageId = LocaleUtil.toLanguageId(
108 LocaleUtil.getDefault());
109
110 String priorityLanguageId = null;
111
112 Locale requestedLocale = LocaleUtil.fromLanguageId(requestedLanguageId);
113
114 if (useDefault && LanguageUtil.isDuplicateLanguageCode(
115 requestedLocale.getLanguage())) {
116
117 Locale priorityLocale = LanguageUtil.getLocale(
118 requestedLocale.getLanguage());
119
120 if (!requestedLanguageId.equals(priorityLanguageId)) {
121 priorityLanguageId = LocaleUtil.toLanguageId(priorityLocale);
122 }
123 }
124
125 if (!Validator.isXml(xml)) {
126 if (useDefault ||
127 requestedLanguageId.equals(systemDefaultLanguageId)) {
128
129 value = xml;
130 }
131
132 _setCachedValue(xml, requestedLanguageId, useDefault, value);
133
134 return value;
135 }
136
137 XMLStreamReader xmlStreamReader = null;
138
139 ClassLoader portalClassLoader = PortalClassLoaderUtil.getClassLoader();
140
141 Thread currentThread = Thread.currentThread();
142
143 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
144
145 try {
146 if (contextClassLoader != portalClassLoader) {
147 currentThread.setContextClassLoader(portalClassLoader);
148 }
149
150 XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
151
152 xmlStreamReader = xmlInputFactory.createXMLStreamReader(
153 new UnsyncStringReader(xml));
154
155 String defaultLanguageId = StringPool.BLANK;
156
157
158
159 if (xmlStreamReader.hasNext()) {
160 xmlStreamReader.nextTag();
161
162 defaultLanguageId = xmlStreamReader.getAttributeValue(
163 null, _DEFAULT_LOCALE);
164
165 if (Validator.isNull(defaultLanguageId)) {
166 defaultLanguageId = systemDefaultLanguageId;
167 }
168 }
169
170
171
172 String defaultValue = StringPool.BLANK;
173 String priorityValue = StringPool.BLANK;
174
175 while (xmlStreamReader.hasNext()) {
176 int event = xmlStreamReader.next();
177
178 if (event == XMLStreamConstants.START_ELEMENT) {
179 String languageId = xmlStreamReader.getAttributeValue(
180 null, _LANGUAGE_ID);
181
182 if (Validator.isNull(languageId)) {
183 languageId = defaultLanguageId;
184 }
185
186 if (languageId.equals(defaultLanguageId) ||
187 languageId.equals(priorityLanguageId) ||
188 languageId.equals(requestedLanguageId)) {
189
190 while (xmlStreamReader.hasNext()) {
191 event = xmlStreamReader.next();
192
193 if (event == XMLStreamConstants.CHARACTERS ||
194 event == XMLStreamConstants.CDATA) {
195
196 String text = xmlStreamReader.getText();
197
198 if (languageId.equals(defaultLanguageId)) {
199 defaultValue = text;
200 }
201
202 if (languageId.equals(priorityLanguageId)) {
203 priorityValue = text;
204 }
205
206 if (languageId.equals(requestedLanguageId)) {
207 value = text;
208 }
209
210 break;
211 }
212 else if (event == XMLStreamConstants.END_ELEMENT) {
213 break;
214 }
215 }
216
217 if (Validator.isNotNull(value)) {
218 break;
219 }
220 }
221 }
222 else if (event == XMLStreamConstants.END_DOCUMENT) {
223 break;
224 }
225 }
226
227 if (useDefault && Validator.isNotNull(priorityLanguageId) &&
228 Validator.isNull(value) && Validator.isNotNull(priorityValue)) {
229
230 value = priorityValue;
231 }
232
233 if (useDefault && Validator.isNull(value)) {
234 value = defaultValue;
235 }
236 }
237 catch (Exception e) {
238 if (_log.isWarnEnabled()) {
239 _log.warn(e, e);
240 }
241 }
242 finally {
243 if (contextClassLoader != portalClassLoader) {
244 currentThread.setContextClassLoader(contextClassLoader);
245 }
246
247 if (xmlStreamReader != null) {
248 try {
249 xmlStreamReader.close();
250 }
251 catch (Exception e) {
252 }
253 }
254 }
255
256 _setCachedValue(xml, requestedLanguageId, useDefault, value);
257
258 return value;
259 }
260
261 public Map<Locale, String> getLocalizationMap(
262 PortletRequest portletRequest, String parameter) {
263
264 Locale[] locales = LanguageUtil.getAvailableLocales();
265
266 Map<Locale, String> map = new HashMap<Locale, String>();
267
268 for (Locale locale : locales) {
269 String languageId = LocaleUtil.toLanguageId(locale);
270
271 String localeParameter =
272 parameter + StringPool.UNDERLINE + languageId;
273
274 map.put(
275 locale, ParamUtil.getString(portletRequest, localeParameter));
276 }
277
278 return map;
279 }
280
281 public Map<Locale, String> getLocalizationMap(String xml) {
282 Locale[] locales = LanguageUtil.getAvailableLocales();
283
284 Map<Locale, String> map = new HashMap<Locale, String>();
285
286 for (Locale locale : locales) {
287 String languageId = LocaleUtil.toLanguageId(locale);
288
289 map.put(locale, getLocalization(xml, languageId));
290 }
291
292 return map;
293 }
294
295 public String getLocalizationXmlFromPreferences(
296 PortletPreferences preferences, PortletRequest portletRequest,
297 String parameter) {
298
299 String xml = StringPool.BLANK;
300
301 Locale[] locales = LanguageUtil.getAvailableLocales();
302 Locale defaultLocale = LocaleUtil.getDefault();
303 String defaultLanguageId = LocaleUtil.toLanguageId(defaultLocale);
304
305 for (Locale locale : locales) {
306 String languageId = LocaleUtil.toLanguageId(locale);
307
308 String localParameter =
309 parameter + StringPool.UNDERLINE + languageId;
310
311 String value = PrefsParamUtil.getString(
312 preferences, portletRequest, localParameter);
313
314 if (Validator.isNotNull(value)) {
315 xml = updateLocalization(xml, parameter, value ,languageId);
316 }
317 }
318
319 if (Validator.isNull(getLocalization(xml, defaultLanguageId))) {
320 String oldValue = PrefsParamUtil.getString(
321 preferences, portletRequest, parameter);
322
323 if (Validator.isNotNull(oldValue)) {
324 xml = updateLocalization(xml, parameter, oldValue);
325 }
326 }
327
328 return xml;
329 }
330
331 public Map<Locale, String> getLocalizedParameter(
332 PortletRequest portletRequest, String parameter) {
333
334 return getLocalizationMap(portletRequest, parameter);
335 }
336
337 public String getPreferencesValue(
338 PortletPreferences preferences, String key, String languageId) {
339
340 return getPreferencesValue(preferences, key, languageId, true);
341 }
342
343 public String getPreferencesValue(
344 PortletPreferences preferences, String key, String languageId,
345 boolean useDefault) {
346
347 String localizedKey = _getPreferencesKey(key, languageId);
348
349 String value = preferences.getValue(localizedKey, StringPool.BLANK);
350
351 if (useDefault && Validator.isNull(value)) {
352 value = preferences.getValue(key, StringPool.BLANK);
353 }
354
355 return value;
356 }
357
358 public String[] getPreferencesValues(
359 PortletPreferences preferences, String key, String languageId) {
360
361 return getPreferencesValues(preferences, key, languageId, true);
362 }
363
364 public String[] getPreferencesValues(
365 PortletPreferences preferences, String key, String languageId,
366 boolean useDefault) {
367
368 String localizedKey = _getPreferencesKey(key, languageId);
369
370 String[] values = preferences.getValues(localizedKey, new String[0]);
371
372 if (useDefault && Validator.isNull(values)) {
373 values = preferences.getValues(key, new String[0]);
374 }
375
376 return values;
377 }
378
379 public String removeLocalization(
380 String xml, String key, String requestedLanguageId) {
381
382 return removeLocalization(xml, key, requestedLanguageId, false);
383 }
384
385 public String removeLocalization(
386 String xml, String key, String requestedLanguageId, boolean cdata) {
387
388 if (Validator.isNull(xml)) {
389 return StringPool.BLANK;
390 }
391
392 xml = _sanitizeXML(xml);
393
394 String systemDefaultLanguageId = LocaleUtil.toLanguageId(
395 LocaleUtil.getDefault());
396
397 XMLStreamReader xmlStreamReader = null;
398 XMLStreamWriter xmlStreamWriter = null;
399
400 ClassLoader portalClassLoader = PortalClassLoaderUtil.getClassLoader();
401
402 Thread currentThread = Thread.currentThread();
403
404 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
405
406 try {
407 if (contextClassLoader != portalClassLoader) {
408 currentThread.setContextClassLoader(portalClassLoader);
409 }
410
411 XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
412
413 xmlStreamReader = xmlInputFactory.createXMLStreamReader(
414 new UnsyncStringReader(xml));
415
416 String availableLocales = StringPool.BLANK;
417 String defaultLanguageId = StringPool.BLANK;
418
419
420
421 if (xmlStreamReader.hasNext()) {
422 xmlStreamReader.nextTag();
423
424 availableLocales = xmlStreamReader.getAttributeValue(
425 null, _AVAILABLE_LOCALES);
426 defaultLanguageId = xmlStreamReader.getAttributeValue(
427 null, _DEFAULT_LOCALE);
428
429 if (Validator.isNull(defaultLanguageId)) {
430 defaultLanguageId = systemDefaultLanguageId;
431 }
432 }
433
434 if ((availableLocales != null) &&
435 (availableLocales.indexOf(requestedLanguageId) != -1)) {
436
437 availableLocales = StringUtil.remove(
438 availableLocales, requestedLanguageId, StringPool.COMMA);
439
440 UnsyncStringWriter unsyncStringWriter =
441 new UnsyncStringWriter();
442
443 XMLOutputFactory xmlOutputFactory =
444 XMLOutputFactory.newInstance();
445
446 xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(
447 unsyncStringWriter);
448
449 xmlStreamWriter.writeStartDocument();
450 xmlStreamWriter.writeStartElement(_ROOT);
451 xmlStreamWriter.writeAttribute(
452 _AVAILABLE_LOCALES, availableLocales);
453 xmlStreamWriter.writeAttribute(
454 _DEFAULT_LOCALE, defaultLanguageId);
455
456 _copyNonExempt(
457 xmlStreamReader, xmlStreamWriter, requestedLanguageId,
458 defaultLanguageId, cdata);
459
460 xmlStreamWriter.writeEndElement();
461 xmlStreamWriter.writeEndDocument();
462
463 xmlStreamWriter.close();
464 xmlStreamWriter = null;
465
466 xml = unsyncStringWriter.toString();
467 }
468 }
469 catch (Exception e) {
470 if (_log.isWarnEnabled()) {
471 _log.warn(e, e);
472 }
473 }
474 finally {
475 if (contextClassLoader != portalClassLoader) {
476 currentThread.setContextClassLoader(contextClassLoader);
477 }
478
479 if (xmlStreamReader != null) {
480 try {
481 xmlStreamReader.close();
482 }
483 catch (Exception e) {
484 }
485 }
486
487 if (xmlStreamWriter != null) {
488 try {
489 xmlStreamWriter.close();
490 }
491 catch (Exception e) {
492 }
493 }
494 }
495
496 return xml;
497 }
498
499 public void setLocalizedPreferencesValues (
500 PortletRequest portletRequest, PortletPreferences preferences,
501 String parameter)
502 throws Exception {
503
504 Map<Locale, String> map = getLocalizationMap(
505 portletRequest, parameter);
506
507 for (Map.Entry<Locale, String> entry : map.entrySet()) {
508 String languageId = LocaleUtil.toLanguageId(entry.getKey());
509 String value = entry.getValue();
510
511 setPreferencesValue(preferences, parameter, languageId, value);
512 }
513 }
514
515 public void setPreferencesValue(
516 PortletPreferences preferences, String key, String languageId,
517 String value)
518 throws Exception {
519
520 preferences.setValue(_getPreferencesKey(key, languageId), value);
521 }
522
523 public void setPreferencesValues(
524 PortletPreferences preferences, String key, String languageId,
525 String[] values)
526 throws Exception {
527
528 preferences.setValues(_getPreferencesKey(key, languageId), values);
529 }
530
531 public String updateLocalization(String xml, String key, String value) {
532 String defaultLanguageId = LocaleUtil.toLanguageId(
533 LocaleUtil.getDefault());
534
535 return updateLocalization(
536 xml, key, value, defaultLanguageId, defaultLanguageId);
537 }
538
539 public String updateLocalization(
540 String xml, String key, String value, String requestedLanguageId) {
541
542 String defaultLanguageId = LocaleUtil.toLanguageId(
543 LocaleUtil.getDefault());
544
545 return updateLocalization(
546 xml, key, value, requestedLanguageId, defaultLanguageId);
547 }
548
549 public String updateLocalization(
550 String xml, String key, String value, String requestedLanguageId,
551 String defaultLanguageId) {
552
553 return updateLocalization(
554 xml, key, value, requestedLanguageId, defaultLanguageId, false);
555 }
556
557 public String updateLocalization(
558 String xml, String key, String value, String requestedLanguageId,
559 String defaultLanguageId, boolean cdata) {
560
561 xml = _sanitizeXML(xml);
562
563 XMLStreamReader xmlStreamReader = null;
564 XMLStreamWriter xmlStreamWriter = null;
565
566 ClassLoader portalClassLoader = PortalClassLoaderUtil.getClassLoader();
567
568 Thread currentThread = Thread.currentThread();
569
570 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
571
572 try {
573 if (contextClassLoader != portalClassLoader) {
574 currentThread.setContextClassLoader(portalClassLoader);
575 }
576
577 XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
578
579 xmlStreamReader = xmlInputFactory.createXMLStreamReader(
580 new UnsyncStringReader(xml));
581
582 String availableLocales = StringPool.BLANK;
583
584
585
586 if (xmlStreamReader.hasNext()) {
587 xmlStreamReader.nextTag();
588
589 availableLocales = xmlStreamReader.getAttributeValue(
590 null, _AVAILABLE_LOCALES);
591
592 if (Validator.isNull(availableLocales)) {
593 availableLocales = defaultLanguageId;
594 }
595
596 if (availableLocales.indexOf(requestedLanguageId) == -1) {
597 availableLocales = StringUtil.add(
598 availableLocales, requestedLanguageId,
599 StringPool.COMMA);
600 }
601 }
602
603 UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
604
605 XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
606
607 xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(
608 unsyncStringWriter);
609
610 xmlStreamWriter.writeStartDocument();
611 xmlStreamWriter.writeStartElement(_ROOT);
612 xmlStreamWriter.writeAttribute(
613 _AVAILABLE_LOCALES, availableLocales);
614 xmlStreamWriter.writeAttribute(_DEFAULT_LOCALE, defaultLanguageId);
615
616 _copyNonExempt(
617 xmlStreamReader, xmlStreamWriter, requestedLanguageId,
618 defaultLanguageId, cdata);
619
620 if (cdata) {
621 xmlStreamWriter.writeStartElement(key);
622 xmlStreamWriter.writeAttribute(
623 _LANGUAGE_ID, requestedLanguageId);
624 xmlStreamWriter.writeCData(value);
625 xmlStreamWriter.writeEndElement();
626 }
627 else {
628 xmlStreamWriter.writeStartElement(key);
629 xmlStreamWriter.writeAttribute(
630 _LANGUAGE_ID, requestedLanguageId);
631 xmlStreamWriter.writeCharacters(value);
632 xmlStreamWriter.writeEndElement();
633 }
634
635 xmlStreamWriter.writeEndElement();
636 xmlStreamWriter.writeEndDocument();
637
638 xmlStreamWriter.close();
639 xmlStreamWriter = null;
640
641 xml = unsyncStringWriter.toString();
642 }
643 catch (Exception e) {
644 if (_log.isWarnEnabled()) {
645 _log.warn(e, e);
646 }
647 }
648 finally {
649 if (contextClassLoader != portalClassLoader) {
650 currentThread.setContextClassLoader(contextClassLoader);
651 }
652
653 if (xmlStreamReader != null) {
654 try {
655 xmlStreamReader.close();
656 }
657 catch (Exception e) {
658 }
659 }
660
661 if (xmlStreamWriter != null) {
662 try {
663 xmlStreamWriter.close();
664 }
665 catch (Exception e) {
666 }
667 }
668 }
669
670 return xml;
671 }
672
673 private void _copyNonExempt(
674 XMLStreamReader xmlStreamReader, XMLStreamWriter xmlStreamWriter,
675 String exemptLanguageId, String defaultLanguageId, boolean cdata)
676 throws XMLStreamException {
677
678 while (xmlStreamReader.hasNext()) {
679 int event = xmlStreamReader.next();
680
681 if (event == XMLStreamConstants.START_ELEMENT) {
682 String languageId = xmlStreamReader.getAttributeValue(
683 null, _LANGUAGE_ID);
684
685 if (Validator.isNull(languageId)) {
686 languageId = defaultLanguageId;
687 }
688
689 if (!languageId.equals(exemptLanguageId)) {
690 xmlStreamWriter.writeStartElement(
691 xmlStreamReader.getLocalName());
692 xmlStreamWriter.writeAttribute(_LANGUAGE_ID, languageId);
693
694 while (xmlStreamReader.hasNext()) {
695 event = xmlStreamReader.next();
696
697 if (event == XMLStreamConstants.CHARACTERS ||
698 event == XMLStreamConstants.CDATA) {
699
700 String text = xmlStreamReader.getText();
701
702 if (cdata) {
703 xmlStreamWriter.writeCData(text);
704 }
705 else {
706 xmlStreamWriter.writeCharacters(
707 xmlStreamReader.getText());
708 }
709
710 break;
711 }
712 else if (event == XMLStreamConstants.END_ELEMENT) {
713 break;
714 }
715 }
716
717 xmlStreamWriter.writeEndElement();
718 }
719 }
720 else if (event == XMLStreamConstants.END_DOCUMENT) {
721 break;
722 }
723 }
724 }
725
726 private String _getCachedValue(
727 String xml, String requestedLanguageId, boolean useDefault) {
728
729 String value = null;
730
731 Map<Tuple, String> valueMap = _cache.get(xml);
732
733 if (valueMap != null) {
734 Tuple subkey = new Tuple(useDefault, requestedLanguageId);
735
736 value = valueMap.get(subkey);
737 }
738
739 return value;
740 }
741
742 private String _getPreferencesKey(String key, String languageId) {
743 String defaultLanguageId = LocaleUtil.toLanguageId(
744 LocaleUtil.getDefault());
745
746 if (!languageId.equals(defaultLanguageId)) {
747 key += StringPool.UNDERLINE + languageId;
748 }
749
750 return key;
751 }
752
753 private String _getRootAttribute(
754 String xml, String name, String defaultValue) {
755
756 String value = null;
757
758 XMLStreamReader xmlStreamReader = null;
759
760 ClassLoader portalClassLoader = PortalClassLoaderUtil.getClassLoader();
761
762 Thread currentThread = Thread.currentThread();
763
764 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
765
766 try {
767 if (contextClassLoader != portalClassLoader) {
768 currentThread.setContextClassLoader(portalClassLoader);
769 }
770
771 XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
772
773 xmlStreamReader = xmlInputFactory.createXMLStreamReader(
774 new UnsyncStringReader(xml));
775
776 if (xmlStreamReader.hasNext()) {
777 xmlStreamReader.nextTag();
778
779 value = xmlStreamReader.getAttributeValue(null, name);
780 }
781 }
782 catch (Exception e) {
783 if (_log.isWarnEnabled()) {
784 _log.warn(e, e);
785 }
786 }
787 finally {
788 if (contextClassLoader != portalClassLoader) {
789 currentThread.setContextClassLoader(contextClassLoader);
790 }
791
792 if (xmlStreamReader != null) {
793 try {
794 xmlStreamReader.close();
795 }
796 catch (Exception e) {
797 }
798 }
799 }
800
801 if (Validator.isNull(value)) {
802 value = defaultValue;
803 }
804
805 return value;
806 }
807
808 private String _sanitizeXML(String xml) {
809 if (Validator.isNull(xml) || (xml.indexOf("<root") == -1)) {
810 xml = _EMPTY_ROOT_NODE;
811 }
812
813 return xml;
814 }
815
816 private void _setCachedValue(
817 String xml, String requestedLanguageId, boolean useDefault,
818 String value) {
819
820 if (Validator.isNotNull(xml) && !xml.equals(_EMPTY_ROOT_NODE)) {
821 synchronized (_cache) {
822 Map<Tuple, String> map = _cache.get(xml);
823
824 if (map == null) {
825 map = new HashMap<Tuple, String>();
826 }
827
828 Tuple subkey = new Tuple(useDefault, requestedLanguageId);
829
830 map.put(subkey, value);
831
832 _cache.put(xml, map);
833 }
834 }
835 }
836
837 private static final String _AVAILABLE_LOCALES = "available-locales";
838
839 private static final String _DEFAULT_LOCALE = "default-locale";
840
841 private static final String _EMPTY_ROOT_NODE = "<root />";
842
843 private static final String _LANGUAGE_ID = "language-id";
844
845 private static final String _ROOT = "root";
846
847 private static Log _log = LogFactoryUtil.getLog(LocalizationImpl.class);
848
849 private Map<String, Map<Tuple, String>> _cache = new ReferenceMap(
850 ReferenceMap.SOFT, ReferenceMap.HARD);
851
852 }