diff --git a/docs/translations.md b/docs/translations.md new file mode 100644 index 00000000..bec2c4dc --- /dev/null +++ b/docs/translations.md @@ -0,0 +1,39 @@ + + + +# AuthMe Translations +The following translations are available in AuthMe. Use the code in your +config.yml to use the language file. + +Code | Language | Translated |   +---- | -------- | ---------: | --- +en | English | 100% | bar +bg | Bulgarian | 73% | bar +br | Brazilian | 100% | bar +cz | Czech | 91% | bar +de | German | 97% | bar +es | Spanish | 100% | bar +eu | Basque | 66% | bar +fi | Finnish | 70% | bar +fr | French | 97% | bar +gl | Galician | 74% | bar +hu | Hungarian | 97% | bar +id | Indonesian | 74% | bar +it | Italian | 100% | bar +ko | Korean | 76% | bar +lt | Latvian | 57% | bar +nl | Dutch | 80% | bar +pl | Polish | 95% | bar +pt | Portuguese | 91% | bar +ru | Russian | 97% | bar +sk | Slovakian | 50% | bar +tr | Turkish | 85% | bar +uk | Ukrainian | 97% | bar +vn | Vietnamese | 85% | bar +zhcn | Chinese (China) | 85% | bar +zhhk | Chinese (Hong Kong) | 85% | bar +zhtw | Chinese (Taiwan) | 85% | bar + +--- + +This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sat Oct 08 22:53:13 CEST 2016 diff --git a/src/test/java/tools/docs/UpdateDocsTask.java b/src/test/java/tools/docs/UpdateDocsTask.java index 86ba85ba..cfdb69ef 100644 --- a/src/test/java/tools/docs/UpdateDocsTask.java +++ b/src/test/java/tools/docs/UpdateDocsTask.java @@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableSet; import tools.docs.commands.CommandPageCreater; import tools.docs.hashmethods.HashAlgorithmsDescriptionTask; import tools.docs.permissions.PermissionsListWriter; +import tools.docs.translations.TranslationPageGenerator; import tools.utils.AutoToolTask; import tools.utils.ToolTask; @@ -17,7 +18,8 @@ import java.util.function.Consumer; public class UpdateDocsTask implements AutoToolTask { private static final Set> TASKS = ImmutableSet - .of(CommandPageCreater.class, HashAlgorithmsDescriptionTask.class, PermissionsListWriter.class); + .of(CommandPageCreater.class, HashAlgorithmsDescriptionTask.class, + PermissionsListWriter.class, TranslationPageGenerator.class); @Override public String getTaskName() { diff --git a/src/test/java/tools/docs/translations/TranslationPageGenerator.java b/src/test/java/tools/docs/translations/TranslationPageGenerator.java new file mode 100644 index 00000000..e7785bd7 --- /dev/null +++ b/src/test/java/tools/docs/translations/TranslationPageGenerator.java @@ -0,0 +1,143 @@ +package tools.docs.translations; + +import com.google.common.collect.ImmutableMap; +import tools.docs.translations.TranslationsGatherer.TranslationInfo; +import tools.utils.AutoToolTask; +import tools.utils.FileUtils; +import tools.utils.TagValue.NestedTagValue; +import tools.utils.TagValueHolder; +import tools.utils.ToolsConstants; + +import java.util.Arrays; +import java.util.Map; +import java.util.Scanner; +import java.util.stream.Collectors; + +import static com.google.common.base.Objects.firstNonNull; + +/** + * Generates the translations page in docs. + */ +public class TranslationPageGenerator implements AutoToolTask { + + private static final String DOCS_PAGE = ToolsConstants.DOCS_FOLDER + "translations.md"; + private static final String TEMPLATE_FILE = ToolsConstants.TOOLS_SOURCE_ROOT + "docs/translations/translations.tpl.md"; + private static final Map LANGUAGE_NAMES = buildLanguageNames(); + + // Color configuration for the bars shown next to translation percentage + /** + * Percentage threshold under which the color will be computed from COLOR_0 to COLOR_1; + * above which COLOR_1 to COLOR_2 is used. + */ + private static final int COLOR_1_PERCENTAGE = 75; + // Colors are in RGB format, displayed as an int array of three values whose entries are in the range [0, 15]. + private static final int[] COLOR_0 = { 9, 0, 0}; + private static final int[] COLOR_1 = {12, 9, 0}; + private static final int[] COLOR_2 = { 6, 15, 6}; + + private final TranslationsGatherer gatherer = new TranslationsGatherer(); + + @Override + public String getTaskName() { + return "updateTranslations"; + } + + @Override + public void execute(Scanner scanner) { + executeDefault(); + } + + @Override + public void executeDefault() { + NestedTagValue translationValuesHolder = new NestedTagValue(); + + for (TranslationInfo translation : gatherer.getTranslationInfo()) { + int percentage = (int) Math.round(translation.percentTranslated * 100); + String name = firstNonNull(LANGUAGE_NAMES.get(translation.code), "?"); + TagValueHolder valueHolder = TagValueHolder.create() + .put("code", translation.code) + .put("name", name) + .put("percentage", Integer.toString(percentage)) + .put("color", computeColor(percentage)); + translationValuesHolder.add(valueHolder); + } + + TagValueHolder tags = TagValueHolder.create().put("languages", translationValuesHolder); + FileUtils.generateFileFromTemplate(TEMPLATE_FILE, DOCS_PAGE, tags); + } + + /** + * Returns the color for the given percentage as a 6-digit hex color code. + * + * @param percentage the percentage to generate a color for + * @return the color + */ + private String computeColor(int percentage) { + int[] color; + if (percentage < COLOR_1_PERCENTAGE) { + color = computeColor(percentage, COLOR_0, COLOR_1, 0, COLOR_1_PERCENTAGE); + } else { + color = computeColor(percentage, COLOR_1, COLOR_2, COLOR_1_PERCENTAGE, 100); + } + + return Arrays.stream(color) + .mapToObj(i -> Integer.toString(i, 16)) + .map(s -> s + s) + .collect(Collectors.joining()); + } + + /** + * Computes the color as the transition between two given colors. + * + * @param percentage the percentage to compute the color for + * @param colorA the color at the start of the range + * @param colorB the color at the end of the range + * @param rangeMin range start + * @param rangeMax range end + * @return color for the given percentage + */ + private static int[] computeColor(int percentage, int[] colorA, int[] colorB, int rangeMin, int rangeMax) { + double max = rangeMax - rangeMin; + double n = percentage - rangeMin; + + return new int[]{ + (int) (colorA[0] + n / max * (colorB[0] - colorA[0])), + (int) (colorA[1] + n / max * (colorB[1] - colorA[1])), + (int) (colorA[2] + n / max * (colorB[2] - colorA[2])) + }; + } + + /** + * @return map of language code -> language name + */ + private static Map buildLanguageNames() { + return ImmutableMap.builder() + .put("bg", "Bulgarian") + .put("br", "Brazilian") + .put("cz", "Czech") + .put("de", "German") + .put("en", "English") + .put("es", "Spanish") + .put("eu", "Basque") + .put("fi", "Finnish") + .put("fr", "French") + .put("gl", "Galician") + .put("hu", "Hungarian") + .put("id", "Indonesian") + .put("it", "Italian") + .put("ko", "Korean") + .put("lt", "Latvian") + .put("nl", "Dutch") + .put("pl", "Polish") + .put("pt", "Portuguese") + .put("ru", "Russian") + .put("sk", "Slovakian") + .put("tr", "Turkish") + .put("uk", "Ukrainian") + .put("vn", "Vietnamese") + .put("zhcn", "Chinese (China)") + .put("zhhk", "Chinese (Hong Kong)") + .put("zhtw", "Chinese (Taiwan)") + .build(); + } +} diff --git a/src/test/java/tools/docs/translations/TranslationsGatherer.java b/src/test/java/tools/docs/translations/TranslationsGatherer.java new file mode 100644 index 00000000..233b9332 --- /dev/null +++ b/src/test/java/tools/docs/translations/TranslationsGatherer.java @@ -0,0 +1,86 @@ +package tools.docs.translations; + +import fr.xephi.authme.message.MessageKey; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import tools.utils.ToolsConstants; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Gathers all available translations of AuthMe. + */ +public class TranslationsGatherer { + + private static final Pattern MESSAGES_PATTERN = Pattern.compile("messages_([a-z]{2,4})\\.yml"); + private static final String MESSAGES_FOLDER = ToolsConstants.MAIN_RESOURCES_ROOT + "messages/"; + + private List translationInfo = new ArrayList<>(); + + public TranslationsGatherer() { + gatherTranslations(); + translationInfo.sort((e1, e2) -> getCode(e1).compareTo(getCode(e2))); + } + + public List getTranslationInfo() { + return translationInfo; + } + + private void gatherTranslations() { + File[] files = new File(MESSAGES_FOLDER).listFiles(); + if (files == null) { + throw new IllegalStateException("Cannot read files of '" + MESSAGES_FOLDER + "'"); + } + for (File file : files) { + String code = getLanguageCode(file.getName()); + if (code != null) { + processMessagesFile(code, file); + } + } + } + + private void processMessagesFile(String code, File file) { + FileConfiguration configuration = YamlConfiguration.loadConfiguration(file); + int availableMessages = 0; + for (MessageKey key : MessageKey.values()) { + if (configuration.contains(key.getKey())) { + ++availableMessages; + } + } + translationInfo.add(new TranslationInfo(code, (double) availableMessages / MessageKey.values().length)); + } + + private String getLanguageCode(String messagesFile) { + Matcher matcher = MESSAGES_PATTERN.matcher(messagesFile); + if (matcher.find()) { + return matcher.group(1); + } + return null; + } + + public static final class TranslationInfo { + public final String code; + public final double percentTranslated; + + TranslationInfo(String code, double percentTranslated) { + this.code = code; + this.percentTranslated = percentTranslated; + } + } + + /** + * Returns the language code from the translation info for sorting purposes. + * Returns "a" for "en" language code to sort English on top. + * + * @param info the translation info + * @return the language code for sorting + */ + private static String getCode(TranslationInfo info) { + return "en".equals(info.code) ? "a" : info.code; + } + +} diff --git a/src/test/java/tools/docs/translations/translations.tpl.md b/src/test/java/tools/docs/translations/translations.tpl.md new file mode 100644 index 00000000..faad36b5 --- /dev/null +++ b/src/test/java/tools/docs/translations/translations.tpl.md @@ -0,0 +1,14 @@ + + + +# AuthMe Translations +The following translations are available in AuthMe. Use the code in your +config.yml to use the language file. + +Code | Language | Translated |   +---- | -------- | ---------: | --- +[#languages] +{code} | {name} | {percentage}% | bar +[/#languages] + +{gen_footer}