Skip to content

Instantly share code, notes, and snippets.

@nathanfranke
Last active February 17, 2022 20:15
Show Gist options
  • Save nathanfranke/47ab998ffa8bdda0ce84f6a414797a08 to your computer and use it in GitHub Desktop.
Save nathanfranke/47ab998ffa8bdda0ce84f6a414797a08 to your computer and use it in GitHub Desktop.
Kyori Adventure complex localization with arguments (e.g. plural, grammar)
@Suppress("UNUSED")
class MyPlugin : JavaPlugin(), Listener {
override fun onEnable() {
super.onEnable()
server.pluginManager.registerEvents(this, this)
}
@EventHandler
fun onPlayerJoin(event: PlayerJoinEvent) {
for (i in 1..5) {
event.player.sendMessage(
Localization.translatable("welcome", i).args(Component.text(i)).color(NamedTextColor.GREEN)
)
}
}
}
private data class LocalizationContext(val key: String, val args: Array<out Any>) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as LocalizationContext
if (key != other.key) return false
if (!args.contentEquals(other.args)) return false
return true
}
override fun hashCode(): Int {
var result = key.hashCode()
result = 31 * result + args.contentHashCode()
return result
}
}
object Localization {
private val localizationCache = mutableMapOf<String, LocalizationContext>()
fun register() {
val name = Key.key("network", "translations")
val registry = TranslationRegistry.create(name)
registry.register(
"welcome",
Locale.ENGLISH,
MessageFormat("There {0,choice,1#is|1<are} {0,number,integer} {0,choice,1#player|1<players} connected to the network.")
)
GlobalTranslator.get().addSource(registry)
GlobalTranslator.get().addSource(object : Translator {
override fun name() = name
override fun translate(key: String, locale: Locale): MessageFormat? {
val context = localizationCache[key] ?: return null
val format = GlobalTranslator.get().translate(context.key, locale) ?: return null
return MessageFormat(format.format(context.args))
}
})
}
/**
* Creates a translatable component with a translation key and arguments.
*
* @param key the translation key
* @param args arguments to use with message format
* @return a translatable component
*/
fun translatable(key: String, vararg args: Any): TranslatableComponent {
val context = LocalizationContext(key, args)
val cacheKey = context.hashCode().toString()
localizationCache[cacheKey] = context
return Component.translatable(cacheKey)
}
}
There is 1 player connected to the network.
There are 2 players connected to the network.
There are 3 players connected to the network.
There are 4 players connected to the network.
There are 5 players connected to the network.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment