001/* 002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License 003 * 004 * Permission is hereby granted, free of charge, to any person obtaining 005 * a copy of this software and associated documentation files (the 006 * "Software"), to deal in the Software without restriction, including 007 * without limitation the rights to use, copy, modify, merge, publish, 008 * distribute, sublicense, and/or sell copies of the Software, and to 009 * permit persons to whom the Software is furnished to do so, subject to 010 * the following conditions: 011 * 012 * The above copyright notice and this permission notice shall be 013 * included in all copies or substantial portions of the Software. 014 * 015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 016 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 017 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 018 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 019 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 020 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 021 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 022 */ 023 024package co.aikar.commands; 025 026import co.aikar.locales.LocaleManager; 027import co.aikar.locales.MessageKey; 028import co.aikar.locales.MessageKeyProvider; 029import com.google.common.collect.HashMultimap; 030import com.google.common.collect.SetMultimap; 031import com.google.common.collect.Sets; 032import org.jetbrains.annotations.NotNull; 033 034import java.util.HashMap; 035import java.util.Locale; 036import java.util.Map; 037import java.util.regex.Matcher; 038 039@SuppressWarnings("WeakerAccess") 040public class Locales { 041 // Locales for reference since Locale doesn't have as many, add our own here for ease of use. 042 public static final Locale ENGLISH = Locale.ENGLISH; 043 public static final Locale GERMAN = Locale.GERMAN; 044 public static final Locale FRENCH = Locale.FRENCH; 045 public static final Locale JAPANESE = Locale.JAPANESE; 046 public static final Locale ITALIAN = Locale.ITALIAN; 047 public static final Locale KOREAN = Locale.KOREAN; 048 public static final Locale CHINESE = Locale.CHINESE; 049 public static final Locale SIMPLIFIED_CHINESE = Locale.SIMPLIFIED_CHINESE; 050 public static final Locale TRADITIONAL_CHINESE = Locale.TRADITIONAL_CHINESE; 051 public static final Locale SPANISH = new Locale("es"); 052 public static final Locale DUTCH = new Locale("nl"); 053 public static final Locale DANISH = new Locale("da"); 054 public static final Locale CZECH = new Locale("cs"); 055 public static final Locale GREEK = new Locale("el"); 056 public static final Locale LATIN = new Locale("la"); 057 public static final Locale BULGARIAN = new Locale("bg"); 058 public static final Locale AFRIKAANS = new Locale("af"); 059 public static final Locale HINDI = new Locale("hi"); 060 public static final Locale HEBREW = new Locale("he"); 061 public static final Locale POLISH = new Locale("pl"); 062 public static final Locale PORTUGUESE = new Locale("pt"); 063 public static final Locale FINNISH = new Locale("fi"); 064 public static final Locale SWEDISH = new Locale("sv"); 065 public static final Locale RUSSIAN = new Locale("ru"); 066 public static final Locale ROMANIAN = new Locale("ro"); 067 public static final Locale VIETNAMESE = new Locale("vi"); 068 public static final Locale THAI = new Locale("th"); 069 public static final Locale TURKISH = new Locale("tr"); 070 public static final Locale UKRANIAN = new Locale("uk"); 071 public static final Locale ARABIC = new Locale("ar"); 072 public static final Locale WELSH = new Locale("cy"); 073 074 075 private final CommandManager<?, ?, ?> manager; 076 private final LocaleManager<CommandIssuer> localeManager; 077 private final SetMultimap<String, Locale> loadedBundles = HashMultimap.create(); 078 079 public Locales(CommandManager manager) { 080 this.manager = manager; 081 this.localeManager = LocaleManager.create(manager::getIssuerLocale); 082 } 083 084 public void loadLanguages() { 085 addMessageBundles("acf-core"); 086 } 087 088 public Locale getDefaultLocale() { 089 return this.localeManager.getDefaultLocale(); 090 } 091 092 public Locale setDefaultLocale(Locale locale) { 093 return this.localeManager.setDefaultLocale(locale); 094 } 095 096 /** 097 * Looks for all previously loaded bundles, and if any new Supported Languages have been added, load them. 098 */ 099 public void loadMissingBundles() { 100 for (Locale locale : manager.getSupportedLanguages()) { 101 for (String bundleName : Sets.newHashSet(loadedBundles.keys())) { 102 addMessageBundle(bundleName, locale); 103 } 104 } 105 } 106 107 public void addMessageBundles(String... bundleNames) { 108 for (String bundleName : bundleNames) { 109 for (Locale locale : manager.getSupportedLanguages()) { 110 addMessageBundle(bundleName, locale); 111 } 112 } 113 } 114 115 public void addMessageBundle(String bundleName, Locale locale) { 116 if (!loadedBundles.containsEntry(bundleName, locale)) { 117 loadedBundles.put(bundleName, locale); 118 this.localeManager.addMessageBundle(bundleName, locale); 119 } 120 } 121 122 public void addMessageStrings(Locale locale, @NotNull Map<String, String> messages) { 123 Map<MessageKey, String> map = new HashMap<>(messages.size()); 124 messages.forEach((key, value) -> map.put(MessageKey.of(key), value)); 125 addMessages(locale, map); 126 } 127 public void addMessages(Locale locale, @NotNull Map<MessageKey, String> messages) { 128 this.localeManager.addMessages(locale, messages); 129 } 130 131 public String addMessage(Locale locale, MessageKey key, String message) { 132 return this.localeManager.addMessage(locale, key, message); 133 } 134 135 public String getMessage(CommandIssuer issuer, MessageKeyProvider key) { 136 final MessageKey msgKey = key.getMessageKey(); 137 String message = this.localeManager.getMessage(issuer, msgKey); 138 if (message == null) { 139 manager.log(LogLevel.ERROR, "Missing Language Key: " + msgKey.getKey()); 140 message = "<MISSING_LANGUAGE_KEY:" + msgKey.getKey() + ">"; 141 } 142 return message; 143 } 144 145 public String replaceI18NStrings(String message) { 146 if (message == null) { 147 return null; 148 } 149 Matcher matcher = ACFPatterns.I18N_STRING.matcher(message); 150 if (!matcher.matches()) { 151 return message; 152 } 153 154 CommandIssuer issuer = CommandManager.getCurrentCommandIssuer(); 155 156 matcher.reset(); 157 StringBuffer sb = new StringBuffer(message.length()); 158 while (matcher.find()) { 159 MessageKey key = MessageKey.of(matcher.group("key")); 160 matcher.appendReplacement(sb, Matcher.quoteReplacement(getMessage(issuer, key))); 161 } 162 matcher.appendTail(sb); 163 return sb.toString(); 164 } 165}