source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/Dictionary.java@ 36592

Last change on this file since 36592 was 36592, checked in by kjdon, 20 months ago

modified Dictionary, so that if a lang fragment starts with [PENDING], then don't use it. This is to allow the addition of old strings which will help the translators, but which are too out of date to display in the interface. OTher classes use of Dictionary modified so that they go through getTextString, or createDictionaryAndGetString, thereby benifitting from the pending stuff

  • Property svn:keywords set to Author Date Id Revision
File size: 9.9 KB
Line 
1/*
2 * Dictionary.java
3 * Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19package org.greenstone.gsdl3.util;
20
21import java.util.ResourceBundle;
22import java.util.Locale;
23import java.util.Enumeration;
24
25import org.apache.log4j.*;
26
27public class Dictionary
28{
29
30 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.Dictionary.class.getName());
31
32 /** The default servlet dictionary */
33 public static final String core_servlet_dictionary_name = "core_servlet_dictionary";
34 /** Fallback language */
35 protected static final String fallback_language = "en";
36 /** THe string to mark a value as awaiting translator input */
37 public static final String PENDING_STR = "[PENDING]";
38 /** The locale of this dictionary. */
39 protected Locale locale = null;
40
41 /** The resource that has been loaded */
42 protected String resource = null;
43
44 /**
45 * The ResourceBundle which contains the raw key-value mappings. Loaded from
46 * a file named "resource_locale.properties
47 */
48 private ResourceBundle raw = null;
49
50 /**
51 * Constructs the Dictionary class by first creating a locale from the
52 * specified language, (or using the default locale if this didn't work),
53 * then loading a resource bundle based on this locale.
54 */
55 public Dictionary(String resource, String lang)
56 {
57 // Initialize.
58
59 this.locale = new Locale(lang);
60 this.resource = resource;
61 if (this.locale == null)
62 {
63 this.locale = Locale.getDefault();
64 }
65 try
66 {
67 this.raw = ResourceBundle.getBundle(this.resource, this.locale, new UTF8Control());
68 }
69 catch (Exception e)
70 {
71 //logger.debug("Dictionary: couldn't locate a resource bundle for "+resource);
72 }
73 }
74
75 public Dictionary(String resource, Locale locale)
76 {
77 this.locale = locale;
78 this.resource = resource;
79 try
80 {
81 this.raw = ResourceBundle.getBundle(this.resource, this.locale, new UTF8Control());
82 }
83 catch (Exception e)
84 {
85 //logger.debug("Dictionary: couldn't locate a resource bundle for "+resource);
86 }
87 }
88
89 /**
90 * Constructs the Dictionary class by first creating a locale from the
91 * specified language, (or using the default locale if this didn't work),
92 * then loading a resource bundle based on this locale. A classloader is
93 * specified which can be used to find the resource.
94 */
95 public Dictionary(String resource, String lang, ClassLoader loader)
96 {
97 // Initialize.
98 this.locale = new Locale(lang);
99 this.resource = resource;
100 if (this.locale == null)
101 {
102 this.locale = Locale.getDefault();
103 }
104 // try the specified class loader
105 if (loader != null) {
106 try
107 {
108 this.raw = ResourceBundle.getBundle(this.resource, this.locale, loader, new UTF8Control());
109 return;
110 }
111 catch (Exception e)
112 {
113 }
114 }
115
116 // try with default class loader
117 try
118 {
119 this.raw = ResourceBundle.getBundle(this.resource, this.locale, new UTF8Control());
120 }
121 catch (Exception ex)
122 {
123 //logger.debug("Dictionary: couldn't locate a resource bundle for "+resource);
124 }
125 }
126
127 public Enumeration<String> getKeys()
128 {
129 if (this.raw != null)
130 {
131 return this.raw.getKeys();
132 }
133 return null;
134 }
135
136 /**
137 * Overloaded to call get with both a key and an empty argument array.
138 *
139 * @param key
140 * A <strong>String</strong> which is mapped to a initial String
141 * within the ResourceBundle.
142 * @return A <strong>String</strong> which has been referenced by the key
143 * String and that contains no argument fields.
144 */
145 public String get(String key)
146 {
147 return get(key, null);
148 }
149
150 public static String processArgs(String initial, String args[])
151 {
152 // If the string contains arguments we have to insert them.
153 StringBuffer complete = new StringBuffer();
154 // While we still have initial string left.
155 while (initial.length() > 0 && initial.indexOf('{') != -1 && initial.indexOf('}') != -1)
156 {
157 // Remove preamble
158 int opening = initial.indexOf('{');
159 int closing = initial.indexOf('}');
160 int comment_mark = initial.indexOf('-', opening); // May not exist
161 if (comment_mark > closing)
162 { // May also be detecting a later comment
163 comment_mark = -1;
164 }
165 complete.append(initial.substring(0, opening));
166
167 // Parse arg_num
168 String arg_str = null;
169 if (comment_mark != -1)
170 {
171 arg_str = initial.substring(opening + 1, comment_mark);
172 }
173 else
174 {
175 arg_str = initial.substring(opening + 1, closing);
176 }
177 if (closing + 1 < initial.length())
178 {
179 initial = initial.substring(closing + 1);
180 }
181 else
182 {
183 initial = "";
184 }
185 int arg_num = Integer.parseInt(arg_str);
186 // Insert argument
187 if (args != null && 0 <= arg_num && arg_num < args.length)
188 {
189 complete.append(args[arg_num]);
190 }
191 }
192 complete.append(initial);
193 return complete.toString();
194 }
195
196 /**
197 * Used to retrieve a property value from the Locale specific
198 * ResourceBundle, based upon the key and arguments supplied. If the key
199 * cannot be found or if some other part of the call fails a default
200 * (English) error message is returned. <BR>
201 * Here the get recieves a second argument which is an array of Strings used
202 * to populate argument fields, denoted {<I>n</I>}, within the value String
203 * returned.
204 *
205 * @param key
206 * A <strong>String</strong> which is mapped to a initial String
207 * within the ResourceBundle.
208 * @param args
209 * A <strong>String[]</strong> used to populate argument fields
210 * within the complete String.
211 * @return A <strong>String</strong> which has been referenced by the key
212 * String and that either contains no argument fields, or has had
213 * the argument fields populated with argument Strings provided in
214 * the get call.
215 */
216 public String get(String key, String args[])
217 {
218
219 if (this.raw == null)
220 {
221 return null;
222 }
223 try
224 {
225 // In older versions of Java, the resource-bundle/properties file was assumed to be "ISO-8859-1", and so
226 // we used to perform a string conversion here so we could support UTF-8
227 // With the introduction of UTF8Control, based on a StackOverflow posting, we now directly work
228 // with the resource as UTF-8, and so not conversion is needed
229 String initial = this.raw.getString(key);
230 // if we haven't been given any args, don't bother looking for them
231 if (args == null)
232 {
233 return initial;
234 }
235
236 return processArgs(initial,args);
237 }
238 catch (Exception e)
239 {
240 //logger.debug("Dictionary Error: couldn't find string for key:" + key +" in resource "+this.resource);
241 return null;
242 }
243 }
244
245
246 public static String getTextString(String key, String lang, String[] args, String dictionary_name, Class class_obj, String stop_at_class, ClassLoader class_loader)
247 {
248 if (dictionary_name == null && class_obj == null) {
249 // no dictionary or class was specified, just use the default
250 // dictionary
251 dictionary_name = core_servlet_dictionary_name;
252 }
253
254 if (dictionary_name != null)
255 {
256 // just try the one specified dictionary
257 return createDictionaryAndGetString(dictionary_name, class_loader, key, lang, args);
258 }
259
260 // try the class names first before the default dictionary
261 String original_class_name = class_obj.getName();
262 original_class_name = original_class_name.substring(original_class_name.lastIndexOf('.') + 1);
263 String result = createDictionaryAndGetString(original_class_name, class_loader, key, lang, args);
264 if (result != null)
265 {
266 return result;
267 }
268
269 // we have to try super classes
270 String class_name;
271 Class c = class_obj.getSuperclass();
272 while (c != null)
273 {
274 class_name = c.getName();
275 class_name = class_name.substring(class_name.lastIndexOf('.') + 1);
276 if (class_name.equals(stop_at_class))
277 {
278 // this is as far as we go
279 break;
280 }
281 result = createDictionaryAndGetString(class_name, class_loader, key, lang, args);
282 if (result != null) {
283 return result;
284 }
285 c = c.getSuperclass();
286 }
287
288 // if we got here, class names were no help, try the default dictionary
289
290 // First we try the key qualified with the original class name
291 // (eg have TextQuery.name and LuceneSearch.TextQuery.name in the
292 // default properties file)
293 String full_key = original_class_name+"."+key;
294 result = createDictionaryAndGetString(core_servlet_dictionary_name, class_loader, full_key, lang, args);
295 if (result == null) {
296 // try the key by itself without class qualified prefix
297 result = createDictionaryAndGetString(core_servlet_dictionary_name, class_loader, key, lang, args);
298 }
299 return result;
300
301 }
302
303 public static String createDictionaryAndGetString(String dictionary_name, ClassLoader class_loader, String key, String lang, String[] args) {
304 Dictionary dict = new Dictionary(dictionary_name, lang, class_loader);
305 String result = dict.get(key, args);
306 // if we have a pending flag, then try the base language
307 if (result != null && result.startsWith(PENDING_STR) && !lang.equals(fallback_language)) {
308 dict = new Dictionary(dictionary_name, fallback_language, class_loader);
309 result = dict.get(key, args);
310 }
311 return result;
312 }
313
314
315
316}
Note: See TracBrowser for help on using the repository browser.