Как использовать интернационализацию в Tornadofx - PullRequest
0 голосов
/ 29 марта 2020

Я пытаюсь использовать интернационализацию в приложении Kotlin с использованием фреймворка tornadofx.

Я создал файл свойств и в зависимости от выбранного языка загружается правильный файл. Но когда я хочу изменить язык в запущенном приложении, пользовательский интерфейс не обновляется соответствующим образом.

1 Ответ

0 голосов
/ 07 апреля 2020

Для интернационализации вы должны использовать сопутствующий объект, чтобы получить соответствующий перевод в любом месте вашего приложения. Прежде всего, ваш класс перевода должен знать, какой именно язык / язык выбран. Для этого я использую перечисление с возможными локалями для приложения:

fun setLocale(locale: SupportedLocale) {
  if (SupportedLocale.supportedLocals.contains(locale)) {
    Locale.setDefault(locale.local)
    actualLocal = locale.local
    //Good practice would be to store it in a properties file to have the information after restart
  } else {
    //Throw a warning or sth with your preferred logger
  }
}

Затем нам нужен метод, который получает конкретное строковое значение из вашего пакета ресурсов, например:

operator fun get(@PropertyKey(resourceBundle = BUNDLE_NAME) key: String, vararg args: Any): String {
        val bundle = ResourceBundle.getBundle(BUNDLE_NAME, actualLocal)
        return MessageFormat.format(bundle.getString(key), *args)
    }

В Приложения JavaFx (также TornadoFX) следует использовать StringBindings (https://docs.oracle.com/javase/8/javafx/api/javafx/beans/binding/StringBinding.html), например, чтобы привязать свойство текста метки к вашей переведенной строке. Для этого мы реализуем специальный метод:

fun createStringBinding(@PropertyKey(resourceBundle = BUNDLE_NAME) key: String, vararg args: Any): StringBinding {
        return Bindings.createStringBinding(Callable { get(key, *args) }, Settings.languageProperty())
    }

Теперь вы можете использовать свой объект следующим образом:

textProperty().bind(MyLang.createStringBinding("MyApp.MyTranslation"))

Вот пример запуска:

MyLang.kt

enum class SupportedLocale(val local:Locale) {
ENGLISH(Locale.ENGLISH),
GERMAN(Locale.GERMAN);

  companion object {
    val supportedLocals: List<SupportedLocale>
        get() = SupportedLocale.values().toList()
  }
}

class MyLang {
    companion object {
        private const val BUNDLE_NAME = "Language" //prefix of your resource bundle
        private var actualLocal = Locale.getDefault()

        fun setLocale(locale: SupportedLocale) {
          if (SupportedLocale.supportedLocals.contains(locale)) {
            Locale.setDefault(locale.local)
            actualLocal = locale.local
            //Good practice would be to store it in a properties file to have the information after restart
          } else {
            //Throw a warning or sth with your preferred logger
          }
        }

        operator fun get(@PropertyKey(resourceBundle = BUNDLE_NAME) key: String, vararg args: Any): String {
            val bundle = ResourceBundle.getBundle(BUNDLE_NAME, actualLocal)
            return MessageFormat.format(bundle.getString(key), *args)
        }

        fun createStringBinding(@PropertyKey(resourceBundle = BUNDLE_NAME) key: String, vararg args: Any): StringBinding {
            return Bindings.createStringBinding(Callable { get(key, *args) }, Settings.languageProperty())
        }
    }
}

fun main() {
  println("My translation: " + MyLang.createStringBinding("MyApp.MyTranslation").get())
  //The get() here is only to get the string for assign a property its not needed like in the example
}

Если вам нужны какие-либо объяснения или это неясно. Просто спроси! Это просто записано, может быть, я забыл кое-что объяснить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...