mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-17 07:47:57 -04:00
优化 checkTranslations Task (#4396)
This commit is contained in:
parent
fe59f495f6
commit
09c17fc85b
@ -1,3 +1,4 @@
|
|||||||
|
import org.jackhuang.hmcl.gradle.CheckTranslations
|
||||||
import org.jackhuang.hmcl.gradle.mod.ParseModDataTask
|
import org.jackhuang.hmcl.gradle.mod.ParseModDataTask
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.nio.file.FileSystems
|
import java.nio.file.FileSystems
|
||||||
@ -332,6 +333,17 @@ tasks.register<JavaExec>("run") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check Translations
|
||||||
|
|
||||||
|
tasks.register<CheckTranslations>("checkTranslations") {
|
||||||
|
val dir = layout.projectDirectory.dir("src/main/resources/assets/lang")
|
||||||
|
|
||||||
|
englishFile.set(dir.file("I18N.properties"))
|
||||||
|
simplifiedChineseFile.set(dir.file("I18N_zh_CN.properties"))
|
||||||
|
traditionalChineseFile.set(dir.file("I18N_zh.properties"))
|
||||||
|
classicalChineseFile.set(dir.file("I18N_lzh.properties"))
|
||||||
|
}
|
||||||
|
|
||||||
// mcmod data
|
// mcmod data
|
||||||
|
|
||||||
tasks.register<ParseModDataTask>("parseModData") {
|
tasks.register<ParseModDataTask>("parseModData") {
|
||||||
|
@ -57,58 +57,6 @@ subprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register("checkTranslations") {
|
|
||||||
doLast {
|
|
||||||
val hmclLangDir = file("HMCL/src/main/resources/assets/lang")
|
|
||||||
|
|
||||||
val en = java.util.Properties().apply {
|
|
||||||
hmclLangDir.resolve("I18N.properties").bufferedReader().use { load(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
val zh = java.util.Properties().apply {
|
|
||||||
hmclLangDir.resolve("I18N_zh.properties").bufferedReader().use { load(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
val zh_CN = java.util.Properties().apply {
|
|
||||||
hmclLangDir.resolve("I18N_zh_CN.properties").bufferedReader().use { load(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
var success = true
|
|
||||||
|
|
||||||
zh_CN.forEach {
|
|
||||||
if (!en.containsKey(it.key)) {
|
|
||||||
project.logger.warn("I18N.properties missing key '${it.key}'")
|
|
||||||
success = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
zh_CN.forEach {
|
|
||||||
if (!zh.containsKey(it.key)) {
|
|
||||||
project.logger.warn("I18N_zh.properties missing key '${it.key}'")
|
|
||||||
success = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
zh_CN.forEach {
|
|
||||||
if (it.value.toString().contains("帐户")) {
|
|
||||||
project.logger.warn("The misspelled '帐户' in '${it.key}' should be replaced by '账户'")
|
|
||||||
success = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
zh_CN.forEach {
|
|
||||||
if (it.value.toString().contains("其它")) {
|
|
||||||
project.logger.warn("The misspelled '其它' in '${it.key}' should be replaced by '其他'")
|
|
||||||
success = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
throw GradleException("Part of the translation is missing")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
org.jackhuang.hmcl.gradle.javafx.JavaFXUtils.register(rootProject)
|
org.jackhuang.hmcl.gradle.javafx.JavaFXUtils.register(rootProject)
|
||||||
|
|
||||||
defaultTasks("clean", "build")
|
defaultTasks("clean", "build")
|
||||||
|
@ -8,6 +8,6 @@ dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
sourceCompatibility = JavaVersion.VERSION_11
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
targetCompatibility = JavaVersion.VERSION_11
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
}
|
}
|
@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher
|
||||||
|
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.gradle;
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask;
|
||||||
|
import org.gradle.api.GradleException;
|
||||||
|
import org.gradle.api.file.RegularFileProperty;
|
||||||
|
import org.gradle.api.logging.Logger;
|
||||||
|
import org.gradle.api.logging.Logging;
|
||||||
|
import org.gradle.api.tasks.InputFile;
|
||||||
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
/// @author Glavo
|
||||||
|
public abstract class CheckTranslations extends DefaultTask {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logging.getLogger(CheckTranslations.class);
|
||||||
|
|
||||||
|
@InputFile
|
||||||
|
public abstract RegularFileProperty getEnglishFile();
|
||||||
|
|
||||||
|
@InputFile
|
||||||
|
public abstract RegularFileProperty getSimplifiedChineseFile();
|
||||||
|
|
||||||
|
@InputFile
|
||||||
|
public abstract RegularFileProperty getTraditionalChineseFile();
|
||||||
|
|
||||||
|
@InputFile
|
||||||
|
public abstract RegularFileProperty getClassicalChineseFile();
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
public void run() throws IOException {
|
||||||
|
Checker checker = new Checker();
|
||||||
|
|
||||||
|
var english = new PropertiesFile(getEnglishFile());
|
||||||
|
var simplifiedChinese = new PropertiesFile(getSimplifiedChineseFile());
|
||||||
|
var traditionalChinese = new PropertiesFile(getTraditionalChineseFile());
|
||||||
|
var classicalChinese = new PropertiesFile(getClassicalChineseFile());
|
||||||
|
|
||||||
|
simplifiedChinese.forEach((key, value) -> {
|
||||||
|
checker.checkKeyExists(english, key);
|
||||||
|
checker.checkKeyExists(traditionalChinese, key);
|
||||||
|
|
||||||
|
checker.checkMisspelled(simplifiedChinese, key, value, "账户", "帐户");
|
||||||
|
checker.checkMisspelled(simplifiedChinese, key, value, "其他", "其它");
|
||||||
|
});
|
||||||
|
|
||||||
|
classicalChinese.forEach((key, value) -> {
|
||||||
|
checker.checkMisspelled(classicalChinese, key, value, "綫", "線");
|
||||||
|
checker.checkMisspelled(classicalChinese, key, value, "爲", "為");
|
||||||
|
checker.checkMisspelled(classicalChinese, key, value, "啟", "啓");
|
||||||
|
});
|
||||||
|
|
||||||
|
checker.check();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class PropertiesFile {
|
||||||
|
final Path path;
|
||||||
|
final Properties properties = new Properties();
|
||||||
|
|
||||||
|
PropertiesFile(RegularFileProperty property) throws IOException {
|
||||||
|
this(property.getAsFile().get().toPath().toAbsolutePath().normalize());
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertiesFile(Path path) throws IOException {
|
||||||
|
this.path = path;
|
||||||
|
try (var reader = Files.newBufferedReader(path)) {
|
||||||
|
properties.load(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileName() {
|
||||||
|
return path.getFileName().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void forEach(BiConsumer<String, String> consumer) {
|
||||||
|
properties.forEach((key, value) -> consumer.accept(key.toString(), value.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class Checker {
|
||||||
|
|
||||||
|
private final Map<PropertiesFile, Map<Class<?>, Set<Problem>>> problems = new LinkedHashMap<>();
|
||||||
|
private int problemsCount;
|
||||||
|
|
||||||
|
public void checkKeyExists(PropertiesFile file, String key) {
|
||||||
|
if (!file.properties.containsKey(key)) {
|
||||||
|
onFailure(file, new Problem.MissingKey(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkMisspelled(PropertiesFile file, String key, String value,
|
||||||
|
String correct, String misspelled) {
|
||||||
|
if (value.contains(misspelled)) {
|
||||||
|
onFailure(file, new Problem.Misspelled(correct, misspelled));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onFailure(PropertiesFile file, Problem problem) {
|
||||||
|
problemsCount++;
|
||||||
|
problems.computeIfAbsent(file, ignored -> new HashMap<>())
|
||||||
|
.computeIfAbsent(problem.getClass(), ignored -> new LinkedHashSet<>())
|
||||||
|
.add(problem);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void check() {
|
||||||
|
if (problemsCount > 0) {
|
||||||
|
problems.forEach((file, problems) -> {
|
||||||
|
problems.values().stream().flatMap(Collection::stream).forEach(problem ->
|
||||||
|
LOGGER.warn("{}: {}", file.getFileName(), problem.getMessage()));
|
||||||
|
});
|
||||||
|
|
||||||
|
throw new GradleException("Failed to check translations, " + problemsCount + " found problems.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static abstract sealed class Problem {
|
||||||
|
public abstract String getMessage();
|
||||||
|
|
||||||
|
private static final class MissingKey extends Problem {
|
||||||
|
private final String key;
|
||||||
|
|
||||||
|
MissingKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return "missing key '%s'".formatted(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class Misspelled extends Problem {
|
||||||
|
private final String correct;
|
||||||
|
private final String misspelled;
|
||||||
|
|
||||||
|
Misspelled(String correct, String misspelled) {
|
||||||
|
this.correct = correct;
|
||||||
|
this.misspelled = misspelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return "misspelled '%s' should be replaced by '%s'".formatted(misspelled, correct);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return misspelled.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
return obj instanceof Misspelled that && this.misspelled.equals(that.misspelled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user