Skip to content

Instantly share code, notes, and snippets.

@jush
Created April 20, 2018 19:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jush/86750587a12da8ea28ce662e9ddaf77f to your computer and use it in GitHub Desktop.
Save jush/86750587a12da8ea28ce662e9ddaf77f to your computer and use it in GitHub Desktop.
Gradle script to pull 'strings.xml' from Transifex
import groovyx.net.http.ContentType
import groovyx.net.http.HttpResponseDecorator
import groovyx.net.http.RESTClient
import net.sf.json.JSONObject
import org.apache.commons.codec.binary.Base64
// This gradle file will add several tasks.
// For example, pulling all source and translation files at once for all projects:
// ./gradlew transifexPullAll
/*
// Copy paste this values to your root build.grade inside 'ext' section
transifexKey = '<username>'
transifexSecret = '<password>'
// Transifex project name (from https://www.transifex.com/<organization>/<project_name>/dashboard/)
transifexProjectApp = 'app-android'
transifexProjectMock = 'mock-android'
// Resource slug (from https://www.transifex.com/<organization>/<project_name>/<slug>/)
transifexResource = 'stringsxml'
// List here all the locales supported by this project in Android format
allSupportedLocales = ["en", "ca", "cs", "da", "de", "es", "fi", "fr", "it","ja", "ko", "nl", "no","pl", "pt", "ru","sv", "tr", "th", "zh", "zh-rCN"]
*/
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'org.codehaus.groovy.modules.http-builder:http-builder:0.5.0'
}
}
/**
* Add Gradle task for pulling all translation files for all flavor projects.
*
* Usage: ./gradlew transifexPullAll
*
**/
task transifexPullAll {
dependsOn 'transifexPullAppProject'
// Repeat above for other project tasks (See below). For example 'Mock':
// dependsOn 'transifexPullMockProject'
}
/**
* Add Gradle task for pulling all translation files for App project.
*
* Usage: ./gradlew transifexPullAppProject
*
**/
task transifexPullAppProject {
doLast {
setActiveTransifexProjectToApp()
pullSupportedLocales()
}
}
/**
* Add Gradle task for pulling all translation files for Mock project.
*
* Usage: ./gradlew transifexPullMockProject
*
**/
//task transifexPullMockProject {
// doLast {
// setActiveTransifexProjectToMock()
// pullSupportedLocales()
// }
//}
/**
* Add Gradle tasks for pulling a single translation file from App project. When no
* language code is specified we default to "en"
*
* Usage: ./gradlew transifexPullSingleApp -PargLanguageCode="es"
*
* */
task transifexPullSingleApp {
doLast {
String languageCode = "en"
if (project.hasProperty('argLanguageCode')) {
languageCode = project.property('argLanguageCode')
}
setActiveTransifexProjectToApp()
pullAndWriteTranslationFile(languageCode)
}
}
/**
* Add Gradle tasks for pulling a single translation file from Mock project. When no language code
* is specified we default to "en"
*
* Usage: ./gradlew transifexPullSingleMock -PargLanguageCode="es"
*
* */
//task transifexPullSingleMock {
// doLast {
// String languageCode = "en"
// if (project.hasProperty('argLanguageCode')) {
// languageCode = project.property('argLanguageCode')
// }
// setActiveTransifexProjectToMock()
// pullAndWriteTranslationFile(languageCode)
// }
//}
def setActiveTransifexProjectToApp() {
rootProject.ext.set("transifexProject", rootProject.ext.transifexProjectApp)
rootProject.ext.set("flavorFolder", "app/src/main")
}
//def setActiveTransifexProjectToMock() {
// rootProject.ext.set("transifexProject", rootProject.ext.transifexProjectMock)
// rootProject.ext.set("flavorFolder", "app/src/mock")
//}
def pullSupportedLocales() {
for (String languageCode : rootProject.ext.allSupportedLocales) {
pullAndWriteTranslationFile(languageCode)
}
}
def pullAndWriteTranslationFile(String languageCode) {
logDebug("Pulling language: " + languageCode)
verifyFileExists(languageCode)
String codeForTF = verifyLanguageCodeForTransifex(languageCode)
writeHttpResponseToFile(fetchTranslationFile(codeForTF), languageCode);
}
/**
* Use this function to modify language codes for TF
* @param languageCode
*/
def verifyLanguageCodeForTransifex(String languageCode) {
// In TF the language code is zh_CN without the 'r'
if (languageCode.equals("zh-rCN")) {
logDebug("Rewriting language code: zh-rCN to zh-CN")
languageCode = "zh-CN"
}
return languageCode
}
def verifyFileExists(String languageCode) {
File currentDir = new File("");
logDebug("Current dir: '" + currentDir.getAbsolutePath() + "'")
File file = new File(getFilePath(languageCode))
if (!file.exists()) {
if (!file.getParentFile().mkdirs() || !file.createNewFile()) {
throw new FileNotFoundException(
"Failed to create new file to path: " + file.getAbsolutePath())
}
}
}
def getApiURL() {
return "https://www.transifex.com/api/2/";
}
def getProjectURL() {
return "project/$rootProject.ext.transifexProject/?details"
}
def getLanguageFileURL(String languageCode) {
return "project/$rootProject.ext.transifexProject/resource/$rootProject.ext.transifexResource/translation/$languageCode/"
}
def getFilePath(String languageCode) {
if (languageCode.equals("en")) {
return "$rootProject.ext.flavorFolder/res/values/strings.xml"
} else {
return "$rootProject.ext.flavorFolder/res/values-$languageCode/strings.xml"
}
}
/**
* TF requires basic HTTP authentication
*
*/
def createHeader() {
return ['Authorization': "Basic " + getAuth()]
}
def getAuth() {
String credentials = "$rootProject.ext.transifexKey:$rootProject.ext.transifexSecret"
byte[] credBytes = credentials.getBytes()
byte[] base64Bytes = Base64.encodeBase64(credBytes)
return new String(base64Bytes)
}
def fetchProjectInfo() {
def client = new RESTClient(getApiURL() + getProjectURL())
def HttpResponseDecorator response = client.get(headers: createHeader(),
requestContentType: ContentType.JSON)
assert response.status == 200
verifyResponse(response)
}
def HttpResponseDecorator fetchTranslationFile(String languageCode) {
String url = getApiURL() + getLanguageFileURL(languageCode)
logDebug("Fetching from URL: " + url)
def client = new RESTClient(url)
def HttpResponseDecorator response = client.get(headers: createHeader(),
"mode": "file")
assert response.status == 200
verifyResponse(response)
return response
}
def writeHttpResponseToFile(HttpResponseDecorator response, String languageCode) {
String path = getFilePath(languageCode)
logDebug("Writing to file: " + path)
JSONObject json = response.getData()
String content = json.get("content").toString()
content = replaceHeader(content, languageCode)
writeToFile(content, path)
}
def replaceHeader(String content, String languageCode) {
if (languageCode != "en") {
logDebug("Modifying header for: " + languageCode)
content = removeToolsLocaleHeader(content)
}
return content
}
/**
* If your app/src/res/strings.xml has 'tools:Locale' defined, this will remove it from other
* languages since it's not done by Transifex
*/
def removeToolsLocaleHeader(String content) {
content = content.replace(' tools:locale="en"', "")
return content.trim()
}
def writeToFile(String data, String filePath) throws IOException {
BufferedWriter writer = null
try {
writer = new BufferedWriter(new FileWriter(filePath, false))
writer.write(data)
} finally {
if (writer != null) {
writer.close()
}
}
}
def verifyResponse(HttpResponseDecorator response) {
if (response != null && response.getData() != null) {
logDebug("Received type: " + response.getData().getClass())
} else {
throw new Exception("Cannot parse response. HttpResponseDecorator or getData() is null.")
}
}
def logDebug(String line) {
logger.quiet("TRANSIFEX_DEBUG: " + line)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment