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 public abstract class AbstractI18n implements I18n
52 {
53 /*** undefinied value. */
54 public static final String DEFAULT_UNDEFINED_VALUE = "[?]";
55
56 /*** default locale. */
57 public static final String DEFAULT_LOCALE = "en_US";
58
59 /*** default locale. */
60 public static final String PREFERED_LOCALE = "en_US";
61
62 /*** default setting for locale defaulting. */
63 public static final boolean DEFAULT_USE_DEFAULT_LOCALE = true;
64
65 /*** default setting for using key as undefinied value. */
66 public static final boolean DEFAULT_USE_KEY_IF_UNDEFINED = true;
67
68 /*** logger. */
69 protected Logger logger;
70
71 /*** string returned when a key has no defined value */
72 private String undefinedValue;
73
74 /*** default locale */
75 private Locale defaultLocale;
76
77 /*** prefered locale */
78 private Locale preferedLocale;
79
80 /*** use default locale */
81 private boolean useDefaultLocale;
82
83 /*** use key if undefined switch */
84 private boolean useKeyIfUndefined;
85
86 /*** the localization bundles map. */
87 protected Map<String, Map<String, String>> localeMap;
88
89 /*** supported locale. */
90 protected Locale[] supportedLocales;
91
92 /*** names of the supported locales. */
93 protected Map<Locale,String> localeNames = new HashMap<Locale,String>();
94
95 /***
96 * Component constructor.
97 *
98 * @param config the configuration.
99 * @param logger the logger.
100 * @throws ConfigurationException if the component configutation is malformed.
101 */
102 public AbstractI18n(Configuration config, Logger logger)
103 throws ConfigurationException
104 {
105 this.logger = logger;
106 undefinedValue = config.getChild("undefined-value-marker").
107 getValue(DEFAULT_UNDEFINED_VALUE);
108 useDefaultLocale = config.getChild("default-locale-fallback").
109 getAttributeAsBoolean("enabled", DEFAULT_USE_DEFAULT_LOCALE);
110 useKeyIfUndefined = config.getChild("key-fallback").
111 getAttributeAsBoolean("enabled", DEFAULT_USE_KEY_IF_UNDEFINED);
112 localeMap = new HashMap<String, Map<String, String>>();
113
114 if(config.getChild("supported-locales", false) != null)
115 {
116 Configuration[] locales = config.getChild("supported-locales").getChildren();
117 supportedLocales = new Locale[locales.length];
118 for(int i=0; i<locales.length; i++)
119 {
120 supportedLocales[i] = StringUtils.getLocale(locales[i].getValue());
121 if(locales[i].getAttributeAsBoolean("default", false))
122 {
123 defaultLocale = supportedLocales[i];
124 }
125 if(locales[i].getAttributeAsBoolean("prefered", false))
126 {
127 preferedLocale = supportedLocales[i];
128 }
129 String localeName = locales[i].getAttribute("name", locales[i].getValue());
130 localeNames.put(supportedLocales[i], localeName);
131 }
132 if(defaultLocale == null && supportedLocales.length > 0)
133 {
134 defaultLocale = supportedLocales[0];
135 }
136 if(preferedLocale == null)
137 {
138 preferedLocale = defaultLocale;
139 }
140 }
141 else
142 {
143 supportedLocales = new Locale[]{ StringUtils.getLocale(DEFAULT_LOCALE) };
144 defaultLocale = StringUtils.getLocale(DEFAULT_LOCALE);
145 preferedLocale = StringUtils.getLocale(PREFERED_LOCALE);
146 }
147 }
148
149 /***
150 * {@inheritDoc}
151 */
152 public Locale getDefaultLocale()
153 {
154 return defaultLocale;
155 }
156
157 /***
158 * {@inheritDoc}
159 */
160 public Locale getPreferedLocale()
161 {
162 return preferedLocale;
163 }
164
165 /***
166 * {@inheritDoc}
167 */
168 public Locale[] getSupportedLocales()
169 {
170 return supportedLocales;
171 }
172
173 /***
174 * {@inheritDoc}
175 */
176 public String getLocaleName(Locale locale)
177 {
178 return (String)localeNames.get(locale);
179 }
180
181 /***
182 * {@inheritDoc}
183 */
184 public boolean defined(Locale locale, String key)
185 {
186 String value = getInternal(locale, key);
187 return value != null;
188 }
189 /***
190 * {@inheritDoc}
191 */
192 public boolean defined(String key)
193 {
194 return defined(this.defaultLocale, key);
195 }
196
197 /***
198 * {@inheritDoc}
199 */
200 public String get(Locale locale, String key)
201 {
202 String value = getInternal(locale, key);
203 if(value == null)
204 {
205 value = useKeyIfUndefined ? key : undefinedValue;
206 }
207 return value;
208 }
209
210 /***
211 * {@inheritDoc}
212 */
213 public String get(Locale locale, String key, String defaultValue)
214 {
215 String value = getInternal(locale, key);
216 if(value == null)
217 {
218 value = defaultValue;
219 }
220 return value;
221 }
222
223 /***
224 * {@inheritDoc}
225 */
226 protected String getInternal(Locale locale, String key)
227 {
228 String value = null;
229
230 Map bundle = (Map)localeMap.get(locale.toString());
231 if(bundle != null)
232 {
233 value = (String)bundle.get(key);
234 if(value != null)
235 {
236 return value;
237 }
238 if(locale.equals(defaultLocale) || !useDefaultLocale)
239 {
240 return null;
241 }
242 }
243
244 bundle = (Map)localeMap.get(defaultLocale.toString());
245 if(bundle != null)
246 {
247 value = (String)bundle.get(key);
248 }
249 return value;
250 }
251
252 /***
253 * {@inheritDoc}
254 */
255 public Collection<String> getKeys(Locale locale)
256 {
257 Map<String, String> bundle = localeMap.get(locale.toString());
258 if(bundle != null)
259 {
260 return bundle.keySet();
261 }
262 return new HashSet<String>();
263 }
264
265 /***
266 * {@inheritDoc}
267 */
268 public String get(Locale locale, String key, String ... values)
269 {
270 String template = get(locale, key);
271 return StringUtils.substitute(template, values);
272 }
273
274 /***
275 * {@inheritDoc}
276 */
277 public String get(Locale locale, String key, List<String> values)
278 {
279 String[] strValues = new String[values.size()];
280 values.toArray(strValues);
281 return get(locale, key, strValues);
282 }
283
284 /***
285 * {@inheritDoc}
286 */
287 public abstract void reload();
288 }