add MessageFormat replacement possibility
[jSite2.git] / src / net / pterodactylus / jsite / i18n / I18n.java
1 /*
2  * jSite2 - I18n.java -
3  * Copyright © 2008 David Roden
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 package net.pterodactylus.jsite.i18n;
21
22 import java.awt.event.InputEvent;
23 import java.awt.event.KeyEvent;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.lang.reflect.Field;
27 import java.text.MessageFormat;
28 import java.util.Locale;
29 import java.util.MissingResourceException;
30 import java.util.Properties;
31 import java.util.StringTokenizer;
32
33 import javax.swing.KeyStroke;
34
35 import net.pterodactylus.util.io.Closer;
36
37 /**
38  * Class that handles i18n.
39  * 
40  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
41  * @version $Id$
42  */
43 public class I18n {
44
45         /** The current locale. */
46         private static Locale currentLocale;
47
48         /** The default language. */
49         private static Properties defaultLanguage;
50
51         /** The current language. */
52         private static Properties currentLanguage;
53
54         static {
55                 defaultLanguage = new Properties();
56                 InputStream inputStream = null;
57                 try {
58                         inputStream = I18n.class.getResourceAsStream("jSite.properties");
59                         if (inputStream != null) {
60                                 defaultLanguage.load(inputStream);
61                         }
62                 } catch (IOException e) {
63                         /* something is fucked. */
64                 }
65                 setLocale(Locale.getDefault());
66         }
67
68         /**
69          * Returns the translated value for a key. The translated values may contain
70          * placeholders that are replaced with the given parameters.
71          * 
72          * @see MessageFormat
73          * @param key
74          *            The key to get
75          * @param parameters
76          *            The parameters in case the translated value contains
77          *            placeholders
78          * @return The translated message, or the key itself if no translation could
79          *         be found
80          */
81         public static String get(String key, Object... parameters) {
82                 String value = null;
83                 value = currentLanguage.getProperty(key);
84                 if (value == null) {
85                         return key;
86                 }
87                 if ((parameters != null) && (parameters.length > 0)) {
88                         return MessageFormat.format(value, parameters);
89                 }
90                 return value;
91         }
92
93         /**
94          * Returns the keycode from the value of the given key. You can specify the
95          * constants in {@link KeyEvent} in the properties file, e.g. VK_S for the
96          * keycode ‘s’ when used for mnemonics.
97          * 
98          * @param key
99          *            The key under which the keycode is stored
100          * @return The keycode
101          */
102         public static int getKey(String key) {
103                 String value = get(key);
104                 if (value.startsWith("VK_")) {
105                         try {
106                                 Field field = KeyEvent.class.getField(value);
107                                 return field.getInt(null);
108                         } catch (SecurityException e) {
109                                 /* ignore. */
110                         } catch (NoSuchFieldException e) {
111                                 /* ignore. */
112                         } catch (IllegalArgumentException e) {
113                                 /* ignore. */
114                         } catch (IllegalAccessException e) {
115                                 /* ignore. */
116                         }
117                 }
118                 return value.toUpperCase().charAt(0);
119         }
120
121         /**
122          * Returns a key stroke for use with swing accelerators.
123          * 
124          * @param key
125          *            The key of the key stroke
126          * @return The key stroke, or <code>null</code> if no key stroke could be
127          *         created from the translated value
128          */
129         public static KeyStroke getKeyStroke(String key) {
130                 String value = get(key);
131                 if (value == null) {
132                         return null;
133                 }
134                 StringTokenizer keyTokens = new StringTokenizer(value, "+- ");
135                 int modifierMask = 0;
136                 while (keyTokens.hasMoreTokens()) {
137                         String keyToken = keyTokens.nextToken();
138                         if ("ctrl".equalsIgnoreCase(keyToken)) {
139                                 modifierMask |= InputEvent.CTRL_DOWN_MASK;
140                         } else if ("alt".equalsIgnoreCase(keyToken)) {
141                                 modifierMask |= InputEvent.ALT_DOWN_MASK;
142                         } else if ("shift".equalsIgnoreCase(keyToken)) {
143                                 modifierMask |= InputEvent.SHIFT_DOWN_MASK;
144                         } else {
145                                 if (keyToken.startsWith("VK_")) {
146                                         try {
147                                                 Field field = KeyEvent.class.getField(keyToken);
148                                                 return KeyStroke.getKeyStroke(field.getInt(null), modifierMask);
149                                         } catch (SecurityException e) {
150                                                 /* ignore. */
151                                         } catch (NoSuchFieldException e) {
152                                                 /* ignore. */
153                                         } catch (IllegalArgumentException e) {
154                                                 /* ignore. */
155                                         } catch (IllegalAccessException e) {
156                                                 /* ignore. */
157                                         }
158                                 }
159                                 return KeyStroke.getKeyStroke(keyToken.charAt(0), modifierMask);
160                         }
161                 }
162                 return null;
163         }
164
165         /**
166          * Sets the current locale.
167          * 
168          * @param newLocale
169          *            The new locale to use
170          */
171         public static void setLocale(Locale newLocale) {
172                 currentLocale = newLocale;
173                 InputStream inputStream = null;
174                 try {
175                         currentLanguage = new Properties(defaultLanguage);
176                         inputStream = I18n.class.getResourceAsStream("jSite_" + currentLocale.toString() + ".properties");
177                         if (inputStream != null) {
178                                 currentLanguage.load(inputStream);
179                         }
180                 } catch (MissingResourceException mre1) {
181                         currentLocale = Locale.ENGLISH;
182                 } catch (IOException ioe1) {
183                         currentLocale = Locale.ENGLISH;
184                 } finally {
185                         Closer.close(inputStream);
186                 }
187         }
188 }