Move tools folder into test folder
- Classes still won't be present in JAR but classes will be automatically compiled by Maven inside of the test scope, facilitating the execution of tool tasks
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
package tools.messages;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Multimap;
|
||||
import fr.xephi.authme.output.MessageKey;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import tools.utils.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Verifies a message file's keys to ensure that it is in sync with {@link MessageKey}, i.e. that the file contains
|
||||
* all keys and that it doesn't have any unknown ones.
|
||||
*/
|
||||
public class MessageFileVerifier {
|
||||
|
||||
private final String messagesFile;
|
||||
private final Set<String> unknownKeys = new HashSet<>();
|
||||
// Map with the missing key and a boolean indicating whether or not it was added to the file by this object
|
||||
private final Map<String, Boolean> missingKeys = new HashMap<>();
|
||||
private final Multimap<String, String> missingTags = HashMultimap.create();
|
||||
|
||||
/**
|
||||
* Create a verifier that verifies the given messages file.
|
||||
*
|
||||
* @param messagesFile The messages file to process
|
||||
*/
|
||||
public MessageFileVerifier(String messagesFile) {
|
||||
this.messagesFile = messagesFile;
|
||||
verifyKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of unknown keys, i.e. the list of keys present in the file that are not
|
||||
* part of the {@link MessageKey} enum.
|
||||
*
|
||||
* @return List of unknown keys
|
||||
*/
|
||||
public Set<String> getUnknownKeys() {
|
||||
return unknownKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of missing keys, i.e. all keys that are part of {@link MessageKey} but absent
|
||||
* in the messages file.
|
||||
*
|
||||
* @return The list of missing keys in the file
|
||||
*/
|
||||
public Map<String, Boolean> getMissingKeys() {
|
||||
return missingKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the collection of tags the message key defines that aren't present in the read line.
|
||||
*
|
||||
* @return Collection of missing tags per message key. Key = message key, value = missing tag.
|
||||
*/
|
||||
public Multimap<String, String> getMissingTags() {
|
||||
return missingTags;
|
||||
}
|
||||
|
||||
private void verifyKeys() {
|
||||
FileConfiguration configuration = YamlConfiguration.loadConfiguration(new File(messagesFile));
|
||||
|
||||
// Check known keys (their existence + presence of all tags)
|
||||
for (MessageKey messageKey : MessageKey.values()) {
|
||||
final String key = messageKey.getKey();
|
||||
if (configuration.isString(key)) {
|
||||
checkTagsInMessage(messageKey, configuration.getString(key));
|
||||
} else {
|
||||
missingKeys.put(key, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Check FileConfiguration for all of its keys to find unknown keys
|
||||
for (String key : configuration.getValues(true).keySet()) {
|
||||
if (!messageKeyExists(key)) {
|
||||
unknownKeys.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkTagsInMessage(MessageKey messageKey, String message) {
|
||||
for (String tag : messageKey.getTags()) {
|
||||
if (!message.contains(tag)) {
|
||||
missingTags.put(messageKey.getKey(), tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add missing keys to the file with the provided default (English) message.
|
||||
*
|
||||
* @param defaultMessages The collection of default messages
|
||||
*/
|
||||
public void addMissingKeys(FileConfiguration defaultMessages) {
|
||||
final List<String> fileLines = new ArrayList<>(
|
||||
Arrays.asList(FileUtils.readFromFile(messagesFile).split("\\n")));
|
||||
|
||||
List<String> keysToAdd = new ArrayList<>();
|
||||
for (Map.Entry<String, Boolean> entry : missingKeys.entrySet()) {
|
||||
final String key = entry.getKey();
|
||||
|
||||
if (Boolean.FALSE.equals(entry.getValue()) && defaultMessages.get(key) != null) {
|
||||
keysToAdd.add(key);
|
||||
}
|
||||
}
|
||||
|
||||
// Add missing keys as comments to the bottom of the file
|
||||
for (String keyToAdd : keysToAdd) {
|
||||
int indexOfComment = Iterables.indexOf(fileLines, isCommentFor(keyToAdd));
|
||||
if (indexOfComment != -1) {
|
||||
// Comment for keyToAdd already exists, so remove it since we're going to add it
|
||||
fileLines.remove(indexOfComment);
|
||||
}
|
||||
String comment = commentForKey(keyToAdd) + "'" +
|
||||
defaultMessages.getString(keyToAdd).replace("'", "''") + "'";
|
||||
fileLines.add(comment);
|
||||
missingKeys.put(keyToAdd, Boolean.TRUE);
|
||||
}
|
||||
|
||||
// Add a comment above messages missing a tag
|
||||
for (Map.Entry<String, Collection<String>> entry : missingTags.asMap().entrySet()) {
|
||||
final String key = entry.getKey();
|
||||
addCommentForMissingTags(fileLines, key, entry.getValue());
|
||||
}
|
||||
|
||||
FileUtils.writeToFile(messagesFile, StringUtils.join("\n", fileLines));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a comment above a message to note the tags the message is missing. Removes
|
||||
* any similar comment that may already be above the message.
|
||||
*
|
||||
* @param fileLines The lines of the file (to modify)
|
||||
* @param key The key of the message
|
||||
* @param tags The missing tags
|
||||
*/
|
||||
private void addCommentForMissingTags(List<String> fileLines, final String key, Collection<String> tags) {
|
||||
int indexForComment = Iterables.indexOf(fileLines, isCommentFor(key));
|
||||
if (indexForComment == -1) {
|
||||
indexForComment = Iterables.indexOf(fileLines, new Predicate<String>() {
|
||||
@Override
|
||||
public boolean apply(String input) {
|
||||
return input.startsWith(key + ": ");
|
||||
}
|
||||
});
|
||||
if (indexForComment == -1) {
|
||||
System.err.println("Error adding comment for key '" + key + "': couldn't find entry in file lines");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
fileLines.remove(indexForComment);
|
||||
}
|
||||
|
||||
String tagWord = tags.size() > 1 ? "tags" : "tag";
|
||||
fileLines.add(indexForComment, commentForKey(key)
|
||||
+ String.format("Missing %s %s", tagWord, StringUtils.join(", ", tags)));
|
||||
}
|
||||
|
||||
private static String commentForKey(String key) {
|
||||
return String.format("# TODO %s: ", key);
|
||||
}
|
||||
|
||||
private static Predicate<String> isCommentFor(final String key) {
|
||||
return new Predicate<String>() {
|
||||
@Override
|
||||
public boolean apply(String input) {
|
||||
return input.startsWith(commentForKey(key));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean messageKeyExists(String key) {
|
||||
for (MessageKey messageKey : MessageKey.values()) {
|
||||
if (messageKey.getKey().equals(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
## Messages
|
||||
Verifies the messages files and adds any missing indices with the English content as default.
|
||||
@@ -0,0 +1,150 @@
|
||||
package tools.messages;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import tools.utils.ToolTask;
|
||||
import tools.utils.ToolsConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
/**
|
||||
* Task to verify the keys in the messages files.
|
||||
*/
|
||||
public final class VerifyMessagesTask implements ToolTask {
|
||||
|
||||
/** The folder containing the message files. */
|
||||
private static final String MESSAGES_FOLDER = ToolsConstants.MAIN_RESOURCES_ROOT + "messages/";
|
||||
/** Pattern of the message file names. */
|
||||
private static final Pattern MESSAGE_FILE_PATTERN = Pattern.compile("messages_[a-z]{2,7}\\.yml");
|
||||
/** Tag that is replaced to the messages folder in user input. */
|
||||
private static final String SOURCES_TAG = "{msgdir}";
|
||||
/** File to get default messages from (assumes that it is complete). */
|
||||
private static final String DEFAULT_MESSAGES_FILE = MESSAGES_FOLDER + "messages_en.yml";
|
||||
|
||||
@Override
|
||||
public String getTaskName() {
|
||||
return "verifyMessages";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Scanner scanner) {
|
||||
System.out.println("Check a specific file only?");
|
||||
System.out.println("- Empty line will check all files in the resources messages folder (default)");
|
||||
System.out.println(format("- %s will be replaced to the messages folder %s", SOURCES_TAG, MESSAGES_FOLDER));
|
||||
String inputFile = scanner.nextLine();
|
||||
|
||||
System.out.println("Add any missing keys to files? ['y' = yes]");
|
||||
boolean addMissingKeys = "y".equalsIgnoreCase(scanner.nextLine());
|
||||
|
||||
List<File> messageFiles;
|
||||
if (StringUtils.isEmpty(inputFile)) {
|
||||
messageFiles = getMessagesFiles();
|
||||
} else {
|
||||
File customFile = new File(inputFile.replace(SOURCES_TAG, MESSAGES_FOLDER));
|
||||
messageFiles = Collections.singletonList(customFile);
|
||||
}
|
||||
|
||||
FileConfiguration defaultMessages = null;
|
||||
if (addMissingKeys) {
|
||||
defaultMessages = YamlConfiguration.loadConfiguration(new File(DEFAULT_MESSAGES_FILE));
|
||||
}
|
||||
|
||||
// Verify the given files
|
||||
for (File file : messageFiles) {
|
||||
System.out.println("Verifying '" + file.getName() + "'");
|
||||
MessageFileVerifier verifier = new MessageFileVerifier(file.getAbsolutePath());
|
||||
if (addMissingKeys) {
|
||||
verifyFileAndAddKeys(verifier, defaultMessages);
|
||||
} else {
|
||||
verifyFile(verifier);
|
||||
}
|
||||
}
|
||||
|
||||
if (messageFiles.size() > 1) {
|
||||
System.out.println("Checked " + messageFiles.size() + " files");
|
||||
}
|
||||
}
|
||||
|
||||
private static void verifyFile(MessageFileVerifier verifier) {
|
||||
Map<String, Boolean> missingKeys = verifier.getMissingKeys();
|
||||
if (!missingKeys.isEmpty()) {
|
||||
System.out.println(" Missing keys: " + missingKeys.keySet());
|
||||
}
|
||||
|
||||
Set<String> unknownKeys = verifier.getUnknownKeys();
|
||||
if (!unknownKeys.isEmpty()) {
|
||||
System.out.println(" Unknown keys: " + unknownKeys);
|
||||
}
|
||||
|
||||
Multimap<String, String> missingTags = verifier.getMissingTags();
|
||||
for (Map.Entry<String, String> entry : missingTags.entries()) {
|
||||
System.out.println(" Missing tag '" + entry.getValue() + "' in entry with key '" + entry.getKey() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
public static void verifyFileAndAddKeys(MessageFileVerifier verifier, FileConfiguration defaultMessages) {
|
||||
Map<String, Boolean> missingKeys = verifier.getMissingKeys();
|
||||
if (!missingKeys.isEmpty() || !verifier.getMissingTags().isEmpty()) {
|
||||
verifier.addMissingKeys(defaultMessages);
|
||||
List<String> addedKeys = getKeysWithValue(Boolean.TRUE, missingKeys);
|
||||
System.out.println(" Added missing keys " + addedKeys);
|
||||
|
||||
List<String> unsuccessfulKeys = getKeysWithValue(Boolean.FALSE, missingKeys);
|
||||
if (!unsuccessfulKeys.isEmpty()) {
|
||||
System.err.println(" Warning! Could not add all missing keys (problem with loading " +
|
||||
"default messages?)");
|
||||
System.err.println(" Could not add keys " + unsuccessfulKeys);
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> unknownKeys = verifier.getUnknownKeys();
|
||||
if (!unknownKeys.isEmpty()) {
|
||||
System.out.println(" Unknown keys: " + unknownKeys);
|
||||
}
|
||||
|
||||
Multimap<String, String> missingTags = verifier.getMissingTags();
|
||||
for (Map.Entry<String, String> entry : missingTags.entries()) {
|
||||
System.out.println(" Missing tag '" + entry.getValue() + "' in entry with key '" + entry.getKey() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
private static <K, V> List<K> getKeysWithValue(V value, Map<K, V> map) {
|
||||
List<K> result = new ArrayList<>();
|
||||
for (Map.Entry<K, V> entry : map.entrySet()) {
|
||||
if (value.equals(entry.getValue())) {
|
||||
result.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<File> getMessagesFiles() {
|
||||
File folder = new File(MESSAGES_FOLDER);
|
||||
File[] files = folder.listFiles();
|
||||
if (files == null) {
|
||||
throw new RuntimeException("Could not read files from folder '" + folder.getName() + "'");
|
||||
}
|
||||
|
||||
List<File> messageFiles = new ArrayList<>();
|
||||
for (File file : files) {
|
||||
if (MESSAGE_FILE_PATTERN.matcher(file.getName()).matches()) {
|
||||
messageFiles.add(file);
|
||||
}
|
||||
}
|
||||
if (messageFiles.isEmpty()) {
|
||||
throw new RuntimeException("Error getting message files: list of files is empty");
|
||||
}
|
||||
return messageFiles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package tools.messages.translation;
|
||||
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Extension of {@link YamlConfiguration} to customize the writing style.
|
||||
*/
|
||||
public class AuthMeYamlConfiguration extends YamlConfiguration {
|
||||
|
||||
// Differences to YamlConfiguration: Texts are always in single quotes
|
||||
// and line breaks are only applied after 200 chars
|
||||
@Override
|
||||
public String saveToString() {
|
||||
DumperOptions options = new DumperOptions();
|
||||
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
options.setDefaultScalarStyle(DumperOptions.ScalarStyle.SINGLE_QUOTED);
|
||||
options.setPrettyFlow(true);
|
||||
options.setWidth(200);
|
||||
Yaml yaml = new Yaml(options);
|
||||
|
||||
String header = buildHeader();
|
||||
String dump = yaml.dump(getValues(false));
|
||||
|
||||
if (dump.equals(BLANK_CONFIG)) {
|
||||
dump = "";
|
||||
}
|
||||
// By setting the scalar style to SINGLE_QUOTED both keys and values will be enclosed in single quotes.
|
||||
// We want all texts wrapped in single quotes, but not the keys. Seems like this is not possible in SnakeYAML
|
||||
dump = Pattern.compile("^'([a-zA-Z0-9-_]+)': ", Pattern.MULTILINE)
|
||||
.matcher(dump).replaceAll("$1: ");
|
||||
|
||||
return header + dump;
|
||||
}
|
||||
|
||||
/**
|
||||
* Behaves similarly to {@link YamlConfiguration#loadConfiguration(File)} but returns an object
|
||||
* of this class instead.
|
||||
*
|
||||
* @param file the file to load
|
||||
* @return the constructed AuthMeYamlConfiguration instance
|
||||
*/
|
||||
public static AuthMeYamlConfiguration loadConfiguration(File file) {
|
||||
AuthMeYamlConfiguration config = new AuthMeYamlConfiguration();
|
||||
try {
|
||||
config.load(file);
|
||||
} catch (IOException | InvalidConfigurationException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package tools.messages.translation;
|
||||
|
||||
import com.google.common.io.CharStreams;
|
||||
import com.google.gson.Gson;
|
||||
import fr.xephi.authme.output.MessageKey;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import tools.utils.ToolTask;
|
||||
import tools.utils.ToolsConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Task to export a language's messages to the remote translation service.
|
||||
*/
|
||||
public class ExportMessagesTask implements ToolTask {
|
||||
|
||||
/** The folder containing the messages files. */
|
||||
protected static final String MESSAGES_FOLDER = ToolsConstants.MAIN_RESOURCES_ROOT + "messages/";
|
||||
/** The remote URL to send an updated file to. */
|
||||
private static final String UPDATE_URL = "http://jalu.ch/ext/authme/update.php";
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
@Override
|
||||
public String getTaskName() {
|
||||
return "exportMessages";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Scanner scanner) {
|
||||
System.out.println("Enter language code of messages to export:");
|
||||
String languageCode = scanner.nextLine().trim();
|
||||
|
||||
File file = new File(MESSAGES_FOLDER + "messages_" + languageCode + ".yml");
|
||||
if (!file.exists()) {
|
||||
throw new IllegalStateException("File '" + file.getAbsolutePath() + "' does not exist");
|
||||
}
|
||||
|
||||
FileConfiguration configuration = YamlConfiguration.loadConfiguration(file);
|
||||
String json = convertToJson(languageCode, loadDefaultMessages(), configuration);
|
||||
|
||||
String result = sendJsonToRemote(languageCode, json);
|
||||
System.out.println("Answer: " + result);
|
||||
}
|
||||
|
||||
protected String convertToJson(String code, FileConfiguration defaultMessages, FileConfiguration messageFile) {
|
||||
List<MessageExport> list = new ArrayList<>();
|
||||
for (MessageKey key : MessageKey.values()) {
|
||||
list.add(new MessageExport(key.getKey(), key.getTags(), getString(key, defaultMessages),
|
||||
getString(key, messageFile)));
|
||||
}
|
||||
|
||||
return gson.toJson(new LanguageExport(code, list));
|
||||
}
|
||||
|
||||
protected FileConfiguration loadDefaultMessages() {
|
||||
return YamlConfiguration.loadConfiguration(new File(MESSAGES_FOLDER + "messages_en.yml"));
|
||||
}
|
||||
|
||||
private static String getString(MessageKey key, FileConfiguration configuration) {
|
||||
return configuration.getString(key.getKey(), "");
|
||||
}
|
||||
|
||||
private static String sendJsonToRemote(String language, String json) {
|
||||
try {
|
||||
String encodedData = "file=" + URLEncoder.encode(json, "UTF-8")
|
||||
+ "&language=" + URLEncoder.encode(language, "UTF-8");
|
||||
|
||||
URL url = new URL(UPDATE_URL);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
conn.setRequestProperty("Content-Length", String.valueOf(encodedData.length()));
|
||||
OutputStream os = conn.getOutputStream();
|
||||
os.write(encodedData.getBytes());
|
||||
os.flush();
|
||||
os.close();
|
||||
|
||||
return "Response code: " + conn.getResponseCode()
|
||||
+ "\n" + inputStreamToString(conn.getInputStream());
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String inputStreamToString(InputStream is) {
|
||||
try (InputStreamReader isr = new InputStreamReader(is)) {
|
||||
return CharStreams.toString(isr);
|
||||
} catch (IOException e) {
|
||||
return "Failed to read output - " + StringUtils.formatException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package tools.messages.translation;
|
||||
|
||||
import com.google.common.io.Resources;
|
||||
import com.google.gson.Gson;
|
||||
import fr.xephi.authme.output.MessageKey;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import tools.messages.MessageFileVerifier;
|
||||
import tools.messages.VerifyMessagesTask;
|
||||
import tools.utils.FileUtils;
|
||||
import tools.utils.ToolTask;
|
||||
import tools.utils.ToolsConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.HashSet;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Imports a message file from a remote JSON export and validates the resulting file.
|
||||
* <p>
|
||||
* Comments at the top of an existing file should remain after the import, but it is important
|
||||
* to verify that no unwanted changes have been applied to the file. Note that YAML comments
|
||||
* tend to disappear if there is no space between the <code>#</code> and the first character.
|
||||
*/
|
||||
public class ImportMessagesTask implements ToolTask {
|
||||
|
||||
private static final String MESSAGES_FOLDER = ToolsConstants.MAIN_RESOURCES_ROOT + "messages/";
|
||||
private Gson gson = new Gson();
|
||||
private Set<String> messageCodes;
|
||||
|
||||
@Override
|
||||
public String getTaskName() {
|
||||
return "importMessages";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Scanner scanner) {
|
||||
System.out.println("Enter URL to import from");
|
||||
// Dirty trick: replace https:// with http:// so we don't have to worry about installing certificates...
|
||||
String url = scanner.nextLine().replace("https://", "http://");
|
||||
|
||||
LanguageExport languageExport = getLanguageExportFromUrl(url);
|
||||
if (languageExport == null) {
|
||||
throw new IllegalStateException("An error occurred: constructed language export is null");
|
||||
}
|
||||
|
||||
mergeExportIntoFile(languageExport);
|
||||
System.out.println("Saved to messages file for code '" + languageExport.code + "'");
|
||||
}
|
||||
|
||||
private LanguageExport getLanguageExportFromUrl(String location) {
|
||||
try {
|
||||
URL url = new URL(location);
|
||||
String json = Resources.toString(url, Charset.forName("UTF-8"));
|
||||
return gson.fromJson(json, LanguageExport.class);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void mergeExportIntoFile(LanguageExport export) {
|
||||
String languageCode = export.code;
|
||||
String fileName = MESSAGES_FOLDER + "messages_" + languageCode + ".yml";
|
||||
File file = new File(fileName);
|
||||
FileConfiguration fileConfiguration;
|
||||
if (file.exists()) {
|
||||
removeAllTodoComments(fileName);
|
||||
fileConfiguration = AuthMeYamlConfiguration.loadConfiguration(file);
|
||||
} else {
|
||||
fileConfiguration = new AuthMeYamlConfiguration();
|
||||
}
|
||||
|
||||
buildMessageCodeList();
|
||||
for (MessageExport messageExport : export.messages) {
|
||||
if (!messageCodes.contains(messageExport.key)) {
|
||||
throw new IllegalStateException("Message key '" + messageExport.key + "' does not exist");
|
||||
} else if (!messageExport.translatedMessage.isEmpty()) {
|
||||
fileConfiguration.set(messageExport.key, messageExport.translatedMessage);
|
||||
}
|
||||
}
|
||||
try {
|
||||
fileConfiguration.save(file);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
MessageFileVerifier verifier = new MessageFileVerifier(fileName);
|
||||
VerifyMessagesTask.verifyFileAndAddKeys(verifier, YamlConfiguration.loadConfiguration(
|
||||
new File(MESSAGES_FOLDER + "messages_en.yml")));
|
||||
}
|
||||
|
||||
private void buildMessageCodeList() {
|
||||
messageCodes = new HashSet<>(MessageKey.values().length);
|
||||
for (MessageKey messageKey : MessageKey.values()) {
|
||||
messageCodes.add(messageKey.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all to-do comments written by {@link VerifyMessagesTask}. This is helpful as the YamlConfiguration
|
||||
* moves those comments otherwise upon saving.
|
||||
*
|
||||
* @param file The file whose to-do comments should be removed
|
||||
*/
|
||||
private static void removeAllTodoComments(String file) {
|
||||
String contents = FileUtils.readFromFile(file);
|
||||
String regex = "^# TODO .*$";
|
||||
contents = Pattern.compile(regex, Pattern.MULTILINE).matcher(contents).replaceAll("");
|
||||
FileUtils.writeToFile(file, contents);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package tools.messages.translation;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Export of a language's messages.
|
||||
*/
|
||||
public class LanguageExport {
|
||||
|
||||
public final String code;
|
||||
public final List<MessageExport> messages;
|
||||
|
||||
public LanguageExport(String code, List<MessageExport> messages) {
|
||||
this.code = code;
|
||||
this.messages = Collections.unmodifiableList(messages);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package tools.messages.translation;
|
||||
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Container class for one translatable message.
|
||||
*/
|
||||
public class MessageExport {
|
||||
|
||||
public final String key;
|
||||
public final String tags;
|
||||
public final String defaultMessage;
|
||||
public final String translatedMessage;
|
||||
|
||||
public MessageExport(String key, String[] tags, String defaultMessage, String translatedMessage) {
|
||||
this.key = key;
|
||||
this.tags = StringUtils.join(",", tags);
|
||||
this.defaultMessage = defaultMessage;
|
||||
this.translatedMessage = translatedMessage;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package tools.messages.translation;
|
||||
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import tools.utils.FileUtils;
|
||||
import tools.utils.ToolsConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Task which exports all messages to a local folder.
|
||||
*/
|
||||
public class WriteAllExportsTask extends ExportMessagesTask {
|
||||
|
||||
private static final String OUTPUT_FOLDER = ToolsConstants.TOOLS_SOURCE_ROOT + "messages/translation/export/";
|
||||
|
||||
@Override
|
||||
public String getTaskName() {
|
||||
return "writeAllExports";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Scanner scanner) {
|
||||
File[] messageFiles = new File(MESSAGES_FOLDER).listFiles();
|
||||
if (messageFiles == null || messageFiles.length == 0) {
|
||||
throw new IllegalStateException("Could not read messages folder");
|
||||
}
|
||||
|
||||
final FileConfiguration defaultMessages = loadDefaultMessages();
|
||||
for (File file : messageFiles) {
|
||||
String code = file.getName().substring("messages_".length(), file.getName().length() - ".yml".length());
|
||||
String json = convertToJson(code, defaultMessages, YamlConfiguration.loadConfiguration(file));
|
||||
FileUtils.writeToFile(OUTPUT_FOLDER + "messages_" + code + ".json", json);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user