1 package com.jsql.view.swing.dialog.translate;
2
3 import com.jsql.util.ConnectionUtil;
4 import com.jsql.util.I18nUtil;
5 import com.jsql.util.LogLevelUtil;
6 import com.jsql.util.PropertiesUtil;
7 import com.jsql.view.swing.dialog.DialogTranslate;
8 import com.jsql.view.swing.util.MediatorHelper;
9 import org.apache.commons.lang3.StringUtils;
10 import org.apache.logging.log4j.LogManager;
11 import org.apache.logging.log4j.Logger;
12 import org.apache.logging.log4j.util.Strings;
13
14 import javax.swing.*;
15 import java.io.IOException;
16 import java.io.StringReader;
17 import java.math.BigDecimal;
18 import java.math.RoundingMode;
19 import java.net.URISyntaxException;
20 import java.nio.charset.StandardCharsets;
21 import java.nio.file.Files;
22 import java.nio.file.Paths;
23 import java.util.Locale;
24 import java.util.Properties;
25 import java.util.ResourceBundle;
26 import java.util.regex.Matcher;
27 import java.util.regex.Pattern;
28
29 public class WorkerTranslateInto extends SwingWorker<Object, Object> {
30
31 private static final Logger LOGGER = LogManager.getRootLogger();
32
33 private final Properties propertiesLanguageToTranslate = new Properties();
34 private final SortedProperties propertiesRoot = new SortedProperties();
35 private final StringBuilder propertiesToTranslate = new StringBuilder();
36 private final DialogTranslate dialogTranslate;
37
38 private final ConnectionUtil connectionUtil = MediatorHelper.model().getMediatorUtils().connectionUtil();
39 private final PropertiesUtil propertiesUtil = MediatorHelper.model().getMediatorUtils().propertiesUtil();
40
41 private static final String LINE_FEED_ESCAPE = "{@|@}";
42 private static final String LINE_FEED = "\\\\[\n\r]+";
43
44 public WorkerTranslateInto(DialogTranslate dialogTranslate) {
45 this.dialogTranslate = dialogTranslate;
46 }
47
48 @Override
49 protected Object doInBackground() throws Exception {
50 Thread.currentThread().setName("SwingWorkerDialogTranslate");
51 this.dialogTranslate.getProgressBarTranslation().setVisible(this.dialogTranslate.getLanguageInto() != Language.OT);
52 try {
53 this.loadFromGithub();
54 } catch (IOException eGithub) {
55 this.logFileNotFound(eGithub);
56 } finally {
57 this.displayDiff();
58 }
59 var localeInto = Locale.forLanguageTag(this.dialogTranslate.getLanguageInto().getLanguageTag());
60 LOGGER.log(
61 LogLevelUtil.CONSOLE_SUCCESS,
62 "Remaining text to translate into {}{} loaded, send any part translated to contribute",
63 () -> localeInto.getDisplayLanguage(localeInto),
64 () -> Strings.isBlank(localeInto.getCountry()) ? StringUtils.EMPTY : " ("+ localeInto.getCountry() +")"
65 );
66 return null;
67 }
68
69 private void displayDiff() {
70 this.propertiesRoot.entrySet().stream()
71 .filter(key ->
72 this.dialogTranslate.getLanguageInto() == Language.OT
73 || this.propertiesLanguageToTranslate.isEmpty()
74 || !this.propertiesLanguageToTranslate.containsKey(key.getKey())
75 )
76 .forEach(key -> this.propertiesToTranslate.append(
77 String.format("%n%n%s=%s", key.getKey(), key.getValue().toString().replace(WorkerTranslateInto.LINE_FEED_ESCAPE,"\\\n"))
78 ));
79
80 this.dialogTranslate.setTextBeforeChange(this.propertiesToTranslate.toString().trim());
81 this.dialogTranslate.getButtonSend().setEnabled(true);
82 this.dialogTranslate.getTextToTranslate().setText(this.dialogTranslate.getTextBeforeChange());
83 this.dialogTranslate.getTextToTranslate().setCaretPosition(0);
84 this.dialogTranslate.getTextToTranslate().setEditable(true);
85 if (this.dialogTranslate.getLanguageInto() != Language.OT) {
86 double percentTranslated = 100.0 * this.propertiesLanguageToTranslate.size() / this.propertiesRoot.size();
87 this.dialogTranslate.getProgressBarTranslation().setValue((int) percentTranslated);
88
89 var bundleInto = ResourceBundle.getBundle(I18nUtil.BASE_NAME, Locale.forLanguageTag(this.dialogTranslate.getLanguageInto().getLanguageTag()));
90 var localeInto = Locale.forLanguageTag(this.dialogTranslate.getLanguageInto().getLanguageTag());
91 this.dialogTranslate.getProgressBarTranslation().setString(
92 String.format(
93 "%s%% %s %s",
94 BigDecimal.valueOf(percentTranslated).setScale(1, RoundingMode.HALF_UP).doubleValue(),
95 bundleInto.getString("TRANSLATION_PROGRESS"),
96 localeInto.getDisplayLanguage(localeInto)
97 )
98 );
99 }
100 }
101
102 private void loadFromGithub() throws IOException, URISyntaxException {
103 this.loadRootFromGithub();
104 if (this.dialogTranslate.getLanguageInto() != Language.OT) {
105 this.loadLanguageFromGithub();
106 }
107 }
108
109 private void logFileNotFound(IOException e) throws IOException {
110 if (this.propertiesLanguageToTranslate.isEmpty()) {
111 LOGGER.log(LogLevelUtil.CONSOLE_INFORM, () -> I18nUtil.valueByKey("LOG_I18N_TEXT_NOT_FOUND"), e);
112 } else if (this.propertiesRoot.isEmpty()) {
113 throw new IOException("Reference language not found");
114 }
115 }
116
117 private void loadRootFromGithub() throws IOException, URISyntaxException {
118 try {
119 String pageSourceRoot = this.connectionUtil.getSourceLineFeed(
120 this.propertiesUtil.getProperty("github.webservice.i18n.root")
121 );
122 String pageSourceRootFixed = Pattern.compile(WorkerTranslateInto.LINE_FEED).matcher(Matcher.quoteReplacement(pageSourceRoot)).replaceAll(WorkerTranslateInto.LINE_FEED_ESCAPE);
123 this.propertiesRoot.load(new StringReader(pageSourceRootFixed));
124 } catch (IOException e) {
125 var uri = ClassLoader.getSystemResource("i18n/jsql.properties").toURI();
126 var path = Paths.get(uri);
127 byte[] root = Files.readAllBytes(path);
128 var rootI18n = new String(root, StandardCharsets.UTF_8);
129 String rootI18nFixed = Pattern.compile(WorkerTranslateInto.LINE_FEED).matcher(Matcher.quoteReplacement(rootI18n)).replaceAll(WorkerTranslateInto.LINE_FEED_ESCAPE);
130 this.propertiesRoot.load(new StringReader(rootI18nFixed));
131 LOGGER.log(LogLevelUtil.CONSOLE_INFORM, "Reference language loaded from local");
132 LOGGER.log(LogLevelUtil.IGNORE, e);
133 }
134 }
135
136 private void loadLanguageFromGithub() throws IOException, URISyntaxException {
137 try {
138 String pageSourceLanguage = this.connectionUtil.getSourceLineFeed(
139 String.format(
140 "%sjsql_%s.properties",
141 this.propertiesUtil.getProperty("github.webservice.i18n.locale"),
142 this.dialogTranslate.getLanguageInto().getLanguageTag().replace("-", "_")
143 )
144 );
145 this.propertiesLanguageToTranslate.load(new StringReader(pageSourceLanguage));
146 } catch (IOException e) {
147 var uri = ClassLoader.getSystemResource(
148 String.format(
149 "i18n/jsql_%s.properties",
150 this.dialogTranslate.getLanguageInto().getLanguageTag().replace("-", "_")
151 )
152 ).toURI();
153
154 var path = Paths.get(uri);
155 byte[] root = Files.readAllBytes(path);
156 var localeI18n = new String(root, StandardCharsets.UTF_8);
157 String localeI18nFixed = Pattern.compile(WorkerTranslateInto.LINE_FEED).matcher(localeI18n).replaceAll(WorkerTranslateInto.LINE_FEED_ESCAPE);
158
159 this.propertiesLanguageToTranslate.load(new StringReader(localeI18nFixed));
160 LOGGER.log(
161 LogLevelUtil.CONSOLE_INFORM,
162 String.format("GitHub failure, %s translation loaded from local", this.dialogTranslate.getLanguageInto())
163 );
164 LOGGER.log(LogLevelUtil.IGNORE, e);
165 }
166 }
167 }