diff --git a/bukkit/loader/src/main/resources/translations/en.yml b/bukkit/loader/src/main/resources/translations/en.yml
index 851f3889d..3c2e1dbed 100644
--- a/bukkit/loader/src/main/resources/translations/en.yml
+++ b/bukkit/loader/src/main/resources/translations/en.yml
@@ -54,7 +54,6 @@ command.search_usage.not_found: "No usage found for this item"
command.search_recipe.no_item: "Please hold an item before running this command"
command.search_usage.no_item: "Please hold an item before running this command"
command.totem.not_totem: "'' is not type of totem_of_undying"
-
warning.config.image.lack_height: "Issue found in file - The image '' is missing the required 'height' argument."
warning.config.image.height_smaller_than_ascent: "Issue found in file - The image '' violates the bitmap image rule: 'height' should be no lower than 'ascent'."
warning.config.image.no_file: "Issue found in file - The image '' is missing the required 'file' argument."
@@ -64,4 +63,5 @@ warning.config.image.lack_char: "Issue found in file - The image
warning.config.image.codepoint_in_use: "Issue found in file - The image '' is using a character[()] in font that has been used by another image ''."
warning.config.image.invalid_codepoint_grid: "Issue found in file - Image '' has an invalid 'chars' codepoint grind."
warning.config.image.file_not_exist: "Issue found in file - PNG file not found for image ''."
-warning.config.recipe.duplicated: "Issue found in file - Duplicated recipe ''."
\ No newline at end of file
+warning.config.recipe.duplicated: "Issue found in file - Duplicated recipe ''."
+warning.config.i18n.unknown_locale: "Issue found in file - Unknown locale ''."
\ No newline at end of file
diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java
index 7b7c042b2..a15a65564 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java
@@ -603,7 +603,7 @@ public abstract class AbstractPackManager implements PackManager {
}
private void generateClientLang(Path generatedPackPath) {
- for (Map.Entry entry : this.plugin.translationManager().clientLangManager().langData().entrySet()) {
+ for (Map.Entry entry : this.plugin.translationManager().clientLangData().entrySet()) {
JsonObject json = new JsonObject();
for (Map.Entry pair : entry.getValue().translations.entrySet()) {
json.addProperty(pair.getKey(), pair.getValue());
diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/obfuscation/ObfC.java b/core/src/main/java/net/momirealms/craftengine/core/pack/obfuscation/ObfC.java
index ba8bb566e..8b9915326 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/pack/obfuscation/ObfC.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/pack/obfuscation/ObfC.java
@@ -46,7 +46,7 @@ public class ObfC {
}
private static String normalizeCharset(String input) {
- return input.toLowerCase(Locale.ROOT);
+ return input.toLowerCase(Locale.ENGLISH);
}
private static String generateDefaultCharset() {
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java
index 767a9edc0..85633973f 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java
@@ -201,8 +201,7 @@ public abstract class CraftEngine implements Plugin {
// register category parser
this.packManager.registerConfigSectionParser(this.itemBrowserManager);
// register translation parser
- this.packManager.registerConfigSectionParser(this.translationManager);
- this.packManager.registerConfigSectionParser(this.translationManager.clientLangManager());
+ this.packManager.registerConfigSectionParsers(this.translationManager.parsers());
// register sound parser
this.packManager.registerConfigSectionParser(this.soundManager);
this.packManager.registerConfigSectionParser(this.soundManager.jukeboxSongManager());
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependency.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependency.java
index 0bf50cb9d..6a6c7e4b4 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependency.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependency.java
@@ -55,7 +55,7 @@ public class Dependency {
}
public String fileName(String classifier) {
- String name = customArtifactID.toLowerCase(Locale.ROOT).replace('_', '-');
+ String name = customArtifactID.toLowerCase(Locale.ENGLISH).replace('_', '-');
String extra = classifier == null || classifier.isEmpty()
? ""
: "-" + classifier;
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/ClientLangManager.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/ClientLangManager.java
deleted file mode 100644
index 575ff8904..000000000
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/ClientLangManager.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package net.momirealms.craftengine.core.plugin.locale;
-
-import net.momirealms.craftengine.core.pack.LoadingSequence;
-import net.momirealms.craftengine.core.plugin.Reloadable;
-import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-public interface ClientLangManager extends Reloadable, ConfigSectionParser {
- Set ALL_LANG = Set.of(
- "af_za", "ar_sa", "ast_es", "az_az", "ba_ru", "bar", "be_by", "be_latn",
- "bg_bg", "br_fr", "brb", "bs_ba", "ca_es", "cs_cz", "cy_gb", "da_dk",
- "de_at", "de_ch", "de_de", "el_gr", "en_au", "en_ca", "en_gb", "en_nz",
- "en_pt", "en_ud", "en_us", "enp", "enws", "eo_uy", "es_ar", "es_cl",
- "es_ec", "es_es", "es_mx", "es_uy", "es_ve", "esan", "et_ee", "eu_es",
- "fa_ir", "fi_fi", "fil_ph", "fo_fo", "fr_ca", "fr_fr", "fra_de", "fur_it",
- "fy_nl", "ga_ie", "gd_gb", "gl_es", "haw_us", "he_il", "hi_in", "hn_no",
- "hr_hr", "hu_hu", "hy_am", "id_id", "ig_ng", "io_en", "is_is", "isv",
- "it_it", "ja_jp", "jbo_en", "ka_ge", "kk_kz", "kn_in", "ko_kr", "ksh",
- "kw_gb", "ky_kg", "la_la", "lb_lu", "li_li", "lmo", "lo_la", "lol_us", "lt_lt",
- "lv_lv", "lzh", "mk_mk", "mn_mn", "ms_my", "mt_mt", "nah", "nds_de",
- "nl_be", "nl_nl", "nn_no", "no_no", "oc_fr", "ovd", "pl_pl", "pls",
- "pt_br", "pt_pt", "qya_aa", "ro_ro", "rpr", "ru_ru", "ry_ua", "sah_sah",
- "se_no", "sk_sk", "sl_si", "so_so", "sq_al", "sr_cs", "sr_sp", "sv_se",
- "sxu", "szl", "ta_in", "th_th", "tl_ph", "tlh_aa", "tok", "tr_tr",
- "tt_ru", "tzo_mx", "uk_ua", "val_es", "vec_it", "vi_vn", "vp_vl", "yi_de",
- "yo_ng", "zh_cn", "zh_hk", "zh_tw", "zlm_arab"
- );
-
- Map> LOCALE_2_COUNTRIES = ALL_LANG.stream()
- .map(lang -> lang.split("_"))
- .filter(split -> split.length >= 2)
- .collect(Collectors.groupingBy(
- split -> split[0],
- Collectors.mapping(split -> split[1], Collectors.toUnmodifiableList())
- ));
-
- String[] CONFIG_SECTION_NAME = new String[] {"lang", "language", "languages"};
-
- Map langData();
-
- @Override
- default int loadingSequence() {
- return LoadingSequence.LANG;
- }
-
- @Override
- default String[] sectionId() {
- return CONFIG_SECTION_NAME;
- }
-
- void addTranslation(String langId, Map translations);
-}
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/ClientLangMangerImpl.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/ClientLangMangerImpl.java
deleted file mode 100644
index 01f7c138e..000000000
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/ClientLangMangerImpl.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package net.momirealms.craftengine.core.plugin.locale;
-
-import net.momirealms.craftengine.core.pack.Pack;
-import net.momirealms.craftengine.core.util.Key;
-
-import java.nio.file.Path;
-import java.util.*;
-import java.util.stream.Collectors;
-
-public class ClientLangMangerImpl implements ClientLangManager {
- private final Map i18nData = new HashMap<>();
-
- protected ClientLangMangerImpl() {}
-
- @Override
- public void reload() {
- this.i18nData.clear();
- }
-
- @Override
- public void parseSection(Pack pack, Path path, Key id, Map section) {
- String langId = id.value().toLowerCase(Locale.ROOT);
-
- Map sectionData = section.entrySet().stream()
- .collect(Collectors.toMap(
- Map.Entry::getKey,
- entry -> String.valueOf(entry.getValue())
- ));
-
- addTranslation(langId, sectionData);
- }
-
- @Override
- public Map langData() {
- return Collections.unmodifiableMap(this.i18nData);
- }
-
- @Override
- public void addTranslation(String langId, Map translations) {
- if ("all".equals(langId)) {
- ALL_LANG.forEach(lang -> this.i18nData.computeIfAbsent(lang, k -> new I18NData())
- .addTranslations(translations));
- return;
- }
-
- if (ALL_LANG.contains(langId)) {
- this.i18nData.computeIfAbsent(langId, k -> new I18NData())
- .addTranslations(translations);
- return;
- }
-
- List langCountries = LOCALE_2_COUNTRIES.getOrDefault(langId, Collections.emptyList());
- for (String lang : langCountries) {
- this.i18nData.computeIfAbsent(langId + "_" + lang, k -> new I18NData())
- .addTranslations(translations);
- }
- }
-
- @Override
- public void delayedLoad() {
- this.i18nData.values().forEach(I18NData::processTranslations);
- }
-}
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManager.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManager.java
index edb9526b0..5c91c1397 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManager.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManager.java
@@ -7,16 +7,45 @@ import net.momirealms.craftengine.core.plugin.Reloadable;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import org.jetbrains.annotations.Nullable;
+import java.util.List;
import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
-public interface TranslationManager extends Reloadable, ConfigSectionParser {
- String[] CONFIG_SECTION_NAME = new String[] {"i18n", "internationalization", "translation", "translations"};
+public interface TranslationManager extends Reloadable {
+ Set ALL_LANG = Set.of(
+ "af_za", "ar_sa", "ast_es", "az_az", "ba_ru", "bar", "be_by", "be_latn",
+ "bg_bg", "br_fr", "brb", "bs_ba", "ca_es", "cs_cz", "cy_gb", "da_dk",
+ "de_at", "de_ch", "de_de", "el_gr", "en_au", "en_ca", "en_gb", "en_nz",
+ "en_pt", "en_ud", "en_us", "enp", "enws", "eo_uy", "es_ar", "es_cl",
+ "es_ec", "es_es", "es_mx", "es_uy", "es_ve", "esan", "et_ee", "eu_es",
+ "fa_ir", "fi_fi", "fil_ph", "fo_fo", "fr_ca", "fr_fr", "fra_de", "fur_it",
+ "fy_nl", "ga_ie", "gd_gb", "gl_es", "haw_us", "he_il", "hi_in", "hn_no",
+ "hr_hr", "hu_hu", "hy_am", "id_id", "ig_ng", "io_en", "is_is", "isv",
+ "it_it", "ja_jp", "jbo_en", "ka_ge", "kk_kz", "kn_in", "ko_kr", "ksh",
+ "kw_gb", "ky_kg", "la_la", "lb_lu", "li_li", "lmo", "lo_la", "lol_us", "lt_lt",
+ "lv_lv", "lzh", "mk_mk", "mn_mn", "ms_my", "mt_mt", "nah", "nds_de",
+ "nl_be", "nl_nl", "nn_no", "no_no", "oc_fr", "ovd", "pl_pl", "pls",
+ "pt_br", "pt_pt", "qya_aa", "ro_ro", "rpr", "ru_ru", "ry_ua", "sah_sah",
+ "se_no", "sk_sk", "sl_si", "so_so", "sq_al", "sr_cs", "sr_sp", "sv_se",
+ "sxu", "szl", "ta_in", "th_th", "tl_ph", "tlh_aa", "tok", "tr_tr",
+ "tt_ru", "tzo_mx", "uk_ua", "val_es", "vec_it", "vi_vn", "vp_vl", "yi_de",
+ "yo_ng", "zh_cn", "zh_hk", "zh_tw", "zlm_arab"
+ );
+ Map> LOCALE_2_COUNTRIES = ALL_LANG.stream()
+ .map(lang -> lang.split("_"))
+ .filter(split -> split.length >= 2)
+ .collect(Collectors.groupingBy(
+ split -> split[0],
+ Collectors.mapping(split -> split[1], Collectors.toUnmodifiableList())
+ ));
static TranslationManager instance() {
return TranslationManagerImpl.instance;
}
- ClientLangManager clientLangManager();
+ ConfigSectionParser[] parsers();
default String miniMessageTranslation(String key) {
return miniMessageTranslation(key, null);
@@ -36,15 +65,9 @@ public interface TranslationManager extends Reloadable, ConfigSectionParser {
return locale == null || locale.isEmpty() ? null : Translator.parseLocale(locale);
}
- @Override
- default int loadingSequence() {
- return LoadingSequence.TRANSLATION;
- }
-
- @Override
- default String[] sectionId() {
- return CONFIG_SECTION_NAME;
- }
-
void log(String id, String... args);
+
+ Map clientLangData();
+
+ void addClientTranslation(String langId, Map translations);
}
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManagerImpl.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManagerImpl.java
index b6c30d3f2..a3cb5abff 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManagerImpl.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManagerImpl.java
@@ -2,10 +2,12 @@ package net.momirealms.craftengine.core.plugin.locale;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.Component;
+import net.momirealms.craftengine.core.pack.LoadingSequence;
import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.Plugin;
import net.momirealms.craftengine.core.plugin.PluginProperties;
+import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.StringKeyConstructor;
import net.momirealms.craftengine.core.plugin.text.minimessage.IndexedArgumentTag;
import net.momirealms.craftengine.core.util.AdventureHelper;
@@ -34,22 +36,24 @@ public class TranslationManagerImpl implements TranslationManager {
private final Plugin plugin;
private final Set installed = ConcurrentHashMap.newKeySet();
private final Path translationsDirectory;
- private final ClientLangManager clientLangManager;
private final String langVersion;
private final String[] supportedLanguages;
private final Map translationFallback = new LinkedHashMap<>();
private Locale forcedLocale = null;
private Locale selectedLocale = DEFAULT_LOCALE;
private MiniMessageTranslationRegistry registry;
+ private final Map clientLangData = new HashMap<>();
+ private final LangParser langParser;
+ private final I18NParser i18nParser;
public TranslationManagerImpl(Plugin plugin) {
+ instance = this;
this.plugin = plugin;
this.translationsDirectory = this.plugin.dataFolderPath().resolve("translations");
- this.clientLangManager = new ClientLangMangerImpl();
this.langVersion = PluginProperties.getValue("lang-version");
this.supportedLanguages = PluginProperties.getValue("supported-languages").split(",");
- instance = this;
-
+ this.langParser = new LangParser();
+ this.i18nParser = new I18NParser();
Yaml yaml = new Yaml(new StringKeyConstructor(new LoaderOptions()));
try (InputStream is = plugin.resourceStream("translations/en.yml")) {
this.translationFallback.putAll(yaml.load(is));
@@ -58,6 +62,11 @@ public class TranslationManagerImpl implements TranslationManager {
}
}
+ @Override
+ public ConfigSectionParser[] parsers() {
+ return new ConfigSectionParser[] {this.langParser, this.i18nParser};
+ }
+
@Override
public void forcedLocale(Locale locale) {
this.forcedLocale = locale;
@@ -65,13 +74,13 @@ public class TranslationManagerImpl implements TranslationManager {
@Override
public void delayedLoad() {
- this.clientLangManager.delayedLoad();
+ this.clientLangData.values().forEach(I18NData::processTranslations);
}
@Override
public void reload() {
// clear old data
- this.clientLangManager.reload();
+ this.clientLangData.clear();
// remove any previous registry
if (this.registry != null) {
@@ -109,7 +118,7 @@ public class TranslationManagerImpl implements TranslationManager {
return;
}
- this.plugin.logger().warn(localLocale.toString().toLowerCase(Locale.ENGLISH) + ".yml not exists, using " + DEFAULT_LOCALE.toString().toLowerCase(Locale.ENGLISH) + ".yml as default locale.");
+ this.plugin.logger().warn("translations/" + localLocale.toString().toLowerCase(Locale.ENGLISH) + ".yml not exists, using " + DEFAULT_LOCALE.toString().toLowerCase(Locale.ENGLISH) + ".yml as default locale.");
this.selectedLocale = DEFAULT_LOCALE;
}
@@ -214,28 +223,6 @@ public class TranslationManagerImpl implements TranslationManager {
return Pair.of(locale, bundle);
}
- @Override
- public void parseSection(Pack pack, Path path, net.momirealms.craftengine.core.util.Key id, Map section) {
- Locale locale = TranslationManager.parseLocale(id.value());
- if (locale == null) {
- throw new IllegalStateException("Unknown locale '" + id.value() + "' - unable to register.");
- }
-
- Map bundle = new HashMap<>();
- for (Map.Entry entry : section.entrySet()) {
- String key = entry.getKey();
- bundle.put(key, entry.getValue().toString());
- }
-
- this.registry.registerAll(locale, bundle);
- this.installed.add(locale);
- }
-
- @Override
- public ClientLangManager clientLangManager() {
- return clientLangManager;
- }
-
@Override
public void log(String id, String... args) {
String translation = miniMessageTranslation(id);
@@ -263,4 +250,87 @@ public class TranslationManagerImpl implements TranslationManager {
return newFileContents;
}
}
+
+ @Override
+ public Map clientLangData() {
+ return Collections.unmodifiableMap(this.clientLangData);
+ }
+
+ @Override
+ public void addClientTranslation(String langId, Map translations) {
+ if ("all".equals(langId)) {
+ ALL_LANG.forEach(lang -> this.clientLangData.computeIfAbsent(lang, k -> new I18NData())
+ .addTranslations(translations));
+ return;
+ }
+
+ if (ALL_LANG.contains(langId)) {
+ this.clientLangData.computeIfAbsent(langId, k -> new I18NData())
+ .addTranslations(translations);
+ return;
+ }
+
+ List langCountries = LOCALE_2_COUNTRIES.getOrDefault(langId, Collections.emptyList());
+ for (String lang : langCountries) {
+ this.clientLangData.computeIfAbsent(langId + "_" + lang, k -> new I18NData())
+ .addTranslations(translations);
+ }
+ }
+
+ public class I18NParser implements ConfigSectionParser {
+ public static final String[] CONFIG_SECTION_NAME = new String[] {"i18n", "internationalization", "translation", "translations"};
+
+ @Override
+ public int loadingSequence() {
+ return LoadingSequence.TRANSLATION;
+ }
+
+ @Override
+ public String[] sectionId() {
+ return CONFIG_SECTION_NAME;
+ }
+
+ @Override
+ public void parseSection(Pack pack, Path path, net.momirealms.craftengine.core.util.Key id, Map section) {
+ Locale locale = TranslationManager.parseLocale(id.value());
+ if (locale == null) {
+ log("warning.config.i18n.unknown_locale", path.toString(), id.value());
+ return;
+ }
+
+ Map bundle = new HashMap<>();
+ for (Map.Entry entry : section.entrySet()) {
+ String key = entry.getKey();
+ bundle.put(key, entry.getValue().toString());
+ }
+
+ TranslationManagerImpl.this.registry.registerAll(locale, bundle);
+ TranslationManagerImpl.this.installed.add(locale);
+ }
+ }
+
+ public class LangParser implements ConfigSectionParser {
+ public static final String[] CONFIG_SECTION_NAME = new String[] {"lang", "language", "languages"};
+
+ @Override
+ public int loadingSequence() {
+ return LoadingSequence.LANG;
+ }
+
+ @Override
+ public String[] sectionId() {
+ return CONFIG_SECTION_NAME;
+ }
+
+ @Override
+ public void parseSection(Pack pack, Path path, net.momirealms.craftengine.core.util.Key id, Map section) {
+ String langId = id.value().toLowerCase(Locale.ENGLISH);
+ Map sectionData = section.entrySet().stream()
+ .collect(Collectors.toMap(
+ Map.Entry::getKey,
+ entry -> String.valueOf(entry.getValue())
+ ));
+ TranslationManagerImpl.this.addClientTranslation(langId, sectionData);
+ }
+ }
}