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); + } + } }