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