Android 多語言字串自動檢查 (Android Gradle Task)



更新 (2020/06/30): 感謝 Sam Lu 大大於 FB Android Developer開發讀書會社團提出 Anrdroid Lint 早已有此功能。大家不想重造輪子可跳過此文章。

稍具規模的 Android Project 會使用 Crowd Sourcing 平台來翻譯多國語言字串。觀察了多家公司的 projects 後發現了一普遍性的問題:如果字串中有包含 string formatter (也就是 %d %s),很難避免 Crowd Sourcing 平台上翻譯者對於 string formatter 的不了解,因此時常會有破壞 string formatter 的問題。

<!-- value/strings.xml -->
<string name="sample_text">sample text with format: %s</string>
	
<!-- value-es/strings.xml, %s is altered to % s  -->
<string name="sample_text">sample text with format: % s</string>

在這種 formatter 格式被破壞之後,若字串數量偏多, Code Review 階段就很難找出問題,即使到了測試階段也不一定能驗證到所有語言,因此最終就是在用戶端 Crash 或是顯示不完整文字。

這種問題理應透過自動化的方式來解決,過去在中國互聯網公司時就寫過 script 在 merge 字串時一併檢查 formatter 正確性。最近在轉換職場後發現依然沒有字串格式檢查,所以隨手寫了一下 Android Gradle Task 來做一下 formatter 檢查。

這個檢查主要由兩個部分組成,一個是實際檢驗 XML 字串內容的 python script,另一個則是執行 python script 並且輸入 gradle output log 的 custom gradle task。

檢查的思路大致是:
1. 以英文字串為基礎,建立每一個字串的 formatter map (此處假設英文是正確的,但還是會包含基本檢查,比如 % s 就會直接判別錯誤格式)
2. 對於每一個語言的字串也建立對應 formatter map 並與英文字串的同一字串的 formatter map 對比,如果個數不吻合則判斷為錯誤
對應 source code 在 https://github.com/kswlee/AndroidStringFormatValidator/tree/master/python

準備好 Python Script 後,下一步就是建立一個 custom gradle task 調用。

Android Gradle Task

import groovy.json.JsonSlurper
tasks.register("checkString", Exec) {
    commandLine "python", "check_strings.py"
    workingDir = "${rootProject.projectDir}/python"

    standardOutput = new ByteArrayOutputStream()
    errorOutput = new ByteArrayOutputStream()

    doLast {
        def output = standardOutput.toString()
        def json = new JsonSlurper().parseText(output)
        def is_error = json.is_error
        def is_warning = json.is_warning
        def error = json.error
        def warning = json.warning

        if (is_error) {
            throw new TaskExecutionException(it, new Exception(error.join('\n')))
        }

        if (is_warning) {
            print(warning.join('\n'))
        }
    }
}

這段 code 建立了一個 Exec 類型的 task,並指定以 python 執行 check_strings.py,並把 stdio / stderr 轉向為自定義的 outputstream,在 doLast 階段解析 python script 輸出的 JSON 格式,將錯誤或警告訊息顯示於 gradle build log 裡。

下圖就是當遇到 formatter 被破壞時,我們就可以快速的透過 gradle build output 定位到有問題的字串:

這個多語言自動檢查完整的 Sample 已放上 GitHub: https://github.com/kswlee/AndroidStringFormatValidator/tree/master/python

小結

作為 Programmer,最有價值的是我們可以把手動的工作轉換為自動的程序,減少人為的錯誤,但有時候會被日常的 task 阻礙了這種做開發輔助工具的動機,不過轉換一下思緒:把心思放在日常 task 可能只是在創造 bug,做這類看起來貌似不起眼的輔助工具可能才是真的在減少 bug XD



Leave a Reply

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *