I'm new to Ktor and Kotlin in general, so please be patient.
I am currently trying to create a little website (mostly for learning) that uses key-value files for internationalization.
I already did something similar in PHP where I just decoded a JSON file and got the value related to the key I passed. This way, I could do something as <p><?php echo $langJson["presentation"][0];?></p>
(with $langJson being my json key-value file) so that I would get the proper translation.
I'm trying to do an equivalent in Kotlin using Ktor, but I don't know how to do it. I found the aymanizz ktor-i18n plugin on GitHub that allows to use i18n for internationalization but I don't know if it is really adapted to what I want to do since it detects the language in the header instead of it being chose by the user (with _GET for instance).
Does anyone have any clue on how I could do that?
Briefly, what I want to do is having a single coded page where the content is dynamicly chosen from the accurate language file.
Thank you all! :)
The basic idea is to get a language code from a request (a query parameter, a header, etc), generate a path to an i18n resource file, read it and then deserialize JSON into a map. The resulting map could be used as-is or passed as a model to a template.
Here is an example where I use kotlinx.serialization to transform a JSON string to get a map and FreeMarker template engine to render HTML. To switch a language just use the lang
GET parameter, e.g, http://localhost:8080/?lang=es
.
import freemarker.cache.ClassTemplateLoader
import io.ktor.application.*
import io.ktor.freemarker.*
import io.ktor.request.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
fun main() {
embeddedServer(Netty, port = 8080) {
install(FreeMarker) {
templateLoader = ClassTemplateLoader(this::class.java.classLoader, "templates")
}
routing {
get("/") {
call.respond(FreeMarkerContent("index.ftl", mapOf("i18n" to loadI18n(call.request))))
}
}
}.start()
}
fun loadI18n(request: ApplicationRequest): Map<String, String> {
val language = request.queryParameters["lang"] ?: "en"
val filePath = "i18n/$language.json"
val data = object {}.javaClass.classLoader.getResource(filePath)?.readText() ?: error("Cannot load i18n from $filePath")
return Json.decodeFromString(data)
}
resources/templates/index.ftl
<html>
<body>
<h1>${i18n.greetings}</h1>
</body>
</html>
resources/i18n/en.json
{
"greetings": "Hello"
}
resources/i18n/es.json
{
"greetings": "Hola"
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With