1 package be
.nikiroo
.jvcard
.resources
;
3 import java
.io
.BufferedWriter
;
5 import java
.io
.FileOutputStream
;
6 import java
.io
.IOException
;
7 import java
.io
.OutputStreamWriter
;
8 import java
.lang
.reflect
.Field
;
9 import java
.util
.Locale
;
10 import java
.util
.ResourceBundle
;
13 * This class manages the translation of {@link Trans.StringId}s into
14 * user-understandable text.
20 private ResourceBundle map
;
21 private boolean utf
= true;
24 * Create a translation service with the default language.
31 * Create a translation service for the given language. (Will fall back to
32 * the default one i not found.)
37 public Trans(String language
) {
38 setLanguage(language
);
42 * Translate the given {@link StringId} into user text.
47 * @return the translated text
49 public String
trans(StringId stringId
) {
50 StringId id
= stringId
;
53 id
= StringId
.valueOf(stringId
.name() + "_NOUTF");
54 } catch (IllegalArgumentException iae
) {
55 // no special _NOUTF version found
59 if (id
== StringId
.NULL
) {
63 if (id
== StringId
.DUMMY
) {
67 if (map
.containsKey(id
.name())) {
68 return map
.getString(id
.name());
75 * Check if unicode characters should be used.
77 * @return TRUE to allow unicode
79 public boolean isUnicode() {
84 * Allow or disallow unicode characters in the program.
87 * TRUE to allow unuciode, FALSE to only allow ASCII characters
89 public void setUnicode(boolean utf
) {
94 * Initialise the translation mappings for the given language.
97 * the language to initialise, in the form "en-GB" or "fr" for
100 private void setLanguage(String language
) {
101 map
= Bundles
.getBundle("resources", getLocaleFor(language
));
105 * Create/update the translation .properties files. Will use the most likely
106 * candidate as base if the file does not already exists (for instance,
107 * "en_US" will use "en" as a base).
110 * the path where the .properties files are
113 * the language code to create/update (e.g.: <tt>fr-BE</tt>)
115 * @throws IOException
116 * in case of IO errors
118 static public void generateTranslationFile(String path
, String language
)
121 Locale locale
= getLocaleFor(language
);
122 String code
= locale
.toString();
123 Trans trans
= new Trans(code
);
126 if (code
.length() > 0) {
127 file
= new File(path
+ "resources_" + code
+ ".properties");
129 // Default properties file:
130 file
= new File(path
+ "resources.properties");
133 BufferedWriter writer
= new BufferedWriter(new OutputStreamWriter(
134 new FileOutputStream(file
), "UTF-8"));
136 String name
= locale
.getDisplayCountry(locale
);
137 if (name
.length() == 0)
138 name
= locale
.getDisplayLanguage(locale
);
139 if (name
.length() == 0)
142 if (code
.length() > 0) {
143 name
= name
+ " (" + code
+ ")";
146 writer
.append("# " + name
+ " translation file (UTF-8)\n");
147 writer
.append("# \n");
148 writer
.append("# Note that any key can be doubled with a _NOUTF suffix\n");
149 writer
.append("# to use when the flag --noutf is passed\n");
150 writer
.append("# \n");
151 writer
.append("# Also, the comments always refer to the key below them.\n");
152 writer
.append("# \n");
155 for (Field field
: StringId
.class.getDeclaredFields()) {
156 Meta meta
= field
.getAnnotation(Meta
.class);
158 StringId id
= StringId
.valueOf(field
.getName());
159 String info
= getMetaInfo(meta
);
165 writer
.append(id
.name());
166 writer
.append(" = ");
167 if (!trans
.trans(id
).equals(id
.name()))
168 writer
.append(trans
.trans(id
));
177 * Return the {@link Locale} representing the given language.
180 * the language to initialise, in the form "en-GB" or "fr" for
183 * @return the corresponding {@link Locale} or the default {@link Locale} if
186 static private Locale
getLocaleFor(String language
) {
189 if (language
== null) {
190 locale
= Locale
.getDefault();
192 language
= language
.replaceAll("_", "-");
193 String lang
= language
;
194 String country
= null;
195 if (language
.contains("-")) {
196 lang
= language
.split("-")[0];
197 country
= language
.split("-")[1];
201 locale
= new Locale(lang
, country
);
203 locale
= new Locale(lang
);
210 * Return formated, display-able information from the {@link Meta} field
211 * given. Each line will always starts with a "#" character.
214 * the {@link Meta} field
216 * @return the information to display or NULL if none
218 static private String
getMetaInfo(Meta meta
) {
219 String what
= meta
.what();
220 String where
= meta
.where();
221 String format
= meta
.format();
222 String info
= meta
.info();
224 int opt
= what
.length() + where
.length() + format
.length();
225 if (opt
+ info
.length() == 0)
228 StringBuilder builder
= new StringBuilder();
229 builder
.append("# ");
233 if (what
.length() > 0) {
234 builder
.append("WHAT: " + what
);
235 if (where
.length() + format
.length() > 0)
236 builder
.append(", ");
239 if (where
.length() > 0) {
240 builder
.append("WHERE: " + where
);
241 if (format
.length() > 0)
242 builder
.append(", ");
245 if (format
.length() > 0) {
246 builder
.append("FORMAT: " + format
);
249 builder
.append(")\n# ");
252 builder
.append(info
);
254 return builder
.toString();
258 * The enum representing textual information to be translated to the user as
261 * Note that each key that should be translated MUST be annotated with a
262 * {@link Meta} annotation.
267 public enum StringId
{
268 DUMMY
, // <-- TODO : remove
269 NULL
, // Special usage, no annotations so it is not visible in
271 @Meta(what
= "a key to press", where
= "action keys", format
= "MUST BE 3 chars long", info
= "Tab key")
273 @Meta(what
= "a key to press", where
= "action keys", format
= "MUST BE 3 chars long", info
= "Enter key")
275 @Meta(what
= "", where
= "", format
= "", info
= "")
276 KEY_ACTION_BACK
, // MainWindow
277 @Meta(what
= "", where
= "", format
= "", info
= "")
279 @Meta(what
= "", where
= "", format
= "", info
= "")
280 KEY_ACTION_VIEW_CARD
, // FileList
281 @Meta(what
= "", where
= "", format
= "", info
= "")
282 KEY_ACTION_VIEW_CONTACT
, // ContactList
283 @Meta(what
= "", where
= "", format
= "", info
= "")
284 KEY_ACTION_EDIT_CONTACT
, //
285 @Meta(what
= "", where
= "", format
= "", info
= "")
286 KEY_ACTION_SAVE_CARD
, //
287 @Meta(what
= "", where
= "", format
= "", info
= "")
288 KEY_ACTION_DELETE_CONTACT
, //
289 @Meta(what
= "", where
= "", format
= "", info
= "")
290 KEY_ACTION_SEARCH
, //
291 @Meta(what
= "", where
= "", format
= "", info
= "we could use: ' ', ┃, │...")
292 DEAULT_FIELD_SEPARATOR
, // MainContentList
293 @Meta(what
= "", where
= "", format
= "", info
= "")
294 DEAULT_FIELD_SEPARATOR_NOUTF
, //
295 @Meta(what
= "", where
= "", format
= "", info
= "")
296 KEY_ACTION_INVERT
, // ContactDetails
297 @Meta(what
= "", where
= "", format
= "", info
= "")
298 KEY_ACTION_FULLSCREEN
, //
299 @Meta(what
= "", where
= "", format
= "", info
= "")
300 KEY_ACTION_SWITCH_FORMAT
, // multi-usage