使用 subname 匹配模组翻译 (#3231)

This commit is contained in:
Zkitefly
2025-10-08 22:36:19 +08:00
committed by GitHub
parent 25323dc385
commit 23037b8afc
2 changed files with 61 additions and 5 deletions

View File

@@ -388,7 +388,7 @@ final class ModListPageSkin extends SkinBase<ModListPage> {
parts.add(i18n("game.version") + ": " + localModFile.getGameVersion());
}
this.message = String.join(", ", parts);
this.mod = ModTranslations.MOD.getModById(localModFile.getId());
this.mod = ModTranslations.MOD.getMod(localModFile.getId(), localModFile.getName());
}
String getTitle() {

View File

@@ -64,9 +64,34 @@ public enum ModTranslations {
};
}
@SuppressWarnings("StatementWithEmptyBody")
private static String cleanSubname(String subname) {
if (StringUtils.isBlank(subname))
return "";
StringBuilder builder = new StringBuilder(subname.length());
for (int i = 0; i < subname.length(); ) {
int ch = subname.codePointAt(i);
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')
|| ".+\\".indexOf(ch) >= 0) {
builder.appendCodePoint(ch);
} else if (Character.isWhitespace(ch)
|| "':_-/&()[]{}|,!?~•".indexOf(ch) >= 0
|| ch >= 0x1F300 && ch <= 0x1FAFF) {
// Remove these unnecessary characters from subname
} else {
// The subname contains unsupported characters, so we do not use this subname to match the mod
return "";
}
i += Character.charCount(ch);
}
return builder.length() == subname.length() ? subname : builder.toString();
}
private final String resourceName;
private volatile List<Mod> mods;
private volatile Map<String, Mod> modIdMap; // mod id -> mod
private volatile Map<String, Mod> subnameMap;
private volatile Map<String, Mod> curseForgeMap; // curseforge id -> mod
private volatile List<Pair<String, Mod>> keywords;
private volatile int maxKeywordLength = -1;
@@ -75,7 +100,7 @@ public enum ModTranslations {
this.resourceName = resourceName;
}
private @NotNull List<Mod> getMods() {
public @NotNull List<Mod> getMods() {
List<Mod> mods = this.mods;
if (mods != null)
return mods;
@@ -124,6 +149,29 @@ public enum ModTranslations {
}
}
private @NotNull Map<String, Mod> getSubnameMap() {
Map<String, Mod> subnameMap = this.subnameMap;
if (subnameMap != null)
return subnameMap;
synchronized (this) {
subnameMap = this.subnameMap;
if (subnameMap != null)
return subnameMap;
subnameMap = new HashMap<>();
List<Mod> mods = getMods();
for (Mod mod : mods) {
String subname = cleanSubname(mod.getSubname());
if (StringUtils.isNotBlank(subname)) {
subnameMap.put(subname, mod);
}
}
return this.subnameMap = subnameMap;
}
}
private @NotNull Map<String, Mod> getCurseForgeMap() {
Map<String, Mod> curseForgeMap = this.curseForgeMap;
if (curseForgeMap != null)
@@ -198,10 +246,18 @@ public enum ModTranslations {
}
@Nullable
public Mod getModById(String id) {
if (StringUtils.isBlank(id)) return null;
public Mod getMod(String id, String subname) {
subname = cleanSubname(subname);
if (StringUtils.isNotBlank(subname)) {
Mod mod = getSubnameMap().get(subname);
if (mod != null)
return mod;
}
if (StringUtils.isNotBlank(id))
return getModIdMap().get(id);
return null;
}
public abstract String getMcmodUrl(Mod mod);