KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > jforum > util > I18n


1 /*
2  * Copyright (c) Rafael Steil
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms,
6  * with or without modification, are permitted provided
7  * that the following conditions are met:
8  *
9  * 1) Redistributions of source code must retain the above
10  * copyright notice, this list of conditions and the
11  * following disclaimer.
12  * 2) Redistributions in binary form must reproduce the
13  * above copyright notice, this list of conditions and
14  * the following disclaimer in the documentation and/or
15  * other materials provided with the distribution.
16  * 3) Neither the name of "Rafael Steil" nor
17  * the names of its contributors may be used to endorse
18  * or promote products derived from this software without
19  * specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
22  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
23  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
27  * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
32  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
34  * IN CONTRACT, STRICT LIABILITY, OR TORT
35  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
37  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
38  *
39  * This file creation date: Mar 10, 2003 / 9:28:40 PM
40  * The JForum Project
41  * http://www.jforum.net
42  */

43 package net.jforum.util;
44
45 import java.io.FileInputStream JavaDoc;
46 import java.io.IOException JavaDoc;
47 import java.text.MessageFormat JavaDoc;
48 import java.util.ArrayList JavaDoc;
49 import java.util.HashMap JavaDoc;
50 import java.util.List JavaDoc;
51 import java.util.Map JavaDoc;
52 import java.util.Properties JavaDoc;
53
54 import net.jforum.SessionFacade;
55 import net.jforum.entities.UserSession;
56 import net.jforum.util.preferences.ConfigKeys;
57 import net.jforum.util.preferences.SystemGlobals;
58
59 import org.apache.log4j.Logger;
60
61 /**
62  * I18n (Internationalization) class implementation. Does nothing of special, just loads the
63  * messages into memory and provides a static method to acess them.
64  *
65  * @author Rafael Steil
66  * @author James Yong
67  * @version $Id: I18n.java,v 1.30 2005/10/30 15:48:17 rafaelsteil Exp $
68  */

69 public class I18n
70 {
71     private static I18n classInstance = new I18n();
72     private static Map JavaDoc messagesMap = new HashMap JavaDoc();
73     private static Properties JavaDoc localeNames = new Properties JavaDoc();
74     private static String JavaDoc defaultName;
75     private static String JavaDoc baseDir;
76     private static List JavaDoc watching = new ArrayList JavaDoc();
77     public static final String JavaDoc CANNOT_DELETE_GROUP = "CannotDeleteGroup";
78     public static final String JavaDoc CANNOT_DELETE_CATEGORY = "CannotDeleteCategory";
79     public static final String JavaDoc CANNOT_DELETE_BANNER = "CannotDeleteBanner";
80     private static final Logger logger = Logger.getLogger(I18n.class);
81
82     private I18n() {}
83
84     /**
85      * Gets the singleton
86      *
87      * @return Instance of I18n class
88      */

89     public static I18n getInstance()
90     {
91         return classInstance;
92     }
93
94     /**
95      * Load the default I18n file
96      *
97      * @throws IOException
98      */

99     public static synchronized void load() throws IOException JavaDoc
100     {
101         baseDir = SystemGlobals.getApplicationResourceDir() + "/" + SystemGlobals.getValue(ConfigKeys.LOCALES_DIR);
102
103         loadLocales();
104
105         defaultName = SystemGlobals.getValue(ConfigKeys.I18N_DEFAULT_ADMIN);
106         load(defaultName, null);
107
108         String JavaDoc custom = SystemGlobals.getValue(ConfigKeys.I18N_DEFAULT);
109         if (!custom.equals(defaultName)) {
110             load(custom, defaultName);
111             defaultName = custom;
112         }
113     }
114     
115     public static void changeBoardDefault(String JavaDoc newDefaultLanguage) throws Exception JavaDoc
116     {
117         load(newDefaultLanguage, SystemGlobals.getValue(ConfigKeys.I18N_DEFAULT_ADMIN));
118         defaultName = newDefaultLanguage;
119     }
120
121     private static void loadLocales() throws IOException JavaDoc
122     {
123         localeNames.load(new FileInputStream JavaDoc(baseDir + SystemGlobals.getValue(ConfigKeys.LOCALES_NAMES)));
124     }
125
126     static void load(String JavaDoc localeName, String JavaDoc mergeWith) throws IOException JavaDoc
127     {
128         load(localeName, mergeWith, false);
129     }
130
131     static void load(String JavaDoc localeName, String JavaDoc mergeWith, boolean force) throws IOException JavaDoc
132     {
133         if (!force && (localeName == null || localeName.trim().equals("") || I18n.contains(localeName))) {
134             return;
135         }
136
137         if (localeNames.size() == 0) {
138             loadLocales();
139         }
140
141         Properties JavaDoc p = new Properties JavaDoc();
142
143         if (mergeWith != null) {
144             if (!I18n.contains(mergeWith)) {
145                 load(mergeWith, null);
146             }
147
148             p.putAll((Properties JavaDoc) messagesMap.get(mergeWith));
149         }
150
151         p.load(new FileInputStream JavaDoc(baseDir + localeNames.getProperty(localeName)));
152         messagesMap.put(localeName, p);
153
154         watchForChanges(localeName);
155     }
156
157     /**
158      * Loads a new locale. If <code>localeName</code> is either null or empty, or if the locale is
159      * already loaded, the method will return without executing any code.
160      *
161      * @param localeName
162      * The locale name to load
163      * @throws IOException
164      */

165     public static void load(String JavaDoc localeName) throws IOException JavaDoc
166     {
167         load(localeName, SystemGlobals.getValue(ConfigKeys.I18N_DEFAULT));
168     }
169
170     public static void reset()
171     {
172         messagesMap = new HashMap JavaDoc();
173         localeNames = new Properties JavaDoc();
174         defaultName = null;
175     }
176
177     private static void watchForChanges(final String JavaDoc localeName)
178     {
179         if (!watching.contains(localeName)) {
180             watching.add(localeName);
181
182             int fileChangesDelay = SystemGlobals.getIntValue(ConfigKeys.FILECHANGES_DELAY);
183
184             if (fileChangesDelay > 0) {
185                 FileMonitor.getInstance().addFileChangeListener(new FileChangeListener() {
186                     /**
187                      * @see net.jforum.util.FileChangeListener#fileChanged(java.lang.String)
188                      */

189                     public void fileChanged(String JavaDoc filename)
190                     {
191                         logger.info("Reloading i18n for " + localeName);
192
193                         try {
194                             I18n.load(localeName, SystemGlobals.getValue(ConfigKeys.I18N_DEFAULT), true);
195                         }
196                         catch (IOException JavaDoc e) {
197                             logger.warn(e);
198                             e.printStackTrace();
199                         }
200                     }
201                 }, baseDir + localeNames.getProperty(localeName), fileChangesDelay);
202             }
203         }
204     }
205
206     /**
207      * Gets a I18N (internationalized) message.
208      *
209      * @param localeName
210      * The locale name to retrieve the messages from
211      * @param messageName
212      * The message name to retrieve. Must be a valid entry into the file specified by
213      * <code>i18n.file</code> property.
214      * @param params
215      * Parameters needed by some messages. The messages with extra parameters are
216      * formated according to {@link java.text.MessageFormat}specification
217      * @return String With the message
218      */

219     public static String JavaDoc getMessage(String JavaDoc localeName, String JavaDoc messageName, Object JavaDoc params[])
220     {
221         return MessageFormat.format(((Properties JavaDoc) messagesMap.get(localeName)).getProperty(messageName), params);
222     }
223
224     /**
225      * @see #getMessage(String, String, Object[])
226      */

227     public static String JavaDoc getMessage(String JavaDoc messageName, Object JavaDoc params[])
228     {
229         String JavaDoc lang = "";
230         UserSession us = SessionFacade.getUserSession();
231         if (us != null && us.getLang() != null) {
232             lang = us.getLang();
233         }
234
235         if ("".equals(lang)) {
236             return getMessage(defaultName, messageName, params);
237         }
238
239         return getMessage(lang, messageName, params);
240     }
241
242     /**
243      * Gets an I18N (internationalization) message.
244      *
245      * @param m
246      * The message name to retrieve. Must be a valid entry into the file specified by
247      * <code>i18n.file</code> property.
248      * @return String With the message
249      */

250     public static String JavaDoc getMessage(String JavaDoc localeName, String JavaDoc m)
251     {
252         if (!messagesMap.containsKey(localeName)) {
253             try {
254                 load(localeName);
255             }
256             catch (IOException JavaDoc e) {
257                 logger.warn("Error loading locale " + localeName + ". " + e.getMessage());
258                 return null;
259             }
260         }
261
262         return (((Properties JavaDoc) messagesMap.get(localeName)).getProperty(m));
263     }
264
265     public static String JavaDoc getMessage(String JavaDoc m)
266     {
267         return getMessage(getUserLanguage(), m);
268     }
269
270     public static String JavaDoc getMessage(String JavaDoc m, UserSession us)
271     {
272         if (us == null || us.getLang() == null || us.getLang().equals("")) {
273             return getMessage(defaultName, m);
274         }
275
276         return getMessage(us.getLang(), m);
277     }
278     
279     /**
280      * Gets the language name for the current request.
281      * The method will first look at {@link UserSession#getLang()} and use
282      * it if any value is found. Otherwise, the default board language will be used
283      * @return
284      */

285     public static String JavaDoc getUserLanguage()
286     {
287         UserSession us = SessionFacade.getUserSession();
288         
289         if (us == null || us.getLang() == null || us.getLang().trim().equals("")) {
290             return defaultName;
291         }
292         
293         return us.getLang();
294     }
295
296     /**
297      * Check whether the language is loaded in i18n.
298      *
299      * @param language
300      * @return boolean
301      */

302     public static boolean contains(String JavaDoc language)
303     {
304         return messagesMap.containsKey(language);
305     }
306
307     /**
308      * Check if the given language exist.
309      *
310      * @param language
311      * The language to check
312      * @return <code>true</code> if the language is a valid and registered translation.
313      */

314     public static boolean languageExists(String JavaDoc language)
315     {
316         return (localeNames.getProperty(language) != null);
317     }
318 }
Popular Tags