001
014
015 package com.liferay.portal.tools;
016
017 import com.liferay.portal.kernel.io.OutputStreamWriter;
018 import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
019 import com.liferay.portal.kernel.io.unsync.UnsyncBufferedWriter;
020 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
021 import com.liferay.portal.kernel.util.FileUtil;
022 import com.liferay.portal.kernel.util.GetterUtil;
023 import com.liferay.portal.kernel.util.PropertiesUtil;
024 import com.liferay.portal.kernel.util.StringPool;
025 import com.liferay.portal.kernel.util.StringUtil;
026 import com.liferay.portal.kernel.util.Validator;
027 import com.liferay.portal.kernel.webcache.WebCacheItem;
028 import com.liferay.portal.util.InitUtil;
029 import com.liferay.portlet.translator.model.Translation;
030 import com.liferay.portlet.translator.util.TranslationWebCacheItem;
031
032 import java.io.File;
033 import java.io.FileInputStream;
034 import java.io.FileOutputStream;
035 import java.io.FileWriter;
036 import java.io.IOException;
037 import java.io.InputStream;
038
039 import java.util.Map;
040 import java.util.Properties;
041 import java.util.Set;
042 import java.util.TreeSet;
043
044
047 public class LangBuilder {
048
049 public static final String AUTOMATIC_COPY = " (Automatic Copy)";
050
051 public static final String AUTOMATIC_TRANSLATION =
052 " (Automatic Translation)";
053
054 public static void main(String[] args) {
055 Map<String, String> arguments = ArgumentsUtil.parseArguments(args);
056
057 System.setProperty("line.separator", StringPool.NEW_LINE);
058
059 InitUtil.initWithSpring();
060
061 String langDir = arguments.get("lang.dir");
062 String langFile = arguments.get("lang.file");
063 boolean langPlugin = GetterUtil.getBoolean(
064 arguments.get("lang.plugin"));
065 boolean langTranslate = GetterUtil.getBoolean(
066 arguments.get("lang.translate"), true);
067
068 try {
069 new LangBuilder(langDir, langFile, langPlugin, langTranslate);
070 }
071 catch (Exception e) {
072 e.printStackTrace();
073 }
074 }
075
076 public LangBuilder(
077 String langDir, String langFile, boolean langPlugin,
078 boolean langTranslate)
079 throws Exception {
080
081 _langDir = langDir;
082 _langFile = langFile;
083 _langTranslate = langTranslate;
084
085 if (langPlugin) {
086 _portalLanguageProperties = new Properties();
087
088 Class<?> clazz = getClass();
089
090 ClassLoader classLoader = clazz.getClassLoader();
091
092 InputStream inputStream = classLoader.getResourceAsStream(
093 "content/Language.properties");
094
095 _portalLanguageProperties.load(inputStream);
096 }
097
098 File renameKeysFile = new File(_langDir + "/rename.properties");
099
100 if (renameKeysFile.exists()) {
101 _renameKeys = PropertiesUtil.load(FileUtil.read(renameKeysFile));
102 }
103
104 String content = _orderProperties(
105 new File(_langDir + "/" + _langFile + ".properties"));
106
107
108
109
110 _orderProperties(
111 new File(_langDir + "/" + _langFile + "_en_GB.properties"));
112
113 _createProperties(content, "ar");
114 _createProperties(content, "eu");
115 _createProperties(content, "bg");
116 _createProperties(content, "ca");
117 _createProperties(content, "zh_CN");
118 _createProperties(content, "zh_TW");
119 _createProperties(content, "hr");
120 _createProperties(content, "cs");
121 _createProperties(content, "da");
122 _createProperties(content, "nl");
123 _createProperties(content, "nl_BE", "nl");
124 _createProperties(content, "et");
125 _createProperties(content, "fi");
126 _createProperties(content, "fr");
127 _createProperties(content, "gl");
128 _createProperties(content, "de");
129 _createProperties(content, "el");
130 _createProperties(content, "iw");
131 _createProperties(content, "hi_IN");
132 _createProperties(content, "hu");
133 _createProperties(content, "in");
134 _createProperties(content, "it");
135 _createProperties(content, "ja");
136 _createProperties(content, "ko");
137 _createProperties(content, "lo");
138 _createProperties(content, "nb");
139 _createProperties(content, "fa");
140 _createProperties(content, "pl");
141 _createProperties(content, "pt_BR");
142 _createProperties(content, "pt_PT", "pt_BR");
143 _createProperties(content, "ro");
144 _createProperties(content, "ru");
145 _createProperties(content, "sr_RS");
146 _createProperties(content, "sr_RS_latin");
147 _createProperties(content, "sk");
148 _createProperties(content, "sl");
149 _createProperties(content, "es");
150 _createProperties(content, "sv");
151 _createProperties(content, "tr");
152 _createProperties(content, "uk");
153 _createProperties(content, "vi");
154 }
155
156 private void _createProperties(String content, String languageId)
157 throws IOException {
158
159 _createProperties(content, languageId, null);
160 }
161
162 private void _createProperties(
163 String content, String languageId, String parentLanguageId)
164 throws IOException {
165
166 File propertiesFile = new File(
167 _langDir + "/" + _langFile + "_" + languageId + ".properties");
168
169 Properties properties = new Properties();
170
171 if (propertiesFile.exists()) {
172 properties = PropertiesUtil.load(
173 new FileInputStream(propertiesFile), StringPool.UTF8);
174 }
175
176 Properties parentProperties = null;
177
178 if (parentLanguageId != null) {
179 File parentPropertiesFile = new File(
180 _langDir + "/" + _langFile + "_" + parentLanguageId +
181 ".properties");
182
183 if (parentPropertiesFile.exists()) {
184 parentProperties = new Properties();
185
186 parentProperties = PropertiesUtil.load(
187 new FileInputStream(parentPropertiesFile), StringPool.UTF8);
188 }
189 }
190
191 String translationId = "en_" + languageId;
192
193 if (translationId.equals("en_pt_BR")) {
194 translationId = "en_pt";
195 }
196 else if (translationId.equals("en_pt_PT")) {
197 translationId = "en_pt";
198 }
199 else if (translationId.equals("en_zh_CN")) {
200 translationId = "en_zh";
201 }
202 else if (translationId.equals("en_zh_TW")) {
203 translationId = "en_zt";
204 }
205 else if (translationId.equals("en_hi_IN")) {
206 translationId = "en_hi";
207 }
208
209 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
210 new UnsyncStringReader(content));
211 UnsyncBufferedWriter unsyncBufferedWriter = new UnsyncBufferedWriter(
212 new OutputStreamWriter(
213 new FileOutputStream(propertiesFile), StringPool.UTF8));
214
215 int state = 0;
216
217 String line = null;
218
219 while ((line = unsyncBufferedReader.readLine()) != null) {
220 line = line.trim();
221
222 int pos = line.indexOf("=");
223
224 if (pos != -1) {
225 String key = line.substring(0, pos);
226 String value = line.substring(pos + 1, line.length());
227
228 if (((state == 1) && !key.startsWith("lang.")) ||
229 ((state == 2) && !key.startsWith("javax.portlet.")) ||
230 ((state == 3) && !key.startsWith("category.")) ||
231 ((state == 4) && !key.startsWith("model.resource.")) ||
232 ((state == 5) && !key.startsWith("action.")) ||
233 ((state == 7) && !key.startsWith("currency.")) ||
234 ((state != 7) && key.startsWith("currency."))) {
235
236 throw new RuntimeException(
237 "File " + languageId + " with state " + state +
238 " has key " + key);
239 }
240
241 String translatedText = properties.getProperty(key);
242
243 if ((translatedText == null) && (parentProperties != null)) {
244 translatedText = parentProperties.getProperty(key);
245 }
246
247 if ((translatedText == null) && (_renameKeys != null)) {
248 String renameKey = _renameKeys.getProperty(key);
249
250 if (renameKey != null) {
251 translatedText = properties.getProperty(key);
252
253 if ((translatedText == null) &&
254 (parentProperties != null)) {
255
256 translatedText = parentProperties.getProperty(key);
257 }
258 }
259 }
260
261 if (translatedText != null) {
262 if (translatedText.contains("Babel Fish") ||
263 translatedText.contains("Yahoo! - 999")) {
264
265 translatedText = "";
266 }
267 else if (translatedText.endsWith(AUTOMATIC_COPY)) {
268 translatedText = value + AUTOMATIC_COPY;
269 }
270 }
271
272 if ((translatedText == null) || translatedText.equals("")) {
273 if (line.contains("{") || line.contains("<")) {
274 translatedText = value + AUTOMATIC_COPY;
275 }
276 else if (line.contains("[")) {
277 pos = line.indexOf("[");
278
279 String baseKey = line.substring(0, pos);
280
281 translatedText =
282 properties.getProperty(baseKey) + AUTOMATIC_COPY;
283 }
284 else if (key.equals("lang.dir")) {
285 translatedText = "ltr";
286 }
287 else if (key.equals("lang.line.begin")) {
288 translatedText = "left";
289 }
290 else if (key.equals("lang.line.end")) {
291 translatedText = "right";
292 }
293 else if (translationId.equals("en_el") &&
294 (key.equals("enabled") || key.equals("on") ||
295 key.equals("on-date"))) {
296
297 translatedText = "";
298 }
299 else if (translationId.equals("en_es") &&
300 key.equals("am")) {
301
302 translatedText = "";
303 }
304 else if (translationId.equals("en_it") &&
305 key.equals("am")) {
306
307 translatedText = "";
308 }
309 else if (translationId.equals("en_ja") &&
310 (key.equals("any") || key.equals("anytime") ||
311 key.equals("down") || key.equals("on") ||
312 key.equals("on-date") || key.equals("the"))) {
313
314 translatedText = "";
315 }
316 else if (translationId.equals("en_ko") &&
317 key.equals("the")) {
318
319 translatedText = "";
320 }
321 else {
322 translatedText = _translate(
323 translationId, key, value, 0);
324
325 if (Validator.isNull(translatedText)) {
326 translatedText = value + AUTOMATIC_COPY;
327 }
328 else {
329 translatedText =
330 translatedText + AUTOMATIC_TRANSLATION;
331 }
332 }
333 }
334
335 if (Validator.isNotNull(translatedText)) {
336 if (translatedText.contains("Babel Fish") ||
337 translatedText.contains("Yahoo! - 999")) {
338
339 throw new IOException(
340 "IP was blocked because of over usage. Please " +
341 "use another IP.");
342 }
343
344 translatedText = _fixTranslation(translatedText);
345
346 unsyncBufferedWriter.write(key + "=" + translatedText);
347
348 unsyncBufferedWriter.newLine();
349 unsyncBufferedWriter.flush();
350 }
351 }
352 else {
353 if (line.startsWith("## Language settings")) {
354 if (state == 1) {
355 throw new RuntimeException(languageId);
356 }
357
358 state = 1;
359 }
360 else if (line.startsWith(
361 "## Portlet descriptions and titles")) {
362
363 if (state == 2) {
364 throw new RuntimeException(languageId);
365 }
366
367 state = 2;
368 }
369 else if (line.startsWith("## Category titles")) {
370 if (state == 3) {
371 throw new RuntimeException(languageId);
372 }
373
374 state = 3;
375 }
376 else if (line.startsWith("## Model resources")) {
377 if (state == 4) {
378 throw new RuntimeException(languageId);
379 }
380
381 state = 4;
382 }
383 else if (line.startsWith("## Action names")) {
384 if (state == 5) {
385 throw new RuntimeException(languageId);
386 }
387
388 state = 5;
389 }
390 else if (line.startsWith("## Messages")) {
391 if (state == 6) {
392 throw new RuntimeException(languageId);
393 }
394
395 state = 6;
396 }
397 else if (line.startsWith("## Currency")) {
398 if (state == 7) {
399 throw new RuntimeException(languageId);
400 }
401
402 state = 7;
403 }
404
405 unsyncBufferedWriter.write(line);
406
407 unsyncBufferedWriter.newLine();
408 unsyncBufferedWriter.flush();
409 }
410 }
411
412 unsyncBufferedReader.close();
413 unsyncBufferedWriter.close();
414 }
415
416 private String _fixEnglishTranslation(String key, String value) {
417 if (value.contains(" this ")) {
418 if (value.contains(".") || value.contains("?") ||
419 value.contains(":") ||
420 key.equals("the-url-of-the-page-comparing-this-page-content-with-the-previous-version")) {
421 }
422 else {
423 value = StringUtil.replace(value, " this ", " This ");
424 }
425 }
426
427 return value;
428 }
429
430 private String _fixTranslation(String value) {
431 value = StringUtil.replace(
432 value.trim(),
433 new String[] {
434 " ", "<b>", "</b>", "<i>", "</i>", " url ", "'", "' ;",
435 """, "" ;"
436 },
437 new String[] {
438 " ", "<strong>", "</strong>", "<em>", "</em>", " URL ", "\'",
439 "\'", "\"", "\""
440 });
441
442 return value;
443 }
444
445 private String _orderProperties(File propertiesFile) throws IOException {
446 if (!propertiesFile.exists()) {
447 return null;
448 }
449
450 String content = FileUtil.read(propertiesFile);
451
452 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
453 new UnsyncStringReader(content));
454 UnsyncBufferedWriter unsyncBufferedWriter = new UnsyncBufferedWriter(
455 new FileWriter(propertiesFile));
456
457 Set<String> messages = new TreeSet<String>();
458
459 boolean begin = false;
460
461 String line = null;
462
463 while ((line = unsyncBufferedReader.readLine()) != null) {
464 int pos = line.indexOf("=");
465
466 if (pos != -1) {
467 String key = line.substring(0, pos);
468
469 String value = _fixTranslation(
470 line.substring(pos + 1, line.length()));
471
472 value = _fixEnglishTranslation(key, value);
473
474 if (_portalLanguageProperties != null) {
475 String portalValue = String.valueOf(
476 _portalLanguageProperties.get(key));
477
478 if (value.equals(portalValue)) {
479 System.out.println("Duplicate key " + key);
480 }
481 }
482
483 messages.add(key + "=" + value);
484 }
485 else {
486 if (begin == true && line.equals("")) {
487 _sortAndWrite(unsyncBufferedWriter, messages);
488 }
489
490 if (line.equals("")) {
491 begin = !begin;
492 }
493
494 unsyncBufferedWriter.write(line);
495 unsyncBufferedWriter.newLine();
496 }
497
498 unsyncBufferedWriter.flush();
499 }
500
501 if (messages.size() > 0) {
502 _sortAndWrite(unsyncBufferedWriter, messages);
503 }
504
505 unsyncBufferedReader.close();
506 unsyncBufferedWriter.close();
507
508 return FileUtil.read(propertiesFile);
509 }
510
511 private void _sortAndWrite(
512 UnsyncBufferedWriter unsyncBufferedWriter, Set<String> messages)
513 throws IOException {
514
515 String[] messagesArray = messages.toArray(new String[messages.size()]);
516
517 for (int i = 0; i < messagesArray.length; i++) {
518 unsyncBufferedWriter.write(messagesArray[i]);
519 unsyncBufferedWriter.newLine();
520 }
521
522 messages.clear();
523 }
524
525 private String _translate(
526 String translationId, String key, String fromText, int limit) {
527
528 if (translationId.equals("en_ar") ||
529 translationId.equals("en_eu") ||
530 translationId.equals("en_bg") ||
531 translationId.equals("en_ca") ||
532 translationId.equals("en_hr") ||
533 translationId.equals("en_cs") ||
534 translationId.equals("en_da") ||
535 translationId.equals("en_fi") ||
536 translationId.equals("en_gl") ||
537 translationId.equals("en_iw") ||
538 translationId.equals("en_hi") ||
539 translationId.equals("en_hu") ||
540 translationId.equals("en_in") ||
541 translationId.equals("en_lo") ||
542 translationId.equals("en_nb") ||
543 translationId.equals("en_fa") ||
544 translationId.equals("en_pl") ||
545 translationId.equals("en_ro") ||
546 translationId.equals("en_ru") ||
547 translationId.equals("en_sr_RS") ||
548 translationId.equals("en_sr_RS_latin") ||
549 translationId.equals("en_sk") ||
550 translationId.equals("en_sl") ||
551 translationId.equals("en_sv") ||
552 translationId.equals("en_tr") ||
553 translationId.equals("en_uk") ||
554 translationId.equals("en_vi") ||
555 translationId.equals("en_et")) {
556
557
558
559
560
561
562
563 return null;
564 }
565
566 if (!_langTranslate) {
567 return null;
568 }
569
570
571
572 if (limit == 3) {
573 return null;
574 }
575
576 String toText = null;
577
578 try {
579 System.out.println(
580 "Translating " + translationId + " " + key + " " + fromText);
581
582 WebCacheItem wci = new TranslationWebCacheItem(
583 translationId, fromText);
584
585 Translation translation = (Translation)wci.convert("");
586
587 toText = translation.getToText();
588
589 if ((toText != null) && toText.contains("Babel Fish")) {
590 toText = null;
591 }
592 }
593 catch (Exception e) {
594 e.printStackTrace();
595 }
596
597
598
599 if (toText == null) {
600 return _translate(translationId, key, fromText, ++limit);
601 }
602
603 return toText;
604 }
605
606 private String _langDir;
607 private String _langFile;
608 private boolean _langTranslate;
609 private Properties _portalLanguageProperties;
610 private Properties _renameKeys;
611
612 }