Skip to content

Commit 49fd420

Browse files
committed
CrowdinOTA now working
1 parent 692e05d commit 49fd420

File tree

4 files changed

+123
-69
lines changed

4 files changed

+123
-69
lines changed

pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,5 +961,13 @@
961961
<version>1.0-SNAPSHOT</version>
962962
<scope>compile</scope>
963963
</dependency>
964+
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
965+
<dependency>
966+
<groupId>com.squareup.okhttp3</groupId>
967+
<artifactId>okhttp</artifactId>
968+
<version>4.9.1</version>
969+
<scope>compile</scope>
970+
</dependency>
971+
964972
</dependencies>
965973
</project>

src/main/java/org/maxgamer/quickshop/shop/InventoryPreview.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ public InventoryPreview(@NotNull QuickShop plugin, @NotNull ItemStack itemStack)
6969
} else {
7070
itemMeta = plugin.getServer().getItemFactory().getItemMeta(itemStack.getType());
7171
}
72-
previewStr = plugin.text().of(player, "quickshop-gui-preview").forLocale();
73-
//previewStr="Preview Test";
72+
//TODO Locale
73+
previewStr="Preview Item";
7474
if (itemMeta != null) {
7575
if (itemMeta.hasLore()) {
7676
itemMeta.getLore().add(previewStr);

src/main/java/org/maxgamer/quickshop/util/language/text/TextManager.java

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public TextManager(QuickShop plugin) {
3939
this.plugin = plugin;
4040
this.distribution = new CrowdinOTA(plugin);
4141
this.overrideFilesFolder = new File(plugin.getDataFolder(), "lang-override");
42+
this.overrideFilesFolder.mkdirs();
4243
load();
4344
}
4445

@@ -54,16 +55,19 @@ public void load() {
5455
} catch (IOException | InvalidConfigurationException ignored) {
5556
bundledLang = new JsonConfiguration();
5657
}
57-
for (String availableLanguage : distribution.getAvailableLanguages()) {
58+
distribution.getAvailableLanguages().parallelStream().forEach(availableLanguage -> {
5859
try {
59-
// load OTA text
60-
String localeFileContent = distribution.getFile(languageFileCrowdin, availableLanguage);
60+
// load OTA text from Crowdin
61+
Util.debugLog("Loading translation for locale: " + availableLanguage);
6162
Map<String, JsonConfiguration> fileLocaleMapping = locale2ContentMapping.computeIfAbsent(languageFileCrowdin, k -> new HashMap<>());
6263
JsonConfiguration configuration = new JsonConfiguration();
64+
try {
65+
configuration.loadFromString(distribution.getFile(languageFileCrowdin, availableLanguage));
66+
} catch (InvalidConfigurationException exception) {
67+
configuration.loadFromString(distribution.getFile(languageFileCrowdin, availableLanguage, true));
68+
}
6369
fileLocaleMapping.put(availableLanguage, configuration);
64-
plugin.getLogger().info(localeFileContent);
65-
configuration.loadFromString(localeFileContent);
66-
// load override text
70+
// load override text (allow user modification the translation)
6771
JsonConfiguration override = new JsonConfiguration();
6872
File localOverrideFile = new File(overrideFilesFolder, availableLanguage + ".json");
6973
if (localOverrideFile.exists()) {
@@ -72,36 +76,44 @@ public void load() {
7276
configuration.set(key, override.get(key));
7377
}
7478
}
79+
Util.debugLog("Locale: " + availableLanguage + " has been successfully loaded.");
80+
} catch (CrowdinOTA.OTAException e) {
81+
plugin.getLogger().warning("Couldn't update the translation for locale " + availableLanguage + " because it not configured, please report to QuickShop");
82+
} catch (IOException e) {
83+
plugin.getLogger().log(Level.WARNING, "Couldn't update the translation for locale " + availableLanguage + " please check your network connection.", e);
7584
} catch (Exception e) {
76-
if(e.getMessage().contains("Did not get expected response code, got 403 for")) {
77-
plugin.getLogger().log(Level.WARNING, "The language " + availableLanguage+" didn't configure correctly, please report to QuickShop.", e);
78-
continue;
79-
}
80-
plugin.getLogger().log(Level.WARNING, "Couldn't update the translation for locale " + availableLanguage, e);
85+
plugin.getLogger().log(Level.WARNING, "Couldn't update the translation for locale " + availableLanguage + ".", e);
8186
}
82-
}
87+
});
88+
89+
// for (String availableLanguage : distribution.getAvailableLanguages()) {
90+
//
91+
// }
8392
postProcessors.add(new FillerProcessor());
8493
postProcessors.add(new ColorProcessor());
8594
postProcessors.add(new PlaceHolderApiProcessor());
8695
}
8796

8897
public Text of(@NotNull String path, String... args) {
89-
return new Text(this, (CommandSender)null, locale2ContentMapping.get(languageFileCrowdin), path, args);
98+
return new Text(this, (CommandSender) null, locale2ContentMapping.get(languageFileCrowdin), path, args);
9099
}
91100

92101
public Text of(@Nullable CommandSender sender, @NotNull String path, String... args) {
93102
return new Text(this, sender, locale2ContentMapping.get(languageFileCrowdin), path, args);
94103
}
104+
95105
public Text of(@Nullable UUID sender, @NotNull String path, String... args) {
96106
return new Text(this, sender, locale2ContentMapping.get(languageFileCrowdin), path, args);
97107
}
108+
98109
public TextList ofList(@NotNull String path, String... args) {
99110
return new TextList(this, (CommandSender) null, locale2ContentMapping.get(languageFileCrowdin), path, args);
100111
}
101112

102113
public TextList ofList(@Nullable UUID sender, @NotNull String path, String... args) {
103114
return new TextList(this, sender, locale2ContentMapping.get(languageFileCrowdin), path, args);
104115
}
116+
105117
public TextList ofList(@Nullable CommandSender sender, @NotNull String path, String... args) {
106118
return new TextList(this, sender, locale2ContentMapping.get(languageFileCrowdin), path, args);
107119
}
@@ -126,7 +138,7 @@ private TextList(TextManager manager, CommandSender sender, Map<String, JsonConf
126138
private TextList(TextManager manager, UUID sender, Map<String, JsonConfiguration> mapping, String path, String... args) {
127139
this.plugin = manager.plugin;
128140
this.manager = manager;
129-
if(sender != null)
141+
if (sender != null)
130142
this.sender = Bukkit.getPlayer(sender);
131143
else
132144
this.sender = null;
@@ -175,7 +187,7 @@ public List<String> forLocale() {
175187
}
176188

177189
public void send() {
178-
if(sender == null)
190+
if (sender == null)
179191
return;
180192
for (String s : forLocale()) {
181193
if (StringUtils.isEmpty(s))
@@ -205,7 +217,7 @@ private Text(TextManager manager, CommandSender sender, Map<String, JsonConfigur
205217
private Text(TextManager manager, UUID sender, Map<String, JsonConfiguration> mapping, String path, String... args) {
206218
this.plugin = manager.plugin;
207219
this.manager = manager;
208-
if(sender != null)
220+
if (sender != null)
209221
this.sender = Bukkit.getPlayer(sender);
210222
else
211223
this.sender = null;
@@ -252,13 +264,13 @@ public String forLocale() {
252264
}
253265

254266
public void send() {
255-
if(sender == null)
267+
if (sender == null)
256268
return;
257269
String lang = forLocale();
258270
if (StringUtils.isEmpty(lang))
259271
return;
260-
MsgUtil.sendDirectMessage(sender,lang);
261-
// plugin.getQuickChat().send(sender, lang);
272+
MsgUtil.sendDirectMessage(sender, lang);
273+
// plugin.getQuickChat().send(sender, lang);
262274
}
263275
}
264276
}

src/main/java/org/maxgamer/quickshop/util/language/text/distributions/crowdin/CrowdinOTA.java

Lines changed: 82 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,85 +5,99 @@
55
import com.google.gson.JsonElement;
66
import com.google.gson.JsonParser;
77
import com.google.gson.JsonPrimitive;
8+
import lombok.AllArgsConstructor;
9+
import lombok.Builder;
10+
import lombok.Data;
11+
import lombok.EqualsAndHashCode;
12+
import okhttp3.OkHttpClient;
13+
import okhttp3.Request;
14+
import okhttp3.Response;
815
import org.apache.commons.codec.digest.DigestUtils;
9-
import org.apache.commons.lang.StringUtils;
1016
import org.bukkit.configuration.file.YamlConfiguration;
1117
import org.jetbrains.annotations.NotNull;
1218
import org.jetbrains.annotations.Nullable;
1319
import org.maxgamer.quickshop.QuickShop;
14-
import org.maxgamer.quickshop.nonquickshopstuff.com.sk89q.worldedit.util.net.HttpRequest;
1520
import org.maxgamer.quickshop.util.JsonUtil;
1621
import org.maxgamer.quickshop.util.Util;
1722
import org.maxgamer.quickshop.util.language.text.distributions.Distribution;
1823
import org.maxgamer.quickshop.util.language.text.distributions.crowdin.bean.Manifest;
1924

2025
import java.io.File;
2126
import java.io.IOException;
22-
import java.net.URL;
2327
import java.nio.charset.StandardCharsets;
28+
import java.nio.file.Files;
29+
import java.nio.file.StandardOpenOption;
2430
import java.util.*;
2531
import java.util.concurrent.TimeUnit;
2632
import java.util.logging.Level;
2733

2834
public class CrowdinOTA implements Distribution {
2935
protected static final String CROWDIN_OTA_HOST = "https://distributions.crowdin.net/daf1a8db40f132ce157c457xrm4/";
30-
protected final Cache<String, byte[]> requestCachePool = CacheBuilder.newBuilder()
36+
protected final Cache<String, String> requestCachePool = CacheBuilder.newBuilder()
37+
.initialCapacity(1)
3138
.expireAfterWrite(7, TimeUnit.DAYS)
3239
.recordStats()
3340
.build();
34-
private QuickShop plugin;
41+
private final QuickShop plugin;
42+
// private final File cacheFolder;
43+
// private final okhttp3.Cache cache;
44+
private final OkHttpClient client;
45+
// private final OkHttpClient clientNoCache;
3546

3647
public CrowdinOTA(QuickShop plugin) {
3748
this.plugin = plugin;
3849
Util.getCacheFolder().mkdirs();
39-
}
50+
// this.cacheFolder = new File(Util.getCacheFolder(), "okhttp");
51+
// this.cacheFolder.mkdirs();
52+
// this.cache = new okhttp3.Cache(cacheFolder, 100 * 1024 * 1024);
53+
// this.client = new OkHttpClient.Builder()
54+
// .cache(cache)
55+
// .build();
56+
this.client = new OkHttpClient.Builder()
57+
.build();
4058

41-
private byte[] requestWithCache(@NotNull String url, @Nullable File saveTo) throws IOException {
42-
byte[] data = requestCachePool.getIfPresent(url);
43-
if (data == null) {
44-
try {
45-
HttpRequest.BufferedResponse response = HttpRequest.get(new URL(url))
46-
.execute()
47-
.expectResponseCode(200)
48-
.returnContent();
49-
if (saveTo != null)
50-
response.saveContent(saveTo);
51-
return response.asBytes();
52-
} catch (InterruptedException e) {
53-
e.printStackTrace();
54-
}
55-
return null;
56-
}
57-
return data;
5859
}
5960

61+
// private byte[] requestWithCache(@NotNull String url, @Nullable File saveTo) throws IOException {
62+
// byte[] data = requestCachePool.getIfPresent(url);
63+
// if (data == null) {
64+
// CloseableHttpClient httpClient = HttpClientBuilder.create().build();
65+
// HttpGet getRequest = new HttpGet(url);
66+
// getRequest.setConfig(RequestConfig.custom()
67+
// .setSocketTimeout(30 * 1000)
68+
// .setConnectTimeout(20 * 1000).build());
69+
// CloseableHttpResponse response = httpClient.execute(getRequest);
70+
// data = Util.inputStream2ByteArray(response.getEntity().getContent());
71+
// if (response.getStatusLine().getStatusCode() != 200)
72+
// throw new OTAException(response.getStatusLine().getStatusCode(), new String(data == null ? new byte[0] : Util.inputStream2ByteArray(response.getEntity().getContent()), StandardCharsets.UTF_8));
73+
// if (saveTo != null && data != null)
74+
// Files.write(saveTo.toPath(), data, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
75+
// }
76+
// return data;
77+
// }
78+
6079
@Nullable
6180
public Manifest getManifest() {
62-
String url = CROWDIN_OTA_HOST + "manifest.json";
63-
String data = null;
64-
try {
65-
data = new String(requestWithCache(url,null), StandardCharsets.UTF_8);
66-
} catch (IOException e) {
67-
plugin.getLogger().log(Level.WARNING,"Failed to download manifest.json, multi-language system won't work");
68-
return null;
69-
}
70-
if (StringUtils.isEmpty(data))
71-
return null;
72-
return JsonUtil.getGson().fromJson(data, Manifest.class);
81+
return JsonUtil.getGson().fromJson(getManifestJson(), Manifest.class);
7382
}
7483

7584
@Nullable
7685
public String getManifestJson() {
7786
String url = CROWDIN_OTA_HOST + "manifest.json";
7887
String data;
79-
try {
80-
data = new String(requestWithCache(url,null), StandardCharsets.UTF_8);
88+
if (requestCachePool.getIfPresent(url) != null)
89+
return requestCachePool.getIfPresent(url);
90+
try (Response response = client.newCall(new Request.Builder().get().url(url).build()).execute()) {
91+
data = response.body().string();
92+
if (response.code() != 200) {
93+
plugin.getLogger().warning("Couldn't get manifest: " + response.code() + ", please report to QuickShop!");
94+
return null;
95+
}
96+
requestCachePool.put(url, data);
8197
} catch (IOException e) {
82-
plugin.getLogger().log(Level.WARNING,"Failed to download manifest.json, multi-language system won't work");
98+
plugin.getLogger().log(Level.WARNING, "Failed to download manifest.json, multi-language system won't work");
8399
return null;
84100
}
85-
if (StringUtils.isEmpty(data))
86-
return null;
87101
return data;
88102
}
89103

@@ -146,25 +160,45 @@ public String getFile(String fileCrowdinPath, String crowdinLocale, boolean forc
146160
File cachedDataFile = new File(Util.getCacheFolder(), pathHash);
147161
String data = null;
148162
if (cachedDataFile.exists()) {
163+
Util.debugLog("Reading data from local cache: " + cachedDataFile.getCanonicalPath());
149164
data = Util.readToString(cachedDataFile);
150165
}
151166
// invalidate cache, flush it
152167
if (forceFlush || data == null || localeTimestamp != manifest.getTimestamp()) {
153168
String url = CROWDIN_OTA_HOST + "content" + fileCrowdinPath.replace("%locale%", crowdinLocale);
154-
byte[] bin = requestWithCache(url,cachedDataFile);
155-
if (bin == null)
156-
throw new IOException("Couldn't download translation from remote server.");
169+
Util.debugLog("Reading data from remote server: " + url);
170+
try (Response response = client.newCall(new Request.Builder().get().url(url).build()).execute()) {
171+
data = response.body().string();
172+
if (response.code() != 200)
173+
throw new OTAException(response.code(), data);
174+
Files.write(cachedDataFile.toPath(), data.getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
175+
} catch (IOException e) {
176+
plugin.getLogger().log(Level.WARNING, "Failed to download manifest.json, multi-language system may won't work");
177+
return "";
178+
}
157179
// update cache index
158-
data = Util.readToString(cachedDataFile);
159180
cacheMetadata.set(pathHash + ".timestamp", manifest.getTimestamp());
160181
cacheMetadata.save(metadataFile);
161182
return data;
162183
}
163-
// if (data == null) {
164-
// cacheMetadata.set(pathHash, null);
165-
// cacheMetadata.save(metadataFile);
166-
// throw new IOException("Couldn't read translation from local cache, please try again");
167-
// }
168184
return data;
169185
}
186+
187+
@EqualsAndHashCode(callSuper = true)
188+
@AllArgsConstructor
189+
@Builder
190+
@Data
191+
public static class OTAException extends Exception {
192+
private int httpCode;
193+
private String content;
194+
}
195+
196+
@AllArgsConstructor
197+
@Builder
198+
@Data
199+
public static class CrowdinGetFileRequest {
200+
private String fileCrowdinPath;
201+
private String crowdinLocale;
202+
private boolean forceFlush;
203+
}
170204
}

0 commit comments

Comments
 (0)