1 package be
.nikiroo
.jvcard
.i18n
;
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
;
12 import be
.nikiroo
.jvcard
.resources
.Bundles
;
13 import be
.nikiroo
.jvcard
.tui
.UiColors
;
15 import com
.googlecode
.lanterna
.input
.KeyStroke
;
18 * This class manages the translation of {@link Trans.StringId}s into
19 * user-understandable text.
28 * Create a translation service with the default language.
35 * Create a translation service for the given language. (Will fall back to
36 * the default one i not found.)
41 public Trans(String language
) {
42 setLanguage(language
);
46 * Translate the given {@link StringId} into user text.
51 * @return the translated text
53 public String
trans(StringId stringId
) {
54 StringId id
= stringId
;
55 if (!UiColors
.getInstance().isUnicode()) {
57 id
= StringId
.valueOf(stringId
.name() + "_NOUTF");
58 } catch (IllegalArgumentException iae
) {
59 // no special _NOUTF version found
63 if (id
== StringId
.NULL
) {
67 if (id
== StringId
.DUMMY
) {
71 if (map
.containsKey(id
.name())) {
72 return map
.getString(id
.name());
79 * Translate the given {@link KeyStroke} into a user text {@link String} of
83 * the key to translate
85 * @return the translated text
87 public String
trans(KeyStroke key
) {
90 switch (key
.getKeyType()) {
92 if (UiColors
.getInstance().isUnicode())
95 keyTrans
= trans(StringId
.KEY_ENTER
);
98 if (UiColors
.getInstance().isUnicode())
101 keyTrans
= trans(StringId
.KEY_TAB
);
105 keyTrans
= " " + key
.getCharacter() + " ";
108 keyTrans
= "" + key
.getKeyType();
110 if (keyTrans
.length() > width
) {
111 keyTrans
= keyTrans
.substring(0, width
);
112 } else if (keyTrans
.length() < width
) {
114 + new String(new char[width
- keyTrans
.length()])
124 * Initialise the translation mappings for the given language.
127 * the language to initialise
129 private void setLanguage(String lang
) {
130 Locale locale
= null;
133 locale
= Locale
.getDefault();
135 locale
= new Locale(lang
);
138 map
= Bundles
.getBundle("resources", locale
);
142 * Create/update the translation .properties files. Will use the most likely
143 * candidate as base if the file does not already exists (for instance,
144 * "en_US" will use "en" as a base).
147 * the path where the .properties files are, then the languages
150 * @throws IOException
151 * in case of IO errors
153 public static void main(String
[] args
) throws IOException
{
154 String path
= args
[0];
155 for (int i
= 1; i
< args
.length
; i
++) {
156 Locale locale
= new Locale(args
[i
].replaceAll("_", "-"));
157 String code
= locale
.toString();
158 Trans trans
= new Trans(code
);
161 if (code
.length() > 0) {
162 file
= new File(path
+ "resources_" + code
+ ".properties");
164 // Default properties file:
165 file
= new File(path
+ "resources.properties");
168 BufferedWriter writer
= new BufferedWriter(new OutputStreamWriter(
169 new FileOutputStream(file
), "UTF-8"));
171 String name
= locale
.getDisplayCountry(locale
);
172 if (name
.length() == 0)
173 name
= locale
.getDisplayLanguage(locale
);
174 if (name
.length() == 0)
177 if (code
.length() > 0) {
178 name
= name
+ " (" + code
+ ")";
181 writer
.append("# " + name
+ " translation file (UTF-8)\n");
182 writer
.append("# \n");
183 writer
.append("# Note that any key can be doubled with a _NOUTF suffix\n");
184 writer
.append("# to use when the flag --noutf is passed\n");
185 writer
.append("# \n");
186 writer
.append("# Also, the comments always refer to the key below them.\n");
187 writer
.append("# \n");
190 for (Field field
: StringId
.class.getDeclaredFields()) {
191 Meta meta
= field
.getAnnotation(Meta
.class);
193 StringId id
= StringId
.valueOf(field
.getName());
194 String info
= getMetaInfo(meta
);
200 writer
.append(id
.name());
201 writer
.append(" = ");
202 if (!trans
.trans(id
).equals(id
.name()))
203 writer
.append(trans
.trans(id
));
213 * Return formated, display-able information from the {@link Meta} field
214 * given. Each line will always starts with a "#" character.
217 * the {@link Meta} field
219 * @return the information to display or NULL if none
221 private static String
getMetaInfo(Meta meta
) {
222 String what
= meta
.what();
223 String where
= meta
.where();
224 String format
= meta
.format();
225 String info
= meta
.info();
227 int opt
= what
.length() + where
.length() + format
.length();
228 if (opt
+ info
.length() == 0)
231 StringBuilder builder
= new StringBuilder();
232 builder
.append("# ");
236 if (what
.length() > 0) {
237 builder
.append("WHAT: " + what
);
238 if (where
.length() + format
.length() > 0)
239 builder
.append(", ");
242 if (where
.length() > 0) {
243 builder
.append("WHERE: " + where
);
244 if (format
.length() > 0)
245 builder
.append(", ");
248 if (format
.length() > 0) {
249 builder
.append("FORMAT: " + format
);
252 builder
.append(")\n# ");
255 builder
.append(info
);
257 return builder
.toString();
261 * The enum representing textual information to be translated to the user as
264 * Note that each key that should be translated MUST be annotated with a
265 * {@link Meta} annotation.
270 public enum StringId
{
271 DUMMY
, // <-- TODO : remove
272 NULL
, // Special usage, no annotations so it is not visible in
274 @Meta(what
= "a key to press", where
= "action keys", format
= "MUST BE 3 chars long", info
= "Tab key")
276 @Meta(what
= "a key to press", where
= "action keys", format
= "MUST BE 3 chars long", info
= "Enter key")
278 @Meta(what
= "", where
= "", format
= "", info
= "")
279 KEY_ACTION_BACK
, // MainWindow
280 @Meta(what
= "", where
= "", format
= "", info
= "")
282 @Meta(what
= "", where
= "", format
= "", info
= "")
283 KEY_ACTION_VIEW_CARD
, // FileList
284 @Meta(what
= "", where
= "", format
= "", info
= "")
285 KEY_ACTION_VIEW_CONTACT
, // ContactList
286 @Meta(what
= "", where
= "", format
= "", info
= "")
287 KEY_ACTION_EDIT_CONTACT
, //
288 @Meta(what
= "", where
= "", format
= "", info
= "")
289 KEY_ACTION_SAVE_CARD
, //
290 @Meta(what
= "", where
= "", format
= "", info
= "")
291 KEY_ACTION_DELETE_CONTACT
, //
292 @Meta(what
= "", where
= "", format
= "", info
= "")
293 KEY_ACTION_SEARCH
, //
294 @Meta(what
= "", where
= "", format
= "", info
= "we could use: ' ', ┃, │...")
295 DEAULT_FIELD_SEPARATOR
, // MainContentList
296 @Meta(what
= "", where
= "", format
= "", info
= "")
297 DEAULT_FIELD_SEPARATOR_NOUTF
, //
298 @Meta(what
= "", where
= "", format
= "", info
= "")
299 KEY_ACTION_INVERT
, // ContactDetails
300 @Meta(what
= "", where
= "", format
= "", info
= "")
301 KEY_ACTION_FULLSCREEN
, //
302 @Meta(what
= "", where
= "", format
= "", info
= "")
303 KEY_ACTION_SWITCH_FORMAT
, // multi-usage