-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from CoreWillSoft/feature/localize_support
Add localize CI import/export support
- Loading branch information
Showing
3 changed files
with
191 additions
and
0 deletions.
There are no files selected for viewing
17 changes: 17 additions & 0 deletions
17
.github/workflows/export-en-localization-on-sprint-push.yaml
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
name: export 'en' localization on sprint push | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
|
||
jobs: | ||
build: | ||
if: false # remove when ready | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
with: | ||
fetch-depth: 0 | ||
- name: upload en localisation | ||
run: curl --fail -H "Authorization:Loco ${{ secrets.LOCALISE_KEY }}" --data @app/src/main/res/values/strings.xml https://localise.biz/api/import/xml\?locale\=en\&format\=android\&ignore-existing\=true\&flag-new\=Incomplete |
48 changes: 48 additions & 0 deletions
48
.github/workflows/import-translation-and-test-on-manual-dispatch.yaml
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
name: import translation and test | ||
|
||
on: | ||
workflow_dispatch: | ||
inputs: | ||
import_translation: | ||
description: 'Import translation and test' | ||
|
||
jobs: | ||
build: | ||
if: false # remove when ready | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
with: | ||
fetch-depth: 1 | ||
- name: set up JDK 11 | ||
uses: actions/setup-java@v3 | ||
with: | ||
distribution: 'zulu' | ||
java-version: 11.0.16+1 | ||
cache: 'gradle' | ||
- name: get all translations | ||
run: curl --header "Authorization:Loco ${{ secrets.LOCALISE_KEY }}" https://localise.biz/api/export/archive/xml.zip\?format\=android\&status\=translated -o ./app/src/main/res/xml.zip | ||
- name: apply translations | ||
run: | | ||
unzip -o ./app/src/main/res/xml.zip | ||
rm ./app/src/main/res/xml.zip | ||
cp -rf ####ARCHIVE_NAME####/res app/src/main/ | ||
rm -rf ####ARCHIVE_NAME#### | ||
- name: init build tools | ||
run: ln -s $ANDROID_HOME/build-tools/33.0.2/d8 $ANDROID_HOME/build-tools/33.0.2/dx; ln -s $ANDROID_HOME/build-tools/33.0.2/lib/d8.jar $ANDROID_HOME/build-tools/33.0.2/lib/dx.jar; | ||
- name: run localization tests | ||
run: ./gradlew :app:testRelease --tests io.template.LocalizationTest | ||
- name: Android Test Report | ||
uses: asadmansr/android-test-report-action@v1.2.0 | ||
if: ${{ always() }} | ||
- name: commit files | ||
run: | | ||
git status | ||
git config --local user.email "action@github.com" | ||
git config --local user.name "GitHub Action" | ||
git add -A | ||
git commit -m "Update translations" | ||
- name: push changes | ||
uses: ad-m/github-push-action@master | ||
with: | ||
github_token: ${{ secrets.GITHUB_TOKEN }} |
126 changes: 126 additions & 0 deletions
126
app/src/testUnit/kotlin/io/template/LocalizationTest.kt
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package io.template | ||
|
||
import android.content.res.Resources | ||
import org.junit.FixMethodOrder | ||
import org.junit.Test | ||
import org.junit.jupiter.api.assertDoesNotThrow | ||
import org.junit.runner.RunWith | ||
import org.junit.runners.MethodSorters | ||
import org.robolectric.RobolectricTestRunner | ||
import org.robolectric.RuntimeEnvironment | ||
import org.robolectric.annotation.Config | ||
import kotlin.test.assertEquals | ||
import io.template.app.R | ||
|
||
@RunWith(RobolectricTestRunner::class) | ||
@FixMethodOrder(MethodSorters.NAME_ASCENDING) | ||
class LocalizationTest { | ||
|
||
companion object { | ||
private val PLURAL_QUANTITIES = listOf(0, 1, 2, 3, 5, 11, 21, 42, 102) | ||
private val PLATFORM_PATTERN = Regex("%s|%d|%\\d[$]s|%\\d[$]d") | ||
private val PHRASE_PATTERN = Regex("[{].*?[}]") | ||
private val SKIP_KEYS = listOf("abc_shareactionprovider_share_with_application") | ||
|
||
private var platformPatternMap: Map<String, List<String>> = mapOf() | ||
private var phrasePatternMap: Map<String, List<String>> = mapOf() | ||
} | ||
|
||
private val resources: Resources | ||
get() = RuntimeEnvironment.getApplication().resources | ||
|
||
@Test | ||
@Config(sdk = [28]) | ||
fun initPatterns() { | ||
platformPatternMap = getAllStringsAndPlurals() | ||
.associate { (key, string) -> key to PLATFORM_PATTERN.findAll(string).map { it.value }.toList() } | ||
.filter { (key) -> !SKIP_KEYS.contains(key) } | ||
.filter { (_, list) -> list.isNotEmpty() } | ||
println("platformPatternMap.size - ${platformPatternMap.size}") | ||
|
||
phrasePatternMap = getAllStringsAndPlurals() | ||
.associate { (key, string) -> key to PHRASE_PATTERN.findAll(string).map { it.value }.toList() } | ||
.filter { (key) -> !SKIP_KEYS.contains(key) } | ||
.filter { (_, list) -> list.isNotEmpty() } | ||
println("phrasePatternMap.size - ${phrasePatternMap.size}") | ||
} | ||
|
||
private fun getAllStringsAndPlurals(): List<Pair<String, String>> { | ||
val strings = R.string::class.java.fields.map { it.name to resources.getString(it.getInt(null)) } | ||
val quantities = R.plurals::class.java.fields.map { it.name to resources.getQuantityString(it.getInt(null), 1) } | ||
return strings + quantities | ||
} | ||
|
||
@Test | ||
@Config(sdk = [28], qualifiers = "en") | ||
fun testEnglish() = test() | ||
|
||
@Test | ||
@Config(sdk = [28], qualifiers = "de") | ||
fun testGerman() = test() | ||
|
||
|
||
private fun test() { | ||
testStrings() | ||
testPlurals() | ||
} | ||
|
||
private fun testStrings() { | ||
R.string::class.java.fields.forEach { field -> | ||
val key = field.name | ||
val resourceValue = field.getInt(null) | ||
val value = resources.getString(resourceValue) | ||
|
||
platformPatternMap[key].let { expected -> | ||
if (expected.isNullOrEmpty()) return@let | ||
|
||
val actual = PLATFORM_PATTERN.findAll(value).map { it.value }.toMutableList() | ||
|
||
assertEquals(expected.sorted(), actual.sorted(), "Format arguments are not equal for string with key - $key.") | ||
assertDoesNotThrow("Creating formatted string should be possible with key - $key.") { | ||
resources.getString( | ||
/* id = */ resourceValue, | ||
/* ...formatArgs = */ *expected.map { if (it.contains('s')) "test" else 1 }.toTypedArray() | ||
) | ||
} | ||
} | ||
|
||
phrasePatternMap[key]?.onEach { expectedKey -> | ||
assert(value.contains(expectedKey)) { "Key - $key, value - $value, should contain $expectedKey" } | ||
} | ||
} | ||
} | ||
|
||
private fun testPlurals() { | ||
R.plurals::class.java.fields.forEach { field -> | ||
PLURAL_QUANTITIES.onEach { quantity -> | ||
val key = field.name | ||
val resourceValue = field.getInt(null) | ||
val value = assertDoesNotThrow("Failed to crate plural with key - $key and quantity - $quantity") { | ||
resources.getQuantityString(resourceValue, quantity) | ||
} | ||
assert(value.isNotBlank()) { "Value for key - $key and quantity - $quantity should no be blank" } | ||
|
||
platformPatternMap[key].let { expected -> | ||
if (expected.isNullOrEmpty()) return@let | ||
|
||
val actual = PLATFORM_PATTERN.findAll(value).map { it.value }.toMutableList() | ||
|
||
assertEquals(expected.sorted(), actual.sorted(), "Format arguments are not equal for plural with key - $key " + | ||
"and quantity - $quantity.") | ||
assertDoesNotThrow("Creating formatted plural should be possible with key - $key and quantity - $quantity.") { | ||
resources.getQuantityString( | ||
/* id = */ resourceValue, | ||
/* quantity = */ quantity, | ||
/* ...formatArgs = */ *expected.map { if (it.contains('s')) "test" else 1 }.toTypedArray() | ||
) | ||
} | ||
} | ||
|
||
phrasePatternMap[key]?.onEach { phraseKey -> | ||
assert(value.contains(phraseKey)) { "Key - $key, value - $value, should contain $phraseKey" } | ||
} | ||
} | ||
} | ||
} | ||
} |