Developing multilingual apps efficiently can be a real challenge - especially when working with various frameworks and tools. This is where doloc comes into play: a lightweight solution for automated translations that integrates seamlessly into your existing workflows. The focus is on great translations and no need for a glossary, as all texts automatically serve implicitly as a glossary.
Today, we’re excited to introduce our latest integration for Android!
In this article, we’ll show you how to use doloc to automate translations in your Android project and save valuable time. It takes you only two steps before you can extract and translate your texts automatically!
Android: Automating Translations with doloc
- Set up Andoroid Localization with the Andorid documentation.
- Add doloc to your workflow by adding the following to your Gradle scripts. Use Groovy or Kotlin DSL depending on your project setup.
Groovy DSL (build.gradle):
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import java.nio.file.Files
import java.nio.file.Path
// other existing plugins/tasks..
static def translate(String targetLang, Path sourceFile, Path targetFile) {
def boundary = "Boundary-${System.currentTimeMillis()}"
HttpClient.newHttpClient().send(
HttpRequest.newBuilder().uri(URI.create("https://api.doloc.io?targetLang=$targetLang"))
.header("Content-Type", "multipart/form-data; boundary=$boundary")
.header("Authorization", "Bearer ${System.getenv("API_TOKEN")}")
.POST(
HttpRequest.BodyPublishers.ofString(
"--$boundary\r\n" +
"Content-Disposition: form-data; name=\"source\"; filename=\"${sourceFile.fileName}\"\r\n" +
"Content-Type: application/octet-stream\r\n\r\n" +
"${Files.readString(sourceFile)}\r\n" +
"--$boundary\r\n" +
"Content-Disposition: form-data; name=\"target\"; filename=\"${targetFile.fileName}\"\r\n" +
"Content-Type: application/octet-stream\r\n\r\n" +
"${Files.readString(targetFile)}\r\n" +
"--$boundary--\r\n"
)
)
.build(), HttpResponse.BodyHandlers.ofFile(targetFile)
)
}
tasks.register("doloc-fr") {
doLast {
translate(
"fr",
project.file("app/src/main/res/values/strings.xml").toPath(),
project.file("app/src/main/res/values-fr/strings.xml").toPath()
)
}
}
tasks.register("doloc-es") {
doLast {
translate(
"es",
project.file("app/src/main/res/values/strings.xml").toPath(),
project.file("app/src/main/res/values-es/strings.xml").toPath()
)
}
}
tasks.register("update-i18n") {
dependsOn("doloc-fr", "doloc-es")
}
Kotlin DSL (build.gradle.kts):
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import java.nio.file.Files
import java.nio.file.Path
// other existing plugins/tasks..
fun translate(targetLang: String, sourceFile: Path, targetFile: Path) {
val boundary = "Boundary-${System.currentTimeMillis()}"
HttpClient.newHttpClient().send(
HttpRequest.newBuilder().uri(URI.create("https://api.doloc.io?targetLang=$targetLang"))
.header("Content-Type", "multipart/form-data; boundary=$boundary")
.header("Authorization", "Bearer ${System.getenv("API_TOKEN")}")
.POST(
HttpRequest.BodyPublishers.ofString(
"--$boundary\r\n" +
"Content-Disposition: form-data; name=\"source\"; filename=\"${sourceFile.fileName}\"\r\n" +
"Content-Type: application/octet-stream\r\n\r\n" +
"${Files.readString(sourceFile)}\r\n" +
"--$boundary\r\n" +
"Content-Disposition: form-data; name=\"target\"; filename=\"${targetFile.fileName}\"\r\n" +
"Content-Type: application/octet-stream\r\n\r\n" +
"${Files.readString(targetFile)}\r\n" +
"--$boundary--\r\n"
)
)
.build(), HttpResponse.BodyHandlers.ofFile(targetFile)
)
}
tasks.register("doloc-fr") {
doLast {
translate(
"fr",
project.file("app/src/main/res/values/strings.xml").toPath(),
project.file("app/src/main/res/values-fr/strings.xml").toPath()
)
}
}
tasks.register("doloc-es") {
doLast {
translate(
"es",
project.file("app/src/main/res/values/strings.xml").toPath(),
project.file("app/src/main/res/values-es/strings.xml").toPath()
)
}
}
tasks.register("update-i18n") {
dependsOn("doloc-fr", "doloc-es")
}
- Make sure to update the translation file paths and to replace
${System.getenv("API_TOKEN")}
with your API token or set a corresponding environment variable. - The
$API_TOKEN
can be found in your doloc account.
Now run gradle update-i18n
to translate all new texts into all target languages!
When should the skript be run by the developer?
This script should be run after adding or updating translations and not on the CI/CD pipeline. This has the advantage that the code always stays in sync with the translations and that the developer can check the translations before committing and/or merging them. (Furthermore, this simplifies the CI/CD pipeline and prevents unnecessary commits for translations only.)
How to handle updated texts?
When changing texts in the source file, one should remove the corresponding texts in the target file to ensure that the translations are updated. Alternatively, one can manually update the translations in the target file, of course.
More Info
To find more info and details to integrate doloc into your Andorid workflow follow our Guide: https://doloc.io/getting-started/frameworks/android/.
Also we provide detailed information on configuration of specific options in the URL in our Android XML Resources guide.
Summary
By using the Android integration of doloc you have the following advantages:
- Easy integration into the development workflow
- Instant translations of texts via API
- Consistent style without a dictionary
- Reduced translator workload
- Accelerated time to market
- And, of course: Great translations!
Leave a comment or send us a message in case you need help or you have questions!
P.S. This also works for many other formats and frameworks!
Be sure to check out our guides for Angular and FormatJS/react-intl.
Top comments (0)