Created
April 20, 2018 19:31
-
-
Save jush/86750587a12da8ea28ce662e9ddaf77f to your computer and use it in GitHub Desktop.
Gradle script to pull 'strings.xml' from Transifex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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