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