51e090f6fab208f7bb6eb3f40fcb3910fe5c7901
1 package be
.nikiroo
.utils
.resources
;
4 import java
.io
.IOException
;
6 import java
.util
.LinkedList
;
8 import java
.util
.Locale
;
9 import java
.util
.regex
.Pattern
;
12 * This class manages a translation-dedicated Bundle.
14 * Two special cases are handled for the used enum:
16 * <li>NULL will always will return an empty {@link String}</li>
17 * <li>DUMMY will return "[DUMMY]" (maybe with a suffix and/or "NOUTF")</li>
21 * the enum to use to get values out of this class
25 public class TransBundle
<E
extends Enum
<E
>> extends Bundle
<E
> {
26 private boolean utf
= true;
27 private Locale locale
;
28 private boolean defaultLocale
= false;
31 * Create a translation service with the default language.
34 * a runtime instance of the class of E
36 * the name of the {@link Bundles}
38 public TransBundle(Class
<E
> type
, Enum
<?
> name
) {
39 super(type
, name
, null);
44 * Create a translation service for the given language (will fall back to
45 * the default one i not found).
48 * a runtime instance of the class of E
50 * the name of the {@link Bundles}
54 public TransBundle(Class
<E
> type
, Enum
<?
> name
, String language
) {
55 super(type
, name
, null);
56 setLanguage(language
);
60 * Translate the given id into user text.
65 * the values to insert instead of the place holders in the
68 * @return the translated text with the given value where required or NULL
69 * if not found (not present in the resource file)
71 public String
getString(E stringId
, Object
... values
) {
72 return getStringX(stringId
, "", values
);
76 * Translate the given id into user text.
81 * the values to insert instead of the place holders in the
84 * @return the translated text with the given value where required or NULL
85 * if not found (not present in the resource file)
87 public String
getStringNOUTF(E stringId
, Object
... values
) {
88 return getStringX(stringId
, "NOUTF", values
);
92 * Translate the given id suffixed with the runtime value "_suffix" (that
93 * is, "_" and suffix) into user text.
98 * the values to insert instead of the place holders in the
103 * @return the translated text with the given value where required or NULL
104 * if not found (not present in the resource file)
106 public String
getStringX(E stringId
, String suffix
, Object
... values
) {
110 String key
= id
.name()
111 + ((suffix
== null || suffix
.isEmpty()) ?
"" : "_"
112 + suffix
.toUpperCase());
115 if (containsKey(key
+ "_NOUTF")) {
120 if ("NULL".equals(id
.name().toUpperCase())) {
122 } else if ("DUMMY".equals(id
.name().toUpperCase())) {
123 result
= "[" + key
.toLowerCase() + "]";
124 } else if (containsKey(key
)) {
125 result
= getString(key
);
130 if (values
!= null && values
.length
> 0 && result
!= null)
131 return String
.format(locale
, result
, values
);
137 * Check if unicode characters should be used.
139 * @return TRUE to allow unicode
141 public boolean isUnicode() {
146 * Allow or disallow unicode characters in the program.
149 * TRUE to allow unuciode, FALSE to only allow ASCII characters
151 public void setUnicode(boolean utf
) {
156 * Return all the languages known by the program.
159 * @return the known language codes
161 public List
<String
> getKnownLanguages() {
162 return getKnownLanguages(keyType
);
166 * Initialise the translation mappings for the given language.
169 * the language to initialise, in the form "en-GB" or "fr" for
172 private void setLanguage(String language
) {
173 defaultLocale
= (language
== null || language
.length() == 0);
174 locale
= getLocaleFor(language
);
175 setBundle(keyType
, locale
, false);
179 public void reload(boolean resetToDefault
) {
180 setBundle(keyType
, locale
, resetToDefault
);
184 public String
getString(E id
) {
185 return getString(id
, (Object
[]) null);
189 * Create/update the .properties files for each supported language and for
190 * the default language.
192 * Note: this method is <b>NOT</b> thread-safe.
195 * the path where the .properties files are
197 * @throws IOException
198 * in case of IO errors
201 public void updateFile(String path
) throws IOException
{
202 String prev
= locale
.getLanguage();
203 Object status
= takeSnapshot();
207 if (prev
.equals(getLocaleFor(null).getLanguage())) {
208 // restore snapshot if default locale = current locale
209 restoreSnapshot(status
);
211 super.updateFile(path
);
213 for (String lang
: getKnownLanguages()) {
215 if (lang
.equals(prev
)) {
216 restoreSnapshot(status
);
218 super.updateFile(path
);
222 restoreSnapshot(status
);
226 protected File
getUpdateFile(String path
) {
227 String code
= locale
.toString();
229 if (!defaultLocale
&& code
.length() > 0) {
230 file
= new File(path
, keyType
.name() + "_" + code
+ ".properties");
232 // Default properties file:
233 file
= new File(path
, keyType
.name() + ".properties");
240 protected void writeHeader(Writer writer
) throws IOException
{
241 String code
= locale
.toString();
242 String name
= locale
.getDisplayCountry(locale
);
244 if (name
.length() == 0) {
245 name
= locale
.getDisplayLanguage(locale
);
248 if (name
.length() == 0) {
252 if (code
.length() > 0) {
253 name
= name
+ " (" + code
+ ")";
256 name
= (name
+ " " + getBundleDisplayName()).trim();
258 writer
.write("# " + name
+ " translation file (UTF-8)\n");
259 writer
.write("# \n");
260 writer
.write("# Note that any key can be doubled with a _NOUTF suffix\n");
261 writer
.write("# to use when the NOUTF env variable is set to 1\n");
262 writer
.write("# \n");
263 writer
.write("# Also, the comments always refer to the key below them.\n");
264 writer
.write("# \n");
268 protected void writeValue(Writer writer
, E id
) throws IOException
{
269 super.writeValue(writer
, id
);
271 String name
= id
.name() + "_NOUTF";
272 if (containsKey(name
)) {
273 String value
= getString(name
);
274 writeValue(writer
, name
, value
);
279 * Return the {@link Locale} representing the given language.
282 * the language to initialise, in the form "en-GB" or "fr" for
285 * @return the corresponding {@link Locale} or the default {@link Locale} if
288 static private Locale
getLocaleFor(String language
) {
291 if (language
== null) {
292 locale
= Locale
.getDefault();
294 language
= language
.replaceAll("_", "-");
295 String lang
= language
;
296 String country
= null;
297 if (language
.contains("-")) {
298 lang
= language
.split("-")[0];
299 country
= language
.split("-")[1];
303 locale
= new Locale(lang
, country
);
305 locale
= new Locale(lang
);
312 * Return all the languages known by the program.
315 * the enumeration on which we translate
317 * @return the known language codes
319 static protected List
<String
> getKnownLanguages(Enum
<?
> name
) {
320 List
<String
> resources
= new LinkedList
<String
>();
322 String regex
= ".*" + name
.name() + "[_a-zA-Za]*\\.properties$";
324 for (String res
: TransBundle_ResourceList
.getResources(Pattern
326 String resource
= res
;
327 int index
= resource
.lastIndexOf('/');
328 if (index
>= 0 && index
< (resource
.length() - 1))
329 resource
= resource
.substring(index
+ 1);
330 if (resource
.startsWith(name
.name())) {
331 resource
= resource
.substring(0, resource
.length()
332 - ".properties".length());
333 resource
= resource
.substring(name
.name().length());
334 if (resource
.startsWith("_")) {
335 resource
= resource
.substring(1);
336 resources
.add(resource
);