From c5aaa5e6fa3ed7c83814571e628412ef9c5e068c Mon Sep 17 00:00:00 2001 From: Syer10 Date: Wed, 23 Jun 2021 14:08:44 -0400 Subject: [PATCH] Enhance string formatter, add tests to validate translations --- .github/workflows/Check.yml | 42 +++++++++++ build.gradle.kts | 5 +- .../data/translation/XmlResourceBundle.kt | 71 +++++++++++-------- .../ui/base/resources/LocalResources.kt | 2 +- src/main/kotlin/ca/gosyer/ui/main/MainMenu.kt | 2 +- .../kotlin/ca/gosyer/ui/manga/ChapterItem.kt | 2 +- .../ui/settings/SettingsReaderScreen.kt | 4 +- .../resources/values/values-fa/strings.xml | 8 +-- .../resources/values/values-hi/strings.xml | 8 +-- .../resources/values/values-pt-BR/strings.xml | 8 +-- .../resources/values/values-sv/strings.xml | 8 +-- .../resources/values/values-tam/strings.xml | 8 +-- src/main/resources/values/values/strings.xml | 8 +-- .../data/server/ExtensionInteractionTest.kt | 10 --- .../data/translation/XmlResourceBundleTest.kt | 49 +++++++++++++ 15 files changed, 163 insertions(+), 72 deletions(-) create mode 100644 .github/workflows/Check.yml delete mode 100644 src/test/kotlin/ca/gosyer/data/server/ExtensionInteractionTest.kt create mode 100644 src/test/kotlin/ca/gosyer/data/translation/XmlResourceBundleTest.kt diff --git a/.github/workflows/Check.yml b/.github/workflows/Check.yml new file mode 100644 index 00000000..65670b40 --- /dev/null +++ b/.github/workflows/Check.yml @@ -0,0 +1,42 @@ +name: Validate +on: + push: + branches: + - master + pull_request: + +jobs: + check_wrapper: + name: Validate Gradle Wrapper + runs-on: ubuntu-latest + + steps: + - name: Clone repo + uses: actions/checkout@v2 + + - name: Validate Gradle Wrapper + uses: gradle/wrapper-validation-action@v1 + + run_tests: + name: Run Tests + runs-on: ubuntu-latest + + steps: + - name: Clone repo + uses: actions/checkout@v2 + + - uses: actions/setup-java@v1 + with: + java-version: '15' + architecture: x64 + + - name: Setup Cl + run: ./scripts/SetupClUnix.sh + + - name: Run Tests + uses: eskatos/gradle-command-action@v1 + with: + arguments: check + wrapper-cache-enabled: true + dependencies-cache-enabled: true + configuration-cache-enabled: true diff --git a/build.gradle.kts b/build.gradle.kts index c4835b25..3277d82c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,7 +20,7 @@ version = "1.1.1" repositories { mavenCentral() - + google() maven { url = uri("https://maven.pkg.jetbrains.space/public/p/compose/dev") } } @@ -81,7 +81,8 @@ dependencies { implementation("io.github.kerubistan.kroki:kroki-coroutines:1.21") // Testing - testImplementation(kotlin("test-junit5")) + testImplementation(kotlin("test-junit")) + testImplementation(compose("org.jetbrains.compose.ui:ui-test-junit4")) testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion") } diff --git a/src/main/kotlin/ca/gosyer/data/translation/XmlResourceBundle.kt b/src/main/kotlin/ca/gosyer/data/translation/XmlResourceBundle.kt index bdcc111a..69de2a5e 100644 --- a/src/main/kotlin/ca/gosyer/data/translation/XmlResourceBundle.kt +++ b/src/main/kotlin/ca/gosyer/data/translation/XmlResourceBundle.kt @@ -46,18 +46,50 @@ class XmlResourceBundle internal constructor(internal val lookup: Map - string = string.replace( - "%" + (index + 1).toString() + '$' + "s", - s - ) + while (true) { + val index = string.indexOf('%') + if (index < 0) { + stringBuilder.append(string) + break + } else { + stringBuilder.append(string.substring(0, index)) + val stringConfig = string.substring(index, index + 4) + val item = replacements[stringConfig[1].digitToInt() - 1] + when (stringConfig[3]) { + 's' -> { + require(item is String) { "Expected String, got ${item::class.java.simpleName}" } + stringBuilder.append(item) + } + 'd' -> { + when (item) { + is Int -> stringBuilder.append(item) + is Long -> stringBuilder.append(item) + else -> throw IllegalArgumentException("Expected Int or Long, got ${item::class.java.simpleName}") + } + } + 'f' -> { + when (item) { + is Float -> stringBuilder.append(item) + is Double -> stringBuilder.append(item) + else -> throw IllegalArgumentException("Expected Float or Double, got ${item::class.java.simpleName}") + } + } + } + stringBuilder.append(item) + string = string.substring((index + 4).coerceAtMost(string.length), string.length) + } } - return string + return stringBuilder.toString() } companion object { @@ -68,29 +100,6 @@ class XmlResourceBundle internal constructor(internal val lookup: Map 0) append(" • ") append( AnnotatedString( - stringResource("page_progress", (chapter.lastPageRead + 1).toString()), + stringResource("page_progress", (chapter.lastPageRead + 1)), SpanStyle(color = LocalContentColor.current.copy(alpha = ContentAlpha.disabled)) ) ) diff --git a/src/main/kotlin/ca/gosyer/ui/settings/SettingsReaderScreen.kt b/src/main/kotlin/ca/gosyer/ui/settings/SettingsReaderScreen.kt index 69b77015..f6b634d9 100644 --- a/src/main/kotlin/ca/gosyer/ui/settings/SettingsReaderScreen.kt +++ b/src/main/kotlin/ca/gosyer/ui/settings/SettingsReaderScreen.kt @@ -168,9 +168,9 @@ fun SettingsReaderScreen(navController: BackStack) { ) val maxSize by it.maxSize.collectAsState() val (maxSizeTitle, maxSizeSubtitle) = if (direction == Direction.Up || direction == Direction.Down) { - stringResource("max_width") to stringResource("max_width_sub", maxSize.toString()) + stringResource("max_width") to stringResource("max_width_sub", maxSize) } else { - stringResource("max_height") to stringResource("max_height_sub", maxSize.toString()) + stringResource("max_height") to stringResource("max_height_sub", maxSize) } ChoicePreference( it.maxSize, diff --git a/src/main/resources/values/values-fa/strings.xml b/src/main/resources/values/values-fa/strings.xml index 2c6a5c87..e987e193 100644 --- a/src/main/resources/values/values-fa/strings.xml +++ b/src/main/resources/values/values-fa/strings.xml @@ -48,7 +48,7 @@ آیا می‌خواهید رده %1$s را پاک کنید؟ - %1$s تغییر نام + %1$d تغییر نام زبان‌های‌ فعال @@ -57,7 +57,7 @@ پیشفرض - صفحه %1$s + صفحه %1$d خانه @@ -145,9 +145,9 @@ هم اندازه کردن طول اگر طول پنجره از عکس بزرگ تر است، عکس هم اندازه می‌شود حداکثر عرض - طولی که عکس باید از آن کوچک‌تر باشد که مقدار فعلی آن %1$sdp است. می‌شود برای بزرگ تر کردن عکس‌ها استفاده شود + طولی که عکس باید از آن کوچک‌تر باشد که مقدار فعلی آن %1$ddp است. می‌شود برای بزرگ تر کردن عکس‌ها استفاده شود حداکثر طول - طولی که عکس باید از آن کوچک‌تر باشد که مقدار فعلی آن %1$sdp است. می‌شود برای بزرگ تر کردن عکس‌ها استفاده شود. + طولی که عکس باید از آن کوچک‌تر باشد که مقدار فعلی آن %1$ddp است. می‌شود برای بزرگ تر کردن عکس‌ها استفاده شود. آزاد مقیاس عکس هم اندازه صفحه diff --git a/src/main/resources/values/values-hi/strings.xml b/src/main/resources/values/values-hi/strings.xml index a1fdfc49..7ca784ac 100644 --- a/src/main/resources/values/values-hi/strings.xml +++ b/src/main/resources/values/values-hi/strings.xml @@ -47,7 +47,7 @@ Do you wish to delete the category %1$s? - %1$s remaining + %1$d remaining Enabled languages @@ -56,7 +56,7 @@ Default - Page %1$s + Page %1$d Home @@ -144,9 +144,9 @@ Force fit height When the window's height is over the images height, scale the image to the window Max width - Width to restrict a image from going over, currently %1$sdp. Works with the above setting to scale images up but restrict them to a certain amount + Width to restrict a image from going over, currently %1$ddp. Works with the above setting to scale images up but restrict them to a certain amount Max height - Height to restrict a image from going over, currently %1$sdp. Works with the above setting to scale images up but restrict them to a certain amount + Height to restrict a image from going over, currently %1$ddp. Works with the above setting to scale images up but restrict them to a certain amount Unrestricted Image Scale Fit Screen diff --git a/src/main/resources/values/values-pt-BR/strings.xml b/src/main/resources/values/values-pt-BR/strings.xml index 72ab2c3e..60f78998 100644 --- a/src/main/resources/values/values-pt-BR/strings.xml +++ b/src/main/resources/values/values-pt-BR/strings.xml @@ -48,7 +48,7 @@ Você deseja deletar a categoria %1$s? - %1$s Remanescente + %1$d Remanescente Idiomas habilitados @@ -57,7 +57,7 @@ Padrão - Página %1$s + Página %1$d Iníco @@ -145,9 +145,9 @@ Forçar o ajuste de altura Quando a altura da janela estiver acima da altura da imagem, dimensione a imagem para a janela Largura máxima - Largura para impedir que uma imagem ultrapasse, atualmente %1$sdp. Funciona com a configuração acima para dimensionar as imagens, mas restringindo-as a uma certa quantidade + Largura para impedir que uma imagem ultrapasse, atualmente %1$ddp. Funciona com a configuração acima para dimensionar as imagens, mas restringindo-as a uma certa quantidade Altura máxima - Altura para impedir que uma imagem ultrapasse, atualmente %1$sdp. Funciona com a configuração acima para dimensionar as imagens, mas restringindo-as a uma certa quantidade + Altura para impedir que uma imagem ultrapasse, atualmente %1$ddp. Funciona com a configuração acima para dimensionar as imagens, mas restringindo-as a uma certa quantidade Irrestrito Ecala da imagem Tela de ajuste diff --git a/src/main/resources/values/values-sv/strings.xml b/src/main/resources/values/values-sv/strings.xml index a815d7d1..6be133e5 100644 --- a/src/main/resources/values/values-sv/strings.xml +++ b/src/main/resources/values/values-sv/strings.xml @@ -47,7 +47,7 @@ Vill du radera kategorin? %1$s? - %1$s kvar + %1$d kvar Aktiverade språk @@ -56,7 +56,7 @@ Standard - Sida %1$s + Sida %1$d Hem @@ -144,9 +144,9 @@ Tvinga höjdpassning När fönstrets höjd är större än bildens höjd, skala bilden till fönstret Max bredd - Bredd för att begränsa en bild från att gå över, för närvarande% %1$sdp. Fungerar med ovanstående inställning för att skala upp bilder men begränsa dem till en viss mängd + Bredd för att begränsa en bild från att gå över, för närvarande %1$ddp. Fungerar med ovanstående inställning för att skala upp bilder men begränsa dem till en viss mängd Max höjd - Höjd för att begränsa en bild från att gå över, för närvarande% %1$sdp. Fungerar med ovanstående inställning för att skala upp bilder men begränsa dem till en viss mängd + Höjd för att begränsa en bild från att gå över, för närvarande %1$ddp. Fungerar med ovanstående inställning för att skala upp bilder men begränsa dem till en viss mängd Obegränsad Bildskala Passa skärmen diff --git a/src/main/resources/values/values-tam/strings.xml b/src/main/resources/values/values-tam/strings.xml index 78b6254a..4221c8f5 100644 --- a/src/main/resources/values/values-tam/strings.xml +++ b/src/main/resources/values/values-tam/strings.xml @@ -47,7 +47,7 @@ %1$s-ஐ அழிக்க வரும்புகிறீர்களா? - %1$s மீதி + %1$d மீதி இயக்கப்பட்ட மொழிகள் @@ -56,7 +56,7 @@ இயல்புநிலை - பக்கம் %1$s + பக்கம் %1$d முகப்பு @@ -144,9 +144,9 @@ பொருத்தமான உயரம் கட்டாயபடுத்தல் சாளரத்தின் உயரம் படங்களின் உயரத்திற்கு மேல் இருக்கும்போது, ​​படத்தை சாளரத்திற்கு அளவிடவும் அதிகபட்ச அகலம் - படத்து அளவு மேலே செல்வதைத் தடுக்கும் அகலம், இப்பொழுது %1$sdp. இது மேல் அமைவுடன் வேலைசையும் ஆனால் ஒரு அளவுக்கு தான் கட்டுப்படுத்தும் + படத்து அளவு மேலே செல்வதைத் தடுக்கும் அகலம், இப்பொழுது %1$ddp. இது மேல் அமைவுடன் வேலைசையும் ஆனால் ஒரு அளவுக்கு தான் கட்டுப்படுத்தும் அதிகபட்ச உயரம் - படத்து அளவு மேலே செல்வதைத் தடுக்கும் உயரம், இப்பொழுது %1$sdp. இது மேல் அமைவுடன் வேலைசையும் ஆனால் ஒரு அளவுக்கு தான் கட்டுப்படுத்தும் + படத்து அளவு மேலே செல்வதைத் தடுக்கும் உயரம், இப்பொழுது %1$ddp. இது மேல் அமைவுடன் வேலைசையும் ஆனால் ஒரு அளவுக்கு தான் கட்டுப்படுத்தும் கட்டுப்பாடற்ற பட அளவு திரைக்கு பொருது diff --git a/src/main/resources/values/values/strings.xml b/src/main/resources/values/values/strings.xml index 934394d7..01f3b445 100644 --- a/src/main/resources/values/values/strings.xml +++ b/src/main/resources/values/values/strings.xml @@ -48,7 +48,7 @@ Do you wish to delete the category %1$s? - %1$s remaining + %1$d remaining Enabled languages @@ -57,7 +57,7 @@ Default - Page %1$s + Page %1$d Home @@ -145,9 +145,9 @@ Force fit height When the window's height is over the images height, scale the image to the window Max width - Width to restrict a image from going over, currently %1$sdp. Works with the above setting to scale images up but restrict them to a certain amount + Width to restrict a image from going over, currently %1$ddp. Works with the above setting to scale images up but restrict them to a certain amount Max height - Height to restrict a image from going over, currently %1$sdp. Works with the above setting to scale images up but restrict them to a certain amount + Height to restrict a image from going over, currently %1$ddp. Works with the above setting to scale images up but restrict them to a certain amount Unrestricted Image Scale Fit Screen diff --git a/src/test/kotlin/ca/gosyer/data/server/ExtensionInteractionTest.kt b/src/test/kotlin/ca/gosyer/data/server/ExtensionInteractionTest.kt deleted file mode 100644 index 7d6408cd..00000000 --- a/src/test/kotlin/ca/gosyer/data/server/ExtensionInteractionTest.kt +++ /dev/null @@ -1,10 +0,0 @@ -package ca.gosyer.data.server - -import kotlin.test.Test - -class ExtensionInteractionTest { - - @Test - fun `Install a extension`() { - } -} diff --git a/src/test/kotlin/ca/gosyer/data/translation/XmlResourceBundleTest.kt b/src/test/kotlin/ca/gosyer/data/translation/XmlResourceBundleTest.kt new file mode 100644 index 00000000..6029e53c --- /dev/null +++ b/src/test/kotlin/ca/gosyer/data/translation/XmlResourceBundleTest.kt @@ -0,0 +1,49 @@ +package ca.gosyer.data.translation + +import org.junit.Before +import java.io.File +import java.util.Locale +import kotlin.test.Test + +class XmlResourceBundleTest { + + lateinit var rootBundle: XmlResourceBundle + lateinit var bundles: List> + + @Before + fun `load root bundle`() { + rootBundle = XmlResourceBundle.forLocale(Locale.ENGLISH) + val url = XmlResourceBundleTest::class.java.getResource("/values/") + requireNotNull(url) + bundles = requireNotNull( + File(url.toURI()).listFiles()?.mapNotNull { + if (it.name == "values") return@mapNotNull null + it.name.substringAfter("values-") to XmlResourceBundle.forLocale(Locale.forLanguageTag(it.name.substringAfter("values-"))) + } + ) + } + + @Test + fun `test each language parameters`() { + rootBundle.lookup.entries.forEach { (key, value) -> + if (value !is String || !value.contains('%')) return@forEach + val testValues: Array = value.split('%').drop(1).map { + when (val char = it[2]) { + 's' -> "Test string" + 'd' -> 69 + 'f' -> 6.9 + else -> { + throw IllegalArgumentException("Unknown value key $char in $key") + } + } + }.toTypedArray() + bundles.forEach { (lang, bundle) -> + try { + bundle.getString(key, *testValues) + } catch (e: Exception) { + throw Exception("Broken translation in $lang with $key", e) + } + } + } + } +}