Хостинг серверов Minecraft playvds.com
  1. Вы находитесь в русском сообществе Bukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на русский язык плагины наших собратьев из других стран.
    Скрыть объявление

[Совет] Делаем возможность самостоятельной локализации в своем плагине

Тема в разделе "Разработка плагинов для новичков", создана пользователем Jampire, 13 дек 2012.

  1. Автор темы
    Jampire

    Jampire Старожил Пользователь

    Баллы:
    173
    Skype:
    jampire-h
    Имя в Minecraft:
    Jampire
    После внедрения следующей системы в ваш плагин, пользователи сами смогут локализировать ваш плагин, не вскрывая его сторонними программами.

    Особенности:
    • Не создает нагрузки на сервер, даже уменьшает ее.
    • Меньше времени занимает перевод плагина на другой язык.
    • Смена языка в плагине в 2 клика.
    • В памяти хранится только выбранный перед запуском плагина язык.
    Установка:
    1. Создаем в своем плагине класс под названием Lang со следующим кодом:
      Код:
      package ru.jampire.bukkit.MyCoolPlugin;
      import java.util.HashMap;
      import java.util.Map;
      import java.util.Map.Entry;
      
      import org.bukkit.configuration.file.YamlConfiguration;
      
      public class Lang {
          private static Map<String, String> language = new HashMap<String, String>();
      
          public static void load(YamlConfiguration langYml) {
              for (Entry<String, Object> entry : langYml.getConfigurationSection(Main.config.getString("lang")).getValues(false).entrySet()) {
                  language.put(Main.config.getString("lang") + "." + entry.getKey(), String.valueOf(entry.getValue()));
              }
          }
      
          public static String getMessage(String target) {
              return language.get(Main.config.getString("lang") + "." + target);
          }}
      • Main.config - Путь к переменной, в которую записан ваш config
      • ru.jampire.bukkit.MyCoolPlugin - Пакет вашего плагина
    2. Создаем в корне плагина файл lang.yml и наполняем его подобным содержимым:
      Код:
      ru:
        msg1: Плагин включен.
        msg2: Плагин отключен.
      en:
        msg1: Plugin enabled.
        msg2: Plugin disabled.
      • ru / en - раздел локализации
      • msgX - сообщения
    3. Заставляем плагин выгрузить lang.yml при первой загрузке:
      Код:
      File flang = new File(plug.getDataFolder(), "lang.yml");
      if (!flang.exists()) {
          InputStream lang = Main.class.getResourceAsStream("/lang.yml");
          try {
              FileOutputStream fos = new FileOutputStream(flang);
              byte[] buff = new byte[65536];
              int n;
              while ((n = lang.read(buff)) > 0) {
                  fos.write(buff, 0, n);
                  fos.flush();
              }
              fos.close();
              buff = null;
          } catch (Exception e) {
              Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "Error: " + e);
          }
      }
      Lang.load(YamlConfiguration.loadConfiguration(flang));
      • plug - Ваш плагин. В моем случае код находился в отдельном классе под названием ConfigHandler, что исключало возможность вызова getDataFolder() напрямую.
    4. Добавляем в ваш config.yml опцию lang, равную стандартому языку. Пример: lang: ru
    5. Прописываем все сообщения плагина в файле lang.yml на всех стандартных языках.
    6. В коде плагина меняем все сообщения плагина на подобные строки:
      Код:
      Lang.getMessage("msg1")
    Упростим же жизнь переводчиков :D
     
  2. Хостинг MineCraft
    <
  3. Автор темы
    Jampire

    Jampire Старожил Пользователь

    Баллы:
    173
    Skype:
    jampire-h
    Имя в Minecraft:
    Jampire
    Если у вас есть какие-то поправки или улучшения к коду - прошу высказывать их в пм, не засоряя тему:)
    Думаю данная система пригодится многим)
     
    Black-UK-Lord нравится это.
  4. akke

    akke Старожил Пользователь

    Баллы:
    103
    Мб лучше так?
    Код:
    public static String getMessage(String target) {
        String r = language.get(Main.config.getString("lang") + "." + target);
        if (r == null)
            return ChatColor.DARK_RED + "Ошибка локализации, строка [" + target + "] не обнаружена";
        else
            return r;
    }}
     
    slavik123123123 нравится это.
  5. Автор темы
    Jampire

    Jampire Старожил Пользователь

    Баллы:
    173
    Skype:
    jampire-h
    Имя в Minecraft:
    Jampire
    Данная проблема может возникнуть только если автор плагина допустит ошибку (или кривой переводчик). А модифицировать код ради этого - бред)
    Велосипеду не нужно 3 колесо, что-бы ехать)
     
    fromgate нравится это.
  6. DPOH-VAR

    DPOH-VAR Старожил Пользователь

    Баллы:
    153
    Skype:
    dpohvar
    Эх, добавлю и свой метод (точнее метод Jampire , но сильно переработанный)

    Код:
    public class Translator {
     
        Map<String,String> tran = new HashMap<String, String>();
     
        public Translator(Plugin plugin, String locale){
            if(locale.contains(File.separator)) throw new RuntimeException("locale name is not valid");
            if (locale.equals("system")) locale = System.getProperty("user.language");
            InputStream is = null;
            File file = new File(plugin.getLangFolder(),locale+".yml");
            if(!file.exists()){
                is = plugin.getResource(locale+".yml");
                if (is==null){
                    is = plugin.getResource("en.yml");
                }
            } else {
                try {
                    is = new FileInputStream(file);
                } catch (FileNotFoundException ignored) {}
            }
            if(is!=null){
                try {
                    Yaml yaml = new Yaml();
                    Map<String, Object> map = (Map<String, Object>) yaml.load(is);
                    Map<String,Object> vals = (Map<String, Object>) map.get("locale");
                    for(Map.Entry<String,Object> e:vals.entrySet()){
                        tran.put(e.getKey(),e.getValue().toString());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
     
        public String translate(String key, Object... values){
            if(!tran.containsKey(key))return key;
            return String.format(tran.get(key),values);
        }
     
        public String translate(String key){
            if(!tran.containsKey(key))return key;
            return tran.get(key);
        }
    }
    Преимущества:
    • Можно указать язык "system" - будет взят язык системы. Если нет перевода на системный, то по умолчанию - английский.
    • Можно указывать параметры с форматированием. (например "Игрок %s нашел клад")
    • Поиск файла локализации происходит сначала в папке, затем в ресурсах jar
    Использование:
    1) Создаем у плагина метод public File getLangFolder(); например так:
    Код:
    public File getLangFolder(){
            File lang = new File(getDataFolder(),"lang");
            lang.mkdirs();
            return lang
    }
    2) При загрузке плагина создаем новый Translator, например:
    Код:
    String lang = this.getConfig().getString("lang");
    this.translator = new Translator(this,lang);
    3) создаем файл перевода, который потом кладем в jar
    Код:
    locale:
      error_offline: "player %s is offline"
      error_noplayer: "player required"
      success_removeentity: "entity with id %d successfully removed"
    4) теперь, чтобы что-то перевести, достаточно вызвать метод translate у объекта translator:
    Код:
    String s1 = translator.translate("error_noplayer");
    String s2 = translator.translate("success_removeentity",entity.getEntityId());
    String s3 = translator.translate("error_offline",player.getName());
    Желательно методы translate продублировать у класса плагина и сделать их статическими. Тогда код будет проще и понятнее.

    ПС: можно улучшить этот метод заменой Yaml на YamlConfiguration.
     
    stew, 1lyaSweeper, fromgate и ещё 1-му нравится это.
  7. Автор темы
    Jampire

    Jampire Старожил Пользователь

    Баллы:
    173
    Skype:
    jampire-h
    Имя в Minecraft:
    Jampire
    Давно хотел форматирование сделать. Но не было времени )
     

Поделиться этой страницей