diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/i18n/LocaleUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/i18n/LocaleUtils.java index 47d86c2af..eccb52101 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/i18n/LocaleUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/i18n/LocaleUtils.java @@ -51,11 +51,12 @@ public final class LocaleUtils { static { try (InputStream input = LocaleUtils.class.getResourceAsStream("/assets/lang/sublanguages.json")) { if (input != null) { - JsonUtils.fromJsonFully(input, JsonUtils.mapTypeOf(String.class, JsonUtils.listTypeOf(String.class))).forEach((parent, subList) -> { - for (String subLanguage : subList) { - subLanguageToParent.put(subLanguage, parent); - } - }); + JsonUtils.fromJsonFully(input, JsonUtils.mapTypeOf(String.class, JsonUtils.listTypeOf(String.class))) + .forEach((parent, subList) -> { + for (String subLanguage : subList) { + subLanguageToParent.put(subLanguage, parent); + } + }); } } catch (IOException e) { LOG.warning("Failed to load sublanguages.json file", e); diff --git a/buildSrc/src/main/java/org/jackhuang/hmcl/gradle/l10n/CreateLanguageList.java b/buildSrc/src/main/java/org/jackhuang/hmcl/gradle/l10n/CreateLanguageList.java index 3e887bdc8..011543e13 100644 --- a/buildSrc/src/main/java/org/jackhuang/hmcl/gradle/l10n/CreateLanguageList.java +++ b/buildSrc/src/main/java/org/jackhuang/hmcl/gradle/l10n/CreateLanguageList.java @@ -17,6 +17,8 @@ */ package org.jackhuang.hmcl.gradle.l10n; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; import org.gradle.api.file.DirectoryProperty; @@ -56,7 +58,7 @@ public abstract class CreateLanguageList extends DefaultTask { throw new GradleException("Input directory not exists: " + inputDir); - SortedSet locales = new TreeSet<>(CreateLanguageList::compareLocale); + SortedSet locales = new TreeSet<>(new LocaleComparator()); locales.addAll(getAdditionalLanguages().getOrElse(List.of()).stream() .map(Locale::forLanguageTag) .toList()); @@ -99,27 +101,75 @@ public abstract class CreateLanguageList extends DefaultTask { .collect(Collectors.joining(",\n", "[\n", "\n]"))); } - private static int compareLanguage(String l1, String l2) { - return l1.compareTo(l2); // TODO - } + private final class LocaleComparator implements Comparator { + Map subLanguageToParent = new HashMap<>(); - private static int compareLocale(Locale l1, Locale l2) { - int c = compareLanguage(l1.getLanguage(), l2.getLanguage()); - if (c != 0) - return c; + { + Path file = getProject().getRootProject().getLayout().getProjectDirectory() + .file("HMCLCore/src/main/resources/assets/lang/sublanguages.json").getAsFile().toPath(); - c = l1.getScript().compareTo(l2.getScript()); - if (c != 0) - return c; + try (var reader = Files.newBufferedReader(file)) { + new Gson().fromJson(reader, new TypeToken>>() { + }).forEach((parent, subList) -> { + for (String subLanguage : subList) { + subLanguageToParent.put(subLanguage, parent); + } + }); + } catch (IOException e) { + throw new GradleException(e.getMessage(), e); + } + } - c = l1.getCountry().compareTo(l2.getCountry()); - if (c != 0) - return c; + private List resolveLanguage(String language) { + List langList = new ArrayList<>(); - c = l1.getVariant().compareTo(l2.getVariant()); - if (c != 0) - return c; + String lang = language; + while (true) { + langList.add(0, lang); + + String parent = subLanguageToParent.get(lang); + if (parent != null) { + lang = parent; + } else { + return langList; + } + } + } + + private int compareLanguage(String l1, String l2) { + var list1 = resolveLanguage(l1); + var list2 = resolveLanguage(l2); + + int n = Math.min(list1.size(), list2.size()); + for (int i = 0; i < n; i++) { + int c = list1.get(i).compareTo(list2.get(i)); + if (c != 0) + return c; + } + + return Integer.compare(list1.size(), list2.size()); + } + + @Override + public int compare(Locale l1, Locale l2) { + int c = compareLanguage(l1.getLanguage(), l2.getLanguage()); + if (c != 0) + return c; + + c = l1.getScript().compareTo(l2.getScript()); + if (c != 0) + return c; + + c = l1.getCountry().compareTo(l2.getCountry()); + if (c != 0) + return c; + + c = l1.getVariant().compareTo(l2.getVariant()); + if (c != 0) + return c; + + return l1.toString().compareTo(l2.toLanguageTag()); + } - return l1.toString().compareTo(l2.toLanguageTag()); } }