diff --git a/.idea/gradle.xml b/.idea/gradle.xml index ae388c2..d7c9288 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -12,6 +12,7 @@ diff --git a/.idea/misc.xml b/.idea/misc.xml index 8978d23..0ad17cb 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,3 +1,4 @@ + diff --git a/README.md b/README.md index 11118d0..13fd0f0 100644 --- a/README.md +++ b/README.md @@ -70,14 +70,14 @@ This simple app helps you avoid forgetting to consume foods that are about to ex
![English default](https://img.shields.io/badge/English-default-blue?style=flat-square) -![Arabic 81%](https://img.shields.io/badge/Arabic-81%25-yellow?style=flat-square) -![French 96%](https://img.shields.io/badge/French-96%25-green?style=flat-square) -![German 93%](https://img.shields.io/badge/German-93%25-yellowgreen?style=flat-square) -![Hindi 70%](https://img.shields.io/badge/Hindi-70%25-orange?style=flat-square) -![Indonesian 100%](https://img.shields.io/badge/Indonesian-100%25-brightgreen?style=flat-square) -![Italian 100%](https://img.shields.io/badge/Italian-100%25-brightgreen?style=flat-square) -![Japanese 84%](https://img.shields.io/badge/Japanese-84%25-yellow?style=flat-square) -![Spanish 100%](https://img.shields.io/badge/Spanish-100%25-brightgreen?style=flat-square) +![Arabic 81%](https://img.shields.io/endpoint?style=flat-square&url=https%3A%2F%2Fraw.githubusercontent.com%2Florenzovngl%2FFoodExpirationDates%2Fmain%2Fshields%2Ftranslations%2Far.json) +![French 96%](https://img.shields.io/endpoint?style=flat-square&url=https%3A%2F%2Fraw.githubusercontent.com%2Florenzovngl%2FFoodExpirationDates%2Fmain%2Fshields%2Ftranslations%2Ffr.json) +![German 93%](https://img.shields.io/endpoint?style=flat-square&url=https%3A%2F%2Fraw.githubusercontent.com%2Florenzovngl%2FFoodExpirationDates%2Fmain%2Fshields%2Ftranslations%2Fde.json) +![Hindi 70%](https://img.shields.io/endpoint?style=flat-square&url=https%3A%2F%2Fraw.githubusercontent.com%2Florenzovngl%2FFoodExpirationDates%2Fmain%2Fshields%2Ftranslations%2Fhi.json) +![Indonesian 100%](https://img.shields.io/endpoint?style=flat-square&url=https%3A%2F%2Fraw.githubusercontent.com%2Florenzovngl%2FFoodExpirationDates%2Fmain%2Fshields%2Ftranslations%2Fin.json) +![Italian 100%](https://img.shields.io/endpoint?style=flat-square&url=https%3A%2F%2Fraw.githubusercontent.com%2Florenzovngl%2FFoodExpirationDates%2Fmain%2Fshields%2Ftranslations%2Fit.json) +![Japanese 84%](https://img.shields.io/endpoint?style=flat-square&url=https%3A%2F%2Fraw.githubusercontent.com%2Florenzovngl%2FFoodExpirationDates%2Fmain%2Fshields%2Ftranslations%2Fja.json) +![Spanish 100%](https://img.shields.io/endpoint?style=flat-square&url=https%3A%2F%2Fraw.githubusercontent.com%2Florenzovngl%2FFoodExpirationDates%2Fmain%2Fshields%2Ftranslations%2Fes.json)
diff --git a/build.gradle.kts b/build.gradle.kts index ec7c759..616171d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,6 +15,7 @@ plugins { alias(libs.plugins.com.android.application) apply false alias(libs.plugins.com.android.library) apply false alias(libs.plugins.org.jetbrains.kotlin.android) apply false + alias(libs.plugins.org.jetbrains.kotlin.jvm) apply false alias(libs.plugins.com.google.dagger.hilt.android) apply false alias(libs.plugins.app.cash.paparazzi) apply false alias(libs.plugins.com.google.devtools.ksp) apply false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 28dd1a8..dd1133a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,6 +25,7 @@ ui-test-junit4 = "1.5.3" uiautomator = "2.2.0" work-runtime-ktx = "2.8.1" splashscreen = "1.0.1" +org-jetbrains-kotlin-jvm = "1.9.10" [libraries] accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanist-systemuicontroller" } @@ -75,5 +76,6 @@ com-android-library = {id = "com.android.library", version.ref = "agp"} com-google-dagger-hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "dagger-hilt"} com-google-devtools-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp"} org-jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "org-jetbrains-kotlin-android" } +org-jetbrains-kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "org-jetbrains-kotlin-jvm" } [bundles] \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 9f91450..d6fd967 100644 --- a/settings.gradle +++ b/settings.gradle @@ -14,3 +14,4 @@ dependencyResolutionManagement { } rootProject.name = "FoodExpirationDates" include ':app' +include ':translation-analyzer' diff --git a/shields/translations/ar.json b/shields/translations/ar.json index 33ecda5..938a5a9 100644 --- a/shields/translations/ar.json +++ b/shields/translations/ar.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "label": "Arabic", - "message": "50%", - "color": "orange", + "message": "81%", + "color": "yellow", "style": "flat-square" } \ No newline at end of file diff --git a/shields/translations/fr.json b/shields/translations/fr.json new file mode 100644 index 0000000..6914c3b --- /dev/null +++ b/shields/translations/fr.json @@ -0,0 +1,7 @@ +{ + "schemaVersion": 1, + "label": "French", + "message": "96%", + "color": "green", + "style": "flat-square" +} \ No newline at end of file diff --git a/shields/translations/hi.json b/shields/translations/hi.json index ff4cc32..e2335c1 100644 --- a/shields/translations/hi.json +++ b/shields/translations/hi.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "label": "Hindi", - "message": "100%", - "color": "brightgreen", + "message": "70%", + "color": "orange", "style": "flat-square" } \ No newline at end of file diff --git a/shields/translations/in.json b/shields/translations/in.json new file mode 100644 index 0000000..d12912d --- /dev/null +++ b/shields/translations/in.json @@ -0,0 +1,7 @@ +{ + "schemaVersion": 1, + "label": "Indonesian", + "message": "100%", + "color": "brightgreen", + "style": "flat-square" +} \ No newline at end of file diff --git a/shields/translations/ja.json b/shields/translations/ja.json new file mode 100644 index 0000000..eeea052 --- /dev/null +++ b/shields/translations/ja.json @@ -0,0 +1,7 @@ +{ + "schemaVersion": 1, + "label": "Japanese", + "message": "84%", + "color": "yellow", + "style": "flat-square" +} \ No newline at end of file diff --git a/translation-analyzer/.gitignore b/translation-analyzer/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/translation-analyzer/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/translation-analyzer/build.gradle.kts b/translation-analyzer/build.gradle.kts new file mode 100644 index 0000000..0c3e34d --- /dev/null +++ b/translation-analyzer/build.gradle.kts @@ -0,0 +1,134 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed +plugins { + alias(libs.plugins.org.jetbrains.kotlin.jvm) +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +dependencies { + implementation(libs.kotlin.stdlib) +} + +val compileKotlin: KotlinCompile by tasks +compileKotlin.kotlinOptions { + jvmTarget = "17" +} + +val compileTestKotlin: KotlinCompile by tasks +compileTestKotlin.kotlinOptions { + jvmTarget = "17" +} + +val locales = mapOf( + "ar" to "Arabic", + "de" to "German", + "en" to "English", + "es" to "Spanish", + "fr" to "French", + "hi" to "Hindi", + "in" to "Indonesian", + "it" to "Italian", + "ja" to "Japanese", +) + +var results: List> = mutableListOf() + +data class JsonEntry( + val schemaVersion: Int = 1, + val label: String, + val message: String, + val color: String, + val style: String = "flat-square" +) { + fun toJson() = "{\n" + + " \"schemaVersion\": $schemaVersion,\n" + + " \"label\": \"$label\",\n" + + " \"message\": \"$message\",\n" + + " \"color\": \"$color\",\n" + + " \"style\": \"$style\"\n" + + "}" +} + +fun path(vararg elements: String) = elements.joinToString(separator = File.separator) + +fun analyzeTranslations(androidProjectPath: String) { + val androidProject = File(androidProjectPath) + val defaultXML = androidProject.walkTopDown() + .filter { + it.absolutePath.endsWith(path("values", "strings.xml")) && + it.absolutePath.contains(path("app", "src", "main")) + }.first() + androidProject.walkTopDown() + .filter { + it.name.endsWith("strings.xml") && it.absolutePath.contains("main") + }.forEach { + parseXML(defaultXML, it) + } +} + +fun parseXML(default: File, translation: File) { + val folderName = translation.absolutePath.substring( + translation.absolutePath.indexOf("values"), + translation.absolutePath.lastIndexOf(File.separator) + ) + val localeKey = folderName.let { + it.substring(startIndex = it.indexOf("-") + 1) + } + val locale = locales[localeKey] + val percent = (countStrings(translation).toDouble() / countStrings(default) * 100).toInt() + val color = percent.let { + when { + it < 50 -> "red" + it < 80 -> "orange" + it < 90 -> "yellow" + it < 95 -> "yellowgreen" + it < 100 -> "green" + else -> "brightgreen" + } + } + if (locale != null) { + results = results.plus(locale to percent) + File(path("shields", "translations", "${localeKey}.json")) + .writeText( + JsonEntry( + label = locale, + message = "$percent%", + color = color + ).toJson() + ) + } +} + +fun countStrings(file: File): Int { + val doc = javax.xml.parsers.DocumentBuilderFactory.newInstance() + .newDocumentBuilder() + .parse(file) + doc.documentElement.normalize() + return doc.getElementsByTagName("string").length + + doc.getElementsByTagName("item").length +} + +tasks.register("analyzeTranslations") { + doLast { + println("Computing translation statistics...") + analyzeTranslations(System.getProperty("user.dir")) + println( + "Translation statistics: ${ + results.sortedBy { + it.first + }.joinToString(separator = ", ") { + "${it.first}: ${it.second}%" + } + }" + ) + } +} + +tasks.named("build") { finalizedBy("analyzeTranslations") } + +tasks.named("assemble") { finalizedBy("analyzeTranslations") } \ No newline at end of file