├── .gitignore ├── .travis.yml ├── Bukkit ├── pom.xml └── src │ └── main │ └── java │ └── dev │ └── notcacha │ └── languagelib │ └── bukkit │ ├── BukkitLanguageLib.java │ ├── file │ └── BukkitLanguageFile.java │ ├── loader │ └── BukkitFileLoader.java │ └── placeholder │ └── PAPIPlaceholderApplier.java ├── Bungee ├── pom.xml └── src │ └── main │ └── java │ └── dev │ └── notcacha │ └── languagelib │ └── bungee │ ├── BungeeLanguageLib.java │ ├── file │ └── BungeeLanguageFile.java │ └── loader │ └── BungeeFileLoader.java ├── LICENSE ├── README.md ├── Universal ├── pom.xml └── src │ └── main │ └── java │ └── dev │ └── notcacha │ └── languagelib │ ├── LanguageLib.java │ ├── exception │ └── FileNotFoundException.java │ ├── file │ └── LanguageFile.java │ ├── i18n │ ├── DefaultI18n.java │ ├── I18n.java │ └── message │ │ └── Message.java │ ├── loader │ └── FileLoader.java │ ├── manageable │ ├── FileManageable.java │ └── SimpleFileManageable.java │ ├── managers │ ├── SimpleTranslationManager.java │ └── TranslationManager.java │ ├── message │ ├── SimpleTranslatableMessage.java │ ├── TranslatableMessage.java │ └── color │ │ └── MessageColorApplier.java │ └── placeholder │ └── PlaceholderApplier.java └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target 3 | Bukkit/target 4 | Bukkit/Bukkit.iml 5 | Universal/target 6 | Bungee/target 7 | Bungee/Bungee.iml -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | # Use default install and test scripts -------------------------------------------------------------------------------- /Bukkit/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | languagelib 9 | dev.notcacha.languagelib 10 | 2.0.6-SNAPSHOT 11 | 12 | 13 | languagelib-bukkit 14 | jar 15 | 16 | 17 | 1.8 18 | UTF-8 19 | 20 | 21 | 22 | 23 | 24 | org.apache.maven.plugins 25 | maven-compiler-plugin 26 | 3.8.1 27 | 28 | ${java.version} 29 | ${java.version} 30 | 31 | 32 | 33 | org.apache.maven.plugins 34 | maven-shade-plugin 35 | 3.2.4 36 | 37 | 38 | package 39 | 40 | shade 41 | 42 | 43 | false 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | src/main/resources 52 | true 53 | 54 | 55 | 56 | 57 | 58 | 59 | spigotmc-repo 60 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 61 | 62 | 63 | sonatype 64 | https://oss.sonatype.org/content/groups/public/ 65 | 66 | 67 | placeholderapi 68 | http://repo.extendedclip.com/content/repositories/placeholderapi/ 69 | 70 | 71 | 72 | 73 | 74 | org.spigotmc 75 | spigot-api 76 | 1.8.8-R0.1-SNAPSHOT 77 | provided 78 | 79 | 80 | dev.notcacha.languagelib 81 | languagelib-universal 82 | 2.0.6-SNAPSHOT 83 | compile 84 | 85 | 86 | me.clip 87 | placeholderapi 88 | 2.10.9 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/dev/notcacha/languagelib/bukkit/BukkitLanguageLib.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.bukkit; 2 | 3 | import dev.notcacha.languagelib.LanguageLib; 4 | import dev.notcacha.languagelib.bukkit.loader.BukkitFileLoader; 5 | import dev.notcacha.languagelib.i18n.DefaultI18n; 6 | import dev.notcacha.languagelib.i18n.I18n; 7 | import dev.notcacha.languagelib.loader.FileLoader; 8 | import dev.notcacha.languagelib.manageable.FileManageable; 9 | import dev.notcacha.languagelib.manageable.SimpleFileManageable; 10 | import dev.notcacha.languagelib.managers.SimpleTranslationManager; 11 | import dev.notcacha.languagelib.managers.TranslationManager; 12 | import org.bukkit.plugin.Plugin; 13 | 14 | public class BukkitLanguageLib implements LanguageLib { 15 | 16 | private final TranslationManager translationManager; 17 | private final FileManageable fileManageable; 18 | private final FileLoader fileLoader; 19 | private final I18n i18n; 20 | 21 | public BukkitLanguageLib(TranslationManager translationManager, FileManageable fileManageable, FileLoader fileLoader, I18n i18n) { 22 | this.translationManager = translationManager; 23 | this.fileManageable = fileManageable; 24 | this.fileLoader = fileLoader; 25 | this.i18n = i18n; 26 | } 27 | 28 | @Override 29 | public TranslationManager getTranslationManager() { 30 | return this.translationManager; 31 | } 32 | 33 | @Override 34 | public FileManageable getFileManageable() { 35 | return this.fileManageable; 36 | } 37 | 38 | @Override 39 | public FileLoader getFileLoader() { 40 | return this.fileLoader; 41 | } 42 | 43 | @Override 44 | public I18n getI18n() { 45 | return this.i18n; 46 | } 47 | 48 | private static class Builder implements LanguageLib.Builder { 49 | 50 | private TranslationManager translationManager; 51 | private FileManageable fileManageable; 52 | private FileLoader fileLoader; 53 | private I18n i18n; 54 | 55 | public Builder(Plugin plugin, String defaultLanguage) { 56 | this(plugin, defaultLanguage, false); 57 | } 58 | 59 | public Builder(Plugin plugin, String defaultLanguage, boolean createDefaultFile) { 60 | this.i18n = new DefaultI18n(); 61 | this.fileLoader = new BukkitFileLoader(plugin, i18n); 62 | this.fileManageable = new SimpleFileManageable(fileLoader, plugin.getDataFolder(), defaultLanguage, createDefaultFile); 63 | this.translationManager = new SimpleTranslationManager(fileManageable); 64 | } 65 | 66 | @Override 67 | public LanguageLib.Builder setTranslationManager(TranslationManager translationManager) { 68 | this.translationManager = translationManager; 69 | return this; 70 | } 71 | 72 | @Override 73 | public LanguageLib.Builder setFilesManageable(FileManageable filesManageable) { 74 | this.fileManageable = filesManageable; 75 | return this; 76 | } 77 | 78 | @Override 79 | public LanguageLib.Builder setFileLoader(FileLoader fileLoader) { 80 | this.fileLoader = fileLoader; 81 | return this; 82 | } 83 | 84 | @Override 85 | public LanguageLib.Builder setI18n(I18n i18n) { 86 | this.i18n = i18n; 87 | return this; 88 | } 89 | 90 | @Override 91 | public LanguageLib build() { 92 | return new BukkitLanguageLib(translationManager, fileManageable, fileLoader, i18n); 93 | } 94 | } 95 | 96 | /** 97 | * @see this#builder(Plugin, String, boolean) 98 | */ 99 | 100 | public static LanguageLib.Builder builder(Plugin plugin, String defaultLanguage) { 101 | return builder(plugin, defaultLanguage, false); 102 | } 103 | 104 | /** 105 | * @param plugin from your plugin 106 | * @param defaultLanguage file name 107 | * @param createDefaultFile whether the value of this parameter will decide if the file has to be created before loading it or not 108 | * @return builder from {@link BukkitLanguageLib} 109 | */ 110 | 111 | public static LanguageLib.Builder builder(Plugin plugin, String defaultLanguage, boolean createDefaultFile) { 112 | return new BukkitLanguageLib.Builder(plugin, defaultLanguage, createDefaultFile); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/dev/notcacha/languagelib/bukkit/file/BukkitLanguageFile.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.bukkit.file; 2 | 3 | import dev.notcacha.languagelib.file.LanguageFile; 4 | import dev.notcacha.languagelib.i18n.I18n; 5 | import dev.notcacha.languagelib.i18n.message.Message; 6 | import org.bukkit.configuration.file.YamlConfiguration; 7 | 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | public class BukkitLanguageFile implements LanguageFile { 12 | 13 | private final I18n i18n; 14 | private final YamlConfiguration file; 15 | 16 | public BukkitLanguageFile(I18n i18n, YamlConfiguration file) { 17 | this.i18n = i18n; 18 | this.file = file; 19 | } 20 | 21 | @Override 22 | public String getString(String path) { 23 | return file.getString(path, 24 | i18n.getMessage(Message.MESSAGE_NOT_FOUND.getId()).replace("%path%", path)); 25 | } 26 | 27 | @Override 28 | public List getList(String path) { 29 | if (file.getStringList(path) == null) { 30 | return Collections.singletonList(i18n.getMessage(Message.LIST_MESSAGE_NOT_FOUND.getId()) 31 | .replace("%path%", path)); 32 | } 33 | 34 | return file.getStringList(path); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/dev/notcacha/languagelib/bukkit/loader/BukkitFileLoader.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.bukkit.loader; 2 | 3 | import dev.notcacha.languagelib.bukkit.file.BukkitLanguageFile; 4 | import dev.notcacha.languagelib.exception.FileNotFoundException; 5 | import dev.notcacha.languagelib.file.LanguageFile; 6 | import dev.notcacha.languagelib.i18n.I18n; 7 | import dev.notcacha.languagelib.i18n.message.Message; 8 | import dev.notcacha.languagelib.loader.FileLoader; 9 | import org.bukkit.configuration.file.YamlConfiguration; 10 | import org.bukkit.plugin.Plugin; 11 | 12 | import java.io.File; 13 | 14 | public class BukkitFileLoader implements FileLoader { 15 | 16 | private final Plugin plugin; 17 | private final I18n i18n; 18 | private String format; 19 | 20 | public BukkitFileLoader(Plugin plugin, I18n i18n) { 21 | this.plugin = plugin; 22 | this.i18n = i18n; 23 | this.format = "language_%lang%.yml"; 24 | } 25 | 26 | @Override 27 | public String getFormat() { 28 | return this.format; 29 | } 30 | 31 | @Override 32 | public FileLoader setFormat(String format) { 33 | this.format = format; 34 | return this; 35 | } 36 | 37 | @Override 38 | public LanguageFile load(String name, File folder) { 39 | File file = new File(folder, format.replace("%lang%", name)); 40 | if (!file.exists()) { 41 | throw new FileNotFoundException(i18n.getMessage(Message.FILE_NOT_FOUND.getId()) 42 | .replace("%file_name%", name)); 43 | } 44 | 45 | return new BukkitLanguageFile(i18n, YamlConfiguration.loadConfiguration(file)); 46 | } 47 | 48 | @Override 49 | public LanguageFile loadAndCreate(String name, File folder) { 50 | File file = new File(folder, format.replace("%lang%", name)); 51 | if (!file.exists()) { 52 | plugin.saveResource(format.replace("%lang%", name), false); 53 | } 54 | 55 | return load(name, folder); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/dev/notcacha/languagelib/bukkit/placeholder/PAPIPlaceholderApplier.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.bukkit.placeholder; 2 | 3 | import dev.notcacha.languagelib.placeholder.PlaceholderApplier; 4 | import me.clip.placeholderapi.PlaceholderAPI; 5 | import org.bukkit.entity.Player; 6 | import org.bukkit.plugin.Plugin; 7 | 8 | public class PAPIPlaceholderApplier implements PlaceholderApplier { 9 | 10 | private final Plugin plugin; 11 | 12 | public PAPIPlaceholderApplier(Plugin plugin) { 13 | this.plugin = plugin; 14 | } 15 | 16 | @Override 17 | public String apply(T holder, String text) { 18 | if (!(holder instanceof Player)) { 19 | return text; 20 | } 21 | 22 | if (plugin.getServer().getPluginManager().getPlugin("PlaceholderAPI") == null) { 23 | return text; 24 | } 25 | 26 | return PlaceholderAPI.setPlaceholders((Player) holder, text); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Bungee/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | languagelib 9 | dev.notcacha.languagelib 10 | 2.0.6-SNAPSHOT 11 | 12 | 13 | languagelib-bungee 14 | jar 15 | 16 | 17 | 1.8 18 | UTF-8 19 | 20 | 21 | 22 | clean package 23 | 24 | 25 | org.apache.maven.plugins 26 | maven-compiler-plugin 27 | 3.8.1 28 | 29 | ${java.version} 30 | ${java.version} 31 | 32 | 33 | 34 | org.apache.maven.plugins 35 | maven-shade-plugin 36 | 3.2.4 37 | 38 | 39 | package 40 | 41 | shade 42 | 43 | 44 | false 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | src/main/resources 53 | true 54 | 55 | 56 | 57 | 58 | 59 | 60 | sonatype 61 | https://oss.sonatype.org/content/groups/public/ 62 | 63 | 64 | 65 | 66 | 67 | net.md-5 68 | bungeecord-api 69 | 1.15-SNAPSHOT 70 | provided 71 | 72 | 73 | dev.notcacha.languagelib 74 | languagelib-universal 75 | 2.0.6-SNAPSHOT 76 | compile 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /Bungee/src/main/java/dev/notcacha/languagelib/bungee/BungeeLanguageLib.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.bungee; 2 | 3 | import dev.notcacha.languagelib.LanguageLib; 4 | import dev.notcacha.languagelib.bungee.loader.BungeeFileLoader; 5 | import dev.notcacha.languagelib.i18n.DefaultI18n; 6 | import dev.notcacha.languagelib.i18n.I18n; 7 | import dev.notcacha.languagelib.loader.FileLoader; 8 | import dev.notcacha.languagelib.manageable.FileManageable; 9 | import dev.notcacha.languagelib.manageable.SimpleFileManageable; 10 | import dev.notcacha.languagelib.managers.SimpleTranslationManager; 11 | import dev.notcacha.languagelib.managers.TranslationManager; 12 | import net.md_5.bungee.api.plugin.Plugin; 13 | 14 | public class BungeeLanguageLib implements LanguageLib { 15 | 16 | private final TranslationManager translationManager; 17 | private final FileManageable fileManageable; 18 | private final FileLoader fileLoader; 19 | private final I18n i18n; 20 | 21 | public BungeeLanguageLib(TranslationManager translationManager, FileManageable fileManageable, FileLoader fileLoader, I18n i18n) { 22 | this.translationManager = translationManager; 23 | this.fileManageable = fileManageable; 24 | this.fileLoader = fileLoader; 25 | this.i18n = i18n; 26 | } 27 | 28 | @Override 29 | public TranslationManager getTranslationManager() { 30 | return this.translationManager; 31 | } 32 | 33 | @Override 34 | public FileManageable getFileManageable() { 35 | return this.fileManageable; 36 | } 37 | 38 | @Override 39 | public FileLoader getFileLoader() { 40 | return this.fileLoader; 41 | } 42 | 43 | @Override 44 | public I18n getI18n() { 45 | return this.i18n; 46 | } 47 | 48 | private static class Builder implements LanguageLib.Builder { 49 | 50 | private TranslationManager translationManager; 51 | private FileManageable fileManageable; 52 | private FileLoader fileLoader; 53 | private I18n i18n; 54 | 55 | public Builder(Plugin plugin, String defaultLanguage) { 56 | this(plugin, defaultLanguage, false); 57 | } 58 | 59 | public Builder(Plugin plugin, String defaultLanguage, boolean createDefaultFile) { 60 | this.i18n = new DefaultI18n(); 61 | this.fileLoader = new BungeeFileLoader(plugin, i18n); 62 | this.fileManageable = new SimpleFileManageable(fileLoader, plugin.getDataFolder(), defaultLanguage, createDefaultFile); 63 | this.translationManager = new SimpleTranslationManager(fileManageable); 64 | } 65 | 66 | @Override 67 | public LanguageLib.Builder setTranslationManager(TranslationManager translationManager) { 68 | this.translationManager = translationManager; 69 | return this; 70 | } 71 | 72 | @Override 73 | public LanguageLib.Builder setFilesManageable(FileManageable filesManageable) { 74 | this.fileManageable = filesManageable; 75 | return this; 76 | } 77 | 78 | @Override 79 | public LanguageLib.Builder setFileLoader(FileLoader fileLoader) { 80 | this.fileLoader = fileLoader; 81 | return this; 82 | } 83 | 84 | @Override 85 | public LanguageLib.Builder setI18n(I18n i18n) { 86 | this.i18n = i18n; 87 | return this; 88 | } 89 | 90 | @Override 91 | public LanguageLib build() { 92 | return new BungeeLanguageLib(translationManager, fileManageable, fileLoader, i18n); 93 | } 94 | } 95 | 96 | /** 97 | * @see this#builder(Plugin, String, boolean) 98 | */ 99 | 100 | public static LanguageLib.Builder builder(Plugin plugin, String defaultLanguage) { 101 | return builder(plugin, defaultLanguage, false); 102 | } 103 | 104 | /** 105 | * @param plugin from your plugin 106 | * @param defaultLanguage file name 107 | * @param createDefaultFile whether the value of this parameter will decide if the file has to be created before loading it or not 108 | * @return builder from create {@link BungeeLanguageLib} 109 | * */ 110 | 111 | public static LanguageLib.Builder builder(Plugin plugin, String defaultLanguage, boolean createDefaultFile) { 112 | return new Builder(plugin, defaultLanguage, createDefaultFile); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Bungee/src/main/java/dev/notcacha/languagelib/bungee/file/BungeeLanguageFile.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.bungee.file; 2 | 3 | import dev.notcacha.languagelib.file.LanguageFile; 4 | import dev.notcacha.languagelib.i18n.I18n; 5 | import dev.notcacha.languagelib.i18n.message.Message; 6 | import net.md_5.bungee.config.Configuration; 7 | 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | public class BungeeLanguageFile implements LanguageFile { 12 | 13 | private final I18n i18n; 14 | private final Configuration file; 15 | 16 | public BungeeLanguageFile(I18n i18n, Configuration file) { 17 | this.i18n = i18n; 18 | this.file = file; 19 | } 20 | 21 | @Override 22 | public String getString(String path) { 23 | return file.getString(path, 24 | i18n.getMessage(Message.MESSAGE_NOT_FOUND.getId()).replace("%path%", path)); 25 | } 26 | 27 | @Override 28 | public List getList(String path) { 29 | if (file.getList(path) == null) { 30 | return Collections.singletonList(i18n.getMessage(Message.LIST_MESSAGE_NOT_FOUND.getId()) 31 | .replace("%path%", path)); 32 | } 33 | 34 | return file.getStringList(path); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Bungee/src/main/java/dev/notcacha/languagelib/bungee/loader/BungeeFileLoader.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.bungee.loader; 2 | 3 | import dev.notcacha.languagelib.bungee.file.BungeeLanguageFile; 4 | import dev.notcacha.languagelib.exception.FileNotFoundException; 5 | import dev.notcacha.languagelib.file.LanguageFile; 6 | import dev.notcacha.languagelib.i18n.I18n; 7 | import dev.notcacha.languagelib.i18n.message.Message; 8 | import dev.notcacha.languagelib.loader.FileLoader; 9 | import net.md_5.bungee.api.plugin.Plugin; 10 | import net.md_5.bungee.config.Configuration; 11 | import net.md_5.bungee.config.ConfigurationProvider; 12 | import net.md_5.bungee.config.YamlConfiguration; 13 | 14 | import java.io.File; 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | 18 | public class BungeeFileLoader implements FileLoader { 19 | 20 | private final Plugin plugin; 21 | private final I18n i18n; 22 | private String format; 23 | 24 | public BungeeFileLoader(Plugin plugin, I18n i18n) { 25 | this.plugin = plugin; 26 | this.i18n = i18n; 27 | this.format = "language_%lang%.yml"; 28 | } 29 | 30 | @Override 31 | public String getFormat() { 32 | return this.format; 33 | } 34 | 35 | @Override 36 | public FileLoader setFormat(String format) { 37 | this.format = format; 38 | return this; 39 | } 40 | 41 | @Override 42 | public LanguageFile load(String name, File folder) { 43 | String inputFile = format.replace("%lang%", name); 44 | 45 | InputStream inputStream = plugin.getResourceAsStream(inputFile); 46 | if (inputStream == null) { 47 | throw new FileNotFoundException("The file " + inputFile + " was not founded in plugin files"); 48 | } 49 | 50 | return new BungeeLanguageFile(i18n, ConfigurationProvider.getProvider(YamlConfiguration.class).load(inputStream)); 51 | } 52 | 53 | @Override 54 | public LanguageFile loadAndCreate(String name, File folder) { 55 | String inputFile = format.replace("%lang%", name); 56 | 57 | File file = new File(folder, inputFile); 58 | if (!file.exists()) { 59 | if (!plugin.getDataFolder().exists()) { 60 | plugin.getDataFolder().mkdirs(); 61 | } 62 | 63 | InputStream inputStream = plugin.getResourceAsStream(inputFile); 64 | if (inputStream == null) { 65 | throw new FileNotFoundException("The file " + inputFile + " was not founded in plugin files"); 66 | } 67 | 68 | Configuration inputConfig = ConfigurationProvider.getProvider(YamlConfiguration.class).load(inputStream); 69 | try { 70 | ConfigurationProvider.getProvider(YamlConfiguration.class).save(inputConfig, file); 71 | } catch (IOException exception) { 72 | throw new IllegalArgumentException(i18n.getMessage(Message.FILE_LOAD_ERROR.getId()) 73 | .replace("%file_name%", name), exception); 74 | } 75 | } 76 | 77 | return load(name, file); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Cassha 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LanguageLib [![Codacy Badge](https://app.codacy.com/project/badge/Grade/7d0836959bc8471a913a5c0b698a9790)](https://www.codacy.com/manual/NotCacha/LanguageLib?utm_source=github.com&utm_medium=referral&utm_content=NotCacha/LanguageLib&utm_campaign=Badge_Grade) [![](https://jitpack.io/v/cassha/LanguageLib.svg)](https://jitpack.io/#cassha/LanguageLib) 2 | 3 | ## Information 4 | LanguageLib is a simple library to make it easier to handle multi languages 5 | 6 | ### Repository 7 | ````xml 8 | 9 | 10 | jitpack.io 11 | https://jitpack.io 12 | 13 | 14 | 15 | 16 | com.github.cassha.LanguageLib 17 | languagelib 18 | 2.0.6-SNAPSHOT 19 | 20 | ```` 21 | 22 | #### Usage 23 | 24 | ##### Create instance 25 | 26 | Available implementations is BungeeLanguageLib and BukkitLanguageLib 27 | 28 | ````java 29 | LanguageLib languageLib = BukkitLanguageLib.builder(your plugin, "language").build(); 30 | ```` 31 | 32 | In any case, those who want to put their own implementations can use 33 | ````java 34 | LanguageLib languageLib = BukkitLanguageLib.builder(plugin, "en") 35 | .setFileLoader(fileLoader) 36 | .setFilesManageable(filesManageable) 37 | .setTranslationManager(translationManager) 38 | .setI18n(i18n) 39 | .build(); 40 | ```` 41 | 42 | ##### Get simple message 43 | ````java 44 | public void sendMessage(Player player) { 45 | TranslatableMessage translateMessage = languageLib.getTranslationManager().getTranslation("path"); 46 | 47 | // Set variable from message 48 | translateMessage.setVariable("%player_name%", player.getName()); 49 | 50 | // Set color from message 51 | translateMessage.colorize(); 52 | 53 | //Get message 54 | String message = translateMessage.getMessage("language"); 55 | 56 | player.sendMessage(message); 57 | } 58 | ```` 59 | 60 | ##### Get list messages 61 | ````java 62 | public void sendMessages(Player player) { 63 | TranslatableMessage translateMessage = languageLib.getTranslationManager().getTranslation("path"); 64 | 65 | // Set variable from messages 66 | translateMessage.setVariable("%player_name%", player.getName()); 67 | 68 | // Set color from messages 69 | translateMessage.colorize(); 70 | 71 | //Get messages in List format 72 | List message = translateMessage.getMessages("language"); 73 | 74 | message.forEach(player::sendMessage); 75 | } 76 | ```` 77 | 78 | #### Placeholders 79 | 80 | #### Create your placeholders 81 | 82 | ##### There are 1 ways available to create placeholders 83 | 84 | ````java 85 | public class TestPlaceholderApplier implements PlaceholderApplier { 86 | 87 | public String apply(T holder, String text) { 88 | if (!(holder instanceof Player)) { 89 | return text; 90 | } 91 | Player player = (Player) player; 92 | 93 | return text.replace("%player_name%", player.getName()); 94 | } 95 | } 96 | ```` 97 | 98 | #### Add your placeholders from message 99 | 100 | ##### In order to add them as a placeholder, they have to implement PlaceholderApplier 101 | 102 | We can add 1 single placeholder 103 | 104 | ```java 105 | translateMessage#addPlaceholder(holder, new YourPlaceholder()) 106 | ``` 107 | 108 | or multiple 109 | 110 | ```java 111 | translateMessage#addPlaceholders(holder, placeholders...); 112 | ``` 113 | 114 | #### Data to take into account 115 | The default library generates the files in this way "language_% lang% .yml", we can change this in the FileLoader 116 | %lang% will be replaced by the language that is being loaded 117 | ```java 118 | fileLoader#setFormat("language_%lang%.yml") 119 | ``` 120 | -------------------------------------------------------------------------------- /Universal/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | languagelib 7 | dev.notcacha.languagelib 8 | 2.0.6-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | languagelib-universal 13 | 14 | 15 | 16 | org.apache.maven.plugins 17 | maven-compiler-plugin 18 | 19 | 8 20 | 8 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Universal/src/main/java/dev/notcacha/languagelib/LanguageLib.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib; 2 | 3 | import dev.notcacha.languagelib.i18n.I18n; 4 | import dev.notcacha.languagelib.loader.FileLoader; 5 | import dev.notcacha.languagelib.manageable.FileManageable; 6 | import dev.notcacha.languagelib.managers.TranslationManager; 7 | 8 | public interface LanguageLib { 9 | 10 | /** 11 | * @return instance from {@link TranslationManager} from get new {@link dev.notcacha.languagelib.message.TranslatableMessage} 12 | */ 13 | 14 | TranslationManager getTranslationManager(); 15 | 16 | /** 17 | * @return instance from {@link FileManageable} from manageable files 18 | */ 19 | 20 | FileManageable getFileManageable(); 21 | 22 | /** 23 | * @return instance from {@link FileLoader} from load files 24 | */ 25 | 26 | FileLoader getFileLoader(); 27 | 28 | /** 29 | * @return an instance {@link I18n} to access that class 30 | */ 31 | 32 | I18n getI18n(); 33 | 34 | interface Builder { 35 | 36 | /** 37 | * Set {@link TranslationManager} instance from use 38 | * 39 | * @param translationManager has been set 40 | */ 41 | 42 | Builder setTranslationManager(TranslationManager translationManager); 43 | 44 | /** 45 | * Set {@link FileManageable} instance from use 46 | * 47 | * @param filesManageable has been set 48 | */ 49 | 50 | Builder setFilesManageable(FileManageable filesManageable); 51 | 52 | /** 53 | * Set {@link FileLoader} instance from use 54 | * 55 | * @param fileLoader has been set 56 | */ 57 | 58 | Builder setFileLoader(FileLoader fileLoader); 59 | 60 | /** 61 | * Set {@link I18n} instance from use 62 | * 63 | * @param i18n has been set 64 | */ 65 | 66 | Builder setI18n(I18n i18n); 67 | 68 | /** 69 | * @return new {@link LanguageLib} with all features assigned! 70 | */ 71 | 72 | LanguageLib build(); 73 | 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /Universal/src/main/java/dev/notcacha/languagelib/exception/FileNotFoundException.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.exception; 2 | 3 | public class FileNotFoundException extends RuntimeException { 4 | 5 | public FileNotFoundException() { 6 | super(); 7 | } 8 | 9 | public FileNotFoundException(String message) { 10 | super(message); 11 | } 12 | 13 | public FileNotFoundException(String message, Throwable cause) { 14 | super(message, cause); 15 | } 16 | 17 | public FileNotFoundException(Throwable cause) { 18 | super(cause); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Universal/src/main/java/dev/notcacha/languagelib/file/LanguageFile.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.file; 2 | 3 | import java.util.List; 4 | 5 | public interface LanguageFile { 6 | 7 | /** 8 | * @return a simple string obtained from a file, using reference {@param path} to identify it 9 | */ 10 | 11 | String getString(String path); 12 | 13 | /** 14 | * @return a list of strings obtained from a file, using reference {@param path} to identify it 15 | */ 16 | 17 | List getList(String path); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Universal/src/main/java/dev/notcacha/languagelib/i18n/DefaultI18n.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.i18n; 2 | 3 | import dev.notcacha.languagelib.i18n.message.Message; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | public class DefaultI18n implements I18n { 10 | 11 | private final Map messageMap; 12 | 13 | public DefaultI18n() { 14 | this.messageMap = new HashMap<>(); 15 | 16 | messageMap.put(Message.MESSAGE_NOT_FOUND.getId(), "Message not found, on path %path%"); 17 | messageMap.put(Message.LIST_MESSAGE_NOT_FOUND.getId(), "Message list not found, on path %path%"); 18 | messageMap.put(Message.FILE_NOT_FOUND.getId(), "The %file_name% file was not found"); 19 | messageMap.put(Message.FILE_LOAD_ERROR.getId(), "An error occurred while trying to load the %file_name% file"); 20 | } 21 | 22 | @Override 23 | public String getMessage(String id) { 24 | return this.messageMap.get(id); 25 | } 26 | 27 | public void setMessage(@NotNull String key, @NotNull String message) { 28 | messageMap.put(key, message); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Universal/src/main/java/dev/notcacha/languagelib/i18n/I18n.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.i18n; 2 | 3 | public interface I18n { 4 | 5 | /** 6 | * @return message from I18n, {@param message} key from message has been get 7 | */ 8 | 9 | String getMessage(String id); 10 | } 11 | -------------------------------------------------------------------------------- /Universal/src/main/java/dev/notcacha/languagelib/i18n/message/Message.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.i18n.message; 2 | 3 | public enum Message { 4 | 5 | MESSAGE_NOT_FOUND("message.simple.not_found"), 6 | LIST_MESSAGE_NOT_FOUND("message.list.not_found"), 7 | FILE_NOT_FOUND("file.not_found"), 8 | FILE_LOAD_ERROR("file.load_error"); 9 | 10 | private final String id; 11 | 12 | Message(String id) { 13 | this.id = id; 14 | } 15 | 16 | 17 | public String getId() { 18 | return id; 19 | } 20 | 21 | @Override 22 | public String toString() { 23 | return id; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /Universal/src/main/java/dev/notcacha/languagelib/loader/FileLoader.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.loader; 2 | 3 | import dev.notcacha.languagelib.file.LanguageFile; 4 | 5 | import java.io.File; 6 | 7 | public interface FileLoader { 8 | 9 | /** 10 | * @return format from languages files 11 | */ 12 | 13 | String getFormat(); 14 | 15 | /** 16 | * {@param format} will be the one established when looking for the file to load it 17 | */ 18 | 19 | FileLoader setFormat(String format); 20 | 21 | /** 22 | * Load a file {@link LanguageFile}, {@param name} name of the file to be identified and loaded 23 | * 24 | * @param folder from file 25 | * @return a file {@link LanguageFile} fully ready to use 26 | */ 27 | 28 | LanguageFile load(String name, File folder); 29 | 30 | /** 31 | * This method is almost the same as the previous method, the only difference is that in any case that the file does not exist, it will create it 32 | * 33 | * @see this#load(String, File); 34 | */ 35 | 36 | LanguageFile loadAndCreate(String name, File folder); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /Universal/src/main/java/dev/notcacha/languagelib/manageable/FileManageable.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.manageable; 2 | 3 | import dev.notcacha.languagelib.file.LanguageFile; 4 | 5 | import java.util.Set; 6 | 7 | public interface FileManageable { 8 | 9 | /** 10 | * @return a {@link Set} with all languages files 11 | */ 12 | 13 | Set get(); 14 | 15 | /** 16 | * Add file from cache 17 | * 18 | * @see this#add(String, boolean) 19 | */ 20 | 21 | default void add(String key) { 22 | add(key, false); 23 | } 24 | 25 | /** 26 | * Add file 27 | * 28 | * @param key name from language file 29 | * @param create this represents if the file has to be created or not, in all cases if it is 'true' the file will be created before being loaded otherwise it will only be loaded 30 | */ 31 | 32 | void add(String key, boolean create); 33 | 34 | /** 35 | * @return an object {@link LanguageFile} using {@param key} to get it 36 | */ 37 | 38 | LanguageFile find(String key); 39 | 40 | /** 41 | * @return if there is an object {@link LanguageFile} with the key {@param key} 42 | */ 43 | 44 | boolean exists(String key); 45 | 46 | 47 | /** 48 | * Remove file from cache 49 | * 50 | * @param key from get and delete object 51 | */ 52 | 53 | void remove(String key); 54 | 55 | /** 56 | * @return the default file {@link LanguageFile} 57 | */ 58 | 59 | LanguageFile getDefault(); 60 | } 61 | -------------------------------------------------------------------------------- /Universal/src/main/java/dev/notcacha/languagelib/manageable/SimpleFileManageable.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.manageable; 2 | 3 | import dev.notcacha.languagelib.file.LanguageFile; 4 | import dev.notcacha.languagelib.loader.FileLoader; 5 | 6 | import java.io.File; 7 | import java.util.HashMap; 8 | import java.util.HashSet; 9 | import java.util.Map; 10 | import java.util.Set; 11 | 12 | public class SimpleFileManageable implements FileManageable { 13 | 14 | private final FileLoader fileLoader; 15 | private final File folder; 16 | 17 | private final Map fileMap; 18 | private final String defaultFile; 19 | 20 | public SimpleFileManageable(FileLoader fileLoader, File folder, String defaultLanguage) { 21 | this(fileLoader, folder, defaultLanguage, false); 22 | } 23 | 24 | public SimpleFileManageable(FileLoader fileLoader, File folder, String defaultLanguage, boolean createFile) { 25 | this.fileLoader = fileLoader; 26 | this.folder = folder; 27 | 28 | this.defaultFile = defaultLanguage; 29 | this.fileMap = new HashMap<>(); 30 | 31 | add(defaultLanguage, createFile); 32 | } 33 | 34 | @Override 35 | public Set get() { 36 | return new HashSet<>(this.fileMap.values()); 37 | } 38 | 39 | @Override 40 | public void add(String key, boolean create) { 41 | this.fileMap.put(key, (!create) ? fileLoader.loadAndCreate(key, folder) : fileLoader.loadAndCreate(key, folder)); 42 | } 43 | 44 | @Override 45 | public LanguageFile find(String key) { 46 | return this.fileMap.get(key); 47 | } 48 | 49 | @Override 50 | public boolean exists(String key) { 51 | return this.fileMap.containsKey(key); 52 | } 53 | 54 | @Override 55 | public void remove(String key) { 56 | this.fileMap.remove(key); 57 | } 58 | 59 | @Override 60 | public LanguageFile getDefault() { 61 | return this.fileMap.get(defaultFile); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /Universal/src/main/java/dev/notcacha/languagelib/managers/SimpleTranslationManager.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.managers; 2 | 3 | import dev.notcacha.languagelib.manageable.FileManageable; 4 | import dev.notcacha.languagelib.message.SimpleTranslatableMessage; 5 | import dev.notcacha.languagelib.message.TranslatableMessage; 6 | 7 | public class SimpleTranslationManager implements TranslationManager { 8 | 9 | private final FileManageable fileManageable; 10 | 11 | public SimpleTranslationManager(FileManageable fileManageable) { 12 | this.fileManageable = fileManageable; 13 | } 14 | 15 | @Override 16 | public TranslatableMessage getTranslation(String path) { 17 | return new SimpleTranslatableMessage(path, fileManageable); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Universal/src/main/java/dev/notcacha/languagelib/managers/TranslationManager.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.managers; 2 | 3 | import dev.notcacha.languagelib.message.TranslatableMessage; 4 | 5 | public interface TranslationManager { 6 | 7 | /** 8 | * Returns a class {@link TranslatableMessage}, so that we can get the message in a certain language and set variables 9 | * 10 | * @param path, path to be obtained from the specified language file 11 | */ 12 | 13 | TranslatableMessage getTranslation(String path); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Universal/src/main/java/dev/notcacha/languagelib/message/SimpleTranslatableMessage.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.message; 2 | 3 | import dev.notcacha.languagelib.manageable.FileManageable; 4 | import dev.notcacha.languagelib.message.color.MessageColorApplier; 5 | import dev.notcacha.languagelib.placeholder.PlaceholderApplier; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | import java.util.concurrent.ConcurrentHashMap; 11 | 12 | public class SimpleTranslatableMessage implements TranslatableMessage { 13 | 14 | private final String path; 15 | private final FileManageable fileManageable; 16 | private final Map variables; 17 | private final Map appliers; 18 | private boolean color; 19 | 20 | public SimpleTranslatableMessage(String path, FileManageable fileManageable) { 21 | this.path = path; 22 | this.fileManageable = fileManageable; 23 | this.variables = new ConcurrentHashMap<>(); 24 | this.appliers = new ConcurrentHashMap<>(); 25 | this.color = false; 26 | } 27 | 28 | 29 | @Override 30 | @NotNull 31 | public String getPath() { 32 | return this.path; 33 | } 34 | 35 | @Override 36 | public String getMessage(String language) { 37 | String translateMessage; 38 | 39 | if (fileManageable.exists(language)) { 40 | translateMessage = fileManageable.find(language).getString(getPath()); 41 | } else { 42 | translateMessage = fileManageable.getDefault().getString(getPath()); 43 | } 44 | 45 | for (String key : variables.keySet()) { 46 | String value = variables.get(key); 47 | translateMessage = translateMessage.replace(key, value); 48 | } 49 | 50 | for (PlaceholderApplier placeholderApplier : this.appliers.keySet()) { 51 | translateMessage = placeholderApplier.apply(this.appliers.get(placeholderApplier), translateMessage); 52 | } 53 | 54 | if (color) { 55 | return MessageColorApplier.apply('&', translateMessage); 56 | } 57 | 58 | return translateMessage; 59 | } 60 | 61 | @Override 62 | public List getMessages(String language) { 63 | List translateMessages; 64 | 65 | if (fileManageable.exists(language)) { 66 | translateMessages = fileManageable.find(language).getList(getPath()); 67 | } else { 68 | translateMessages = fileManageable.getDefault().getList(getPath()); 69 | } 70 | 71 | for (String key : variables.keySet()) { 72 | String value = variables.get(key); 73 | translateMessages.replaceAll(message -> message.replace(key, value)); 74 | } 75 | 76 | for (PlaceholderApplier placeholderApplier : this.appliers.keySet()) { 77 | translateMessages.replaceAll(message -> placeholderApplier.apply(this.appliers.get(placeholderApplier), message)); 78 | } 79 | 80 | if (color) { 81 | translateMessages.replaceAll(message -> MessageColorApplier.apply('&', message)); 82 | } 83 | 84 | return translateMessages; 85 | } 86 | 87 | @Override 88 | public TranslatableMessage setVariable(String key, String value) { 89 | if (value == null) { 90 | this.variables.remove(key); 91 | } else { 92 | this.variables.put(key, value); 93 | } 94 | return this; 95 | } 96 | 97 | @Override 98 | public TranslatableMessage addPlaceholder(T holder, PlaceholderApplier placeholder) { 99 | this.appliers.put(placeholder, holder); 100 | 101 | return this; 102 | } 103 | 104 | @Override 105 | public TranslatableMessage colorize() { 106 | this.color = true; 107 | return this; 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /Universal/src/main/java/dev/notcacha/languagelib/message/TranslatableMessage.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.message; 2 | 3 | import dev.notcacha.languagelib.placeholder.PlaceholderApplier; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.util.List; 7 | 8 | public interface TranslatableMessage { 9 | 10 | /** 11 | * @return path of message 12 | */ 13 | 14 | @NotNull 15 | String getPath(); 16 | 17 | /** 18 | * Get message from path 19 | * 20 | * @param language the language in which to search for the message 21 | */ 22 | 23 | String getMessage(String language); 24 | 25 | /** 26 | * Get message from path 27 | * 28 | * @param language the language in which to search for the message 29 | */ 30 | 31 | List getMessages(String language); 32 | 33 | /** 34 | * Set variables to message 35 | * 36 | * @param key message to replace 37 | * @param value to be set in the {@param key} 38 | */ 39 | 40 | TranslatableMessage setVariable(String key, String value); 41 | 42 | /** 43 | * It is the same as the method above, only that the {@param value} receives a valueOf towards a {@link String} 44 | */ 45 | 46 | default TranslatableMessage setVariable(String key, Number value) { 47 | return setVariable(key, String.valueOf(value)); 48 | } 49 | 50 | /** 51 | * Set a {@link PlaceholderApplier} to do set in the message, {@param placeholder} will be the one set to use 52 | */ 53 | 54 | TranslatableMessage addPlaceholder(T holder, PlaceholderApplier placeholder); 55 | 56 | /** 57 | * Add multiple {@link PlaceholderApplier} to be applied to the message 58 | */ 59 | 60 | default TranslatableMessage addPlaceholders(T holder, PlaceholderApplier... placeholders) { 61 | for (PlaceholderApplier placeholderApplier : placeholders) { 62 | addPlaceholder(holder, placeholderApplier); 63 | } 64 | return this; 65 | } 66 | 67 | /** 68 | * Set color from message 69 | */ 70 | 71 | TranslatableMessage colorize(); 72 | 73 | } 74 | -------------------------------------------------------------------------------- /Universal/src/main/java/dev/notcacha/languagelib/message/color/MessageColorApplier.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.message.color; 2 | 3 | public interface MessageColorApplier { 4 | 5 | /** 6 | * Set color from message 7 | * 8 | * @param altColorChar the {@link Character} that will be changed by the {@link Character} that sets the color 9 | * @param textToTranslate text to be set color 10 | * @return {@param textToTranslate} with set colors 11 | */ 12 | 13 | static String apply(char altColorChar, String textToTranslate) { 14 | char color = '\u00A7'; 15 | 16 | String codes = "0123456789AaBbCcDdEeFfKkLlMmNnOoRr"; 17 | 18 | char[] b = textToTranslate.toCharArray(); 19 | 20 | for (int i = 0; i < b.length - 1; i++) { 21 | if (b[i] == altColorChar && codes.indexOf(b[i + 1]) > -1) { 22 | b[i] = color; 23 | b[i + 1] = Character.toLowerCase(b[i + 1]); 24 | } 25 | } 26 | 27 | return new String(b); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /Universal/src/main/java/dev/notcacha/languagelib/placeholder/PlaceholderApplier.java: -------------------------------------------------------------------------------- 1 | package dev.notcacha.languagelib.placeholder; 2 | 3 | public interface PlaceholderApplier { 4 | 5 | /** 6 | * Apply multiple variables in 1 single method to text {@param text}, using {@param holder} to get some value to be set 7 | */ 8 | 9 | String apply(T holder, String text); 10 | } 11 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | dev.notcacha.languagelib 8 | languagelib 9 | pom 10 | 2.0.6-SNAPSHOT 11 | 12 | Universal 13 | Bukkit 14 | Bungee 15 | 16 | 17 | 18 | 19 | org.jetbrains 20 | annotations 21 | 16.0.1 22 | 23 | 24 | 25 | 26 | --------------------------------------------------------------------------------