优化对颠倒的英语的支持 (#4577)
This commit is contained in:
@@ -72,6 +72,7 @@ import org.jackhuang.hmcl.util.Holder;
|
||||
import org.jackhuang.hmcl.util.Lang;
|
||||
import org.jackhuang.hmcl.util.StringUtils;
|
||||
import org.jackhuang.hmcl.util.TaskCancellationAction;
|
||||
import org.jackhuang.hmcl.util.i18n.I18n;
|
||||
import org.jackhuang.hmcl.util.javafx.BindingMapping;
|
||||
import org.jackhuang.hmcl.util.javafx.MappedObservableList;
|
||||
|
||||
@@ -115,6 +116,10 @@ public final class MainPage extends StackPane implements DecoratorPage {
|
||||
|
||||
ImageView titleIcon = new ImageView(FXUtils.newBuiltinImage("/assets/img/icon-title.png"));
|
||||
Label titleLabel = new Label(Metadata.FULL_TITLE);
|
||||
if (I18n.isUpsideDown()) {
|
||||
titleIcon.setRotate(180);
|
||||
titleLabel.setRotate(180);
|
||||
}
|
||||
titleLabel.getStyleClass().add("jfx-decorator-title");
|
||||
titleNode.getChildren().setAll(titleIcon, titleLabel);
|
||||
|
||||
|
||||
@@ -43,6 +43,10 @@ public final class I18n {
|
||||
return locale;
|
||||
}
|
||||
|
||||
public static boolean isUpsideDown() {
|
||||
return LocaleUtils.getScript(locale.getLocale()).equals("Qabs");
|
||||
}
|
||||
|
||||
public static boolean isUseChinese() {
|
||||
return LocaleUtils.isChinese(locale.getLocale());
|
||||
}
|
||||
|
||||
@@ -17,37 +17,46 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.util.i18n;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||
|
||||
/// @author Glavo
|
||||
public final class UpsideDownUtils {
|
||||
private static final Map<Integer, Integer> MAPPER = new LinkedHashMap<>();
|
||||
private static final Map<Integer, Integer> MAPPER = loadMap();
|
||||
|
||||
private static void putChars(char baseChar, String upsideDownChars) {
|
||||
for (int i = 0; i < upsideDownChars.length(); i++) {
|
||||
MAPPER.put(baseChar + i, (int) upsideDownChars.charAt(i));
|
||||
private static Map<Integer, Integer> loadMap() {
|
||||
var map = new LinkedHashMap<Integer, Integer>();
|
||||
|
||||
InputStream inputStream = UpsideDownUtils.class.getResourceAsStream("/assets/lang/upside_down.txt");
|
||||
if (inputStream != null) {
|
||||
try (inputStream) {
|
||||
new String(inputStream.readAllBytes(), StandardCharsets.UTF_8).lines().forEach(line -> {
|
||||
if (line.isBlank() || line.startsWith("#"))
|
||||
return;
|
||||
|
||||
if (line.length() != 2) {
|
||||
LOG.warning("Invalid line: " + line);
|
||||
return;
|
||||
}
|
||||
|
||||
map.put((int) line.charAt(0), (int) line.charAt(1));
|
||||
});
|
||||
} catch (IOException e) {
|
||||
LOG.warning("Failed to load upside_down.txt", e);
|
||||
}
|
||||
} else {
|
||||
LOG.warning("upside_down.txt not found");
|
||||
}
|
||||
}
|
||||
|
||||
private static void putChars(String baseChars, String upsideDownChars) {
|
||||
if (baseChars.length() != upsideDownChars.length()) {
|
||||
throw new IllegalArgumentException("baseChars and upsideDownChars must have same length");
|
||||
}
|
||||
|
||||
for (int i = 0; i < baseChars.length(); i++) {
|
||||
MAPPER.put((int) baseChars.charAt(i), (int) upsideDownChars.charAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
putChars('a', "ɐqɔpǝɟbɥıظʞןɯuodbɹsʇnʌʍxʎz");
|
||||
putChars('A', "ⱯᗺƆᗡƎℲ⅁HIſʞꞀWNOԀὉᴚS⟘∩ΛMXʎZ");
|
||||
putChars('0', "0ƖᘔƐㄣϛ9ㄥ86");
|
||||
putChars("_,;.?!/\\'", "‾'⸵˙¿¡/\\,");
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
public static String translate(String str) {
|
||||
@@ -56,7 +65,7 @@ public final class UpsideDownUtils {
|
||||
return builder.reverse().toString();
|
||||
}
|
||||
|
||||
private static DateTimeFormatter BASE_FORMATTER = DateTimeFormatter.ofPattern("MMM d, yyyy, h:mm:ss a")
|
||||
private static final DateTimeFormatter BASE_FORMATTER = DateTimeFormatter.ofPattern("MMM d, yyyy, h:mm:ss a")
|
||||
.withZone(ZoneId.systemDefault());
|
||||
|
||||
public static String formatDateTime(TemporalAccessor time) {
|
||||
|
||||
71
HMCLCore/src/main/resources/assets/lang/upside_down.txt
Normal file
71
HMCLCore/src/main/resources/assets/lang/upside_down.txt
Normal file
@@ -0,0 +1,71 @@
|
||||
aɐ
|
||||
bq
|
||||
cɔ
|
||||
dp
|
||||
eǝ
|
||||
fɟ
|
||||
gᵷ
|
||||
hɥ
|
||||
iᴉ
|
||||
jɾ
|
||||
kʞ
|
||||
lꞁ
|
||||
mɯ
|
||||
nu
|
||||
oo
|
||||
pd
|
||||
qb
|
||||
rɹ
|
||||
ss
|
||||
tʇ
|
||||
un
|
||||
vʌ
|
||||
wʍ
|
||||
xx
|
||||
yʎ
|
||||
zz
|
||||
AⱯ
|
||||
Bᗺ
|
||||
CƆ
|
||||
Dᗡ
|
||||
EƎ
|
||||
FℲ
|
||||
G⅁
|
||||
HH
|
||||
II
|
||||
Jſ
|
||||
Kʞ
|
||||
LꞀ
|
||||
MW
|
||||
NN
|
||||
OO
|
||||
PԀ
|
||||
QὉ
|
||||
Rᴚ
|
||||
SS
|
||||
T⟘
|
||||
U∩
|
||||
VΛ
|
||||
WM
|
||||
XX
|
||||
Yʎ
|
||||
ZZ
|
||||
00
|
||||
1Ɩ
|
||||
2ᘔ
|
||||
3Ɛ
|
||||
4ㄣ
|
||||
5ϛ
|
||||
69
|
||||
7ㄥ
|
||||
88
|
||||
96
|
||||
_‾
|
||||
,'
|
||||
;⸵
|
||||
.˙
|
||||
?¿
|
||||
!¡
|
||||
//
|
||||
\\
|
||||
',
|
||||
@@ -18,18 +18,18 @@
|
||||
package org.jackhuang.hmcl.gradle.l10n;
|
||||
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.tasks.InputFile;
|
||||
import org.gradle.api.tasks.OutputFile;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -75,29 +75,31 @@ public abstract class UpsideDownTranslate extends DefaultTask {
|
||||
}
|
||||
|
||||
static final class Translator {
|
||||
private static final Map<Integer, Integer> MAPPER = new LinkedHashMap<>();
|
||||
private static final Map<Integer, Integer> MAPPER = loadMap();
|
||||
|
||||
private static void putChars(char baseChar, String upsideDownChars) {
|
||||
for (int i = 0; i < upsideDownChars.length(); i++) {
|
||||
MAPPER.put(baseChar + i, (int) upsideDownChars.charAt(i));
|
||||
private static Map<Integer, Integer> loadMap() {
|
||||
var map = new LinkedHashMap<Integer, Integer>();
|
||||
|
||||
InputStream inputStream = UpsideDownTranslate.class.getResourceAsStream("upside_down.txt");
|
||||
if (inputStream != null) {
|
||||
try (inputStream) {
|
||||
new String(inputStream.readAllBytes(), StandardCharsets.UTF_8).lines().forEach(line -> {
|
||||
if (line.isBlank() || line.startsWith("#"))
|
||||
return;
|
||||
|
||||
if (line.length() != 2) {
|
||||
throw new GradleException("Invalid line: " + line);
|
||||
}
|
||||
|
||||
map.put((int) line.charAt(0), (int) line.charAt(1));
|
||||
});
|
||||
} catch (IOException e) {
|
||||
throw new GradleException("Failed to load upside_down.txt", e);
|
||||
}
|
||||
} else {
|
||||
throw new GradleException("upside_down.txt not found");
|
||||
}
|
||||
}
|
||||
|
||||
private static void putChars(String baseChars, String upsideDownChars) {
|
||||
if (baseChars.length() != upsideDownChars.length()) {
|
||||
throw new IllegalArgumentException("baseChars and upsideDownChars must have same length");
|
||||
}
|
||||
|
||||
for (int i = 0; i < baseChars.length(); i++) {
|
||||
MAPPER.put((int) baseChars.charAt(i), (int) upsideDownChars.charAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
putChars('a', "ɐqɔpǝɟbɥıظʞןɯuodbɹsʇnʌʍxʎz");
|
||||
putChars('A', "ⱯᗺƆᗡƎℲ⅁HIſʞꞀWNOԀὉᴚS⟘∩ΛMXʎZ");
|
||||
putChars('0', "0ƖᘔƐㄣϛ9ㄥ86");
|
||||
putChars("_,;.?!/\\'", "‾'⸵˙¿¡/\\,");
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
private static final Pattern FORMAT_PATTERN = Pattern.compile("^%(\\d\\$)?(\\d+)?(\\.\\d+)?([sdf])");
|
||||
|
||||
Reference in New Issue
Block a user