From f47bb5bc05dfa55961f6bc16747f8f192d3e9ff7 Mon Sep 17 00:00:00 2001 From: Colin Lee Date: Mon, 1 May 2023 16:08:08 -0500 Subject: [PATCH 1/3] Fix #118: Fill in missing string translations with base translation --- .../resources/desc/PluralFormattedStringDesc.kt | 5 +++++ .../dev/icerock/moko/resources/desc/Utils.kt | 15 +++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/PluralFormattedStringDesc.kt b/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/PluralFormattedStringDesc.kt index 774b7c659..2a18bcec5 100644 --- a/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/PluralFormattedStringDesc.kt +++ b/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/PluralFormattedStringDesc.kt @@ -5,6 +5,7 @@ package dev.icerock.moko.resources.desc import dev.icerock.moko.resources.PluralsResource +import dev.icerock.moko.resources.desc.Utils.FALLBACK_FALLBACK_LOCALE import platform.Foundation.NSBundle import platform.Foundation.NSLocale import platform.Foundation.NSString @@ -37,10 +38,13 @@ internal fun pluralizedString( resourceId: String, number: Int ): String { + val fallbackLocale = bundle.developmentLocalization ?: FALLBACK_FALLBACK_LOCALE val localized = bundle .localizedStringForKey(resourceId, null, null) .takeUnless { it == resourceId } ?: baseBundle.localizedStringForKey(resourceId, null, null) + .takeUnless { it == resourceId } ?: StringDesc.LocaleType.Custom(fallbackLocale) + .getLocaleBundle(bundle).localizedStringForKey(resourceId, null, null) @Suppress("CAST_NEVER_SUCCEEDS") return NSString.create( format = localized, @@ -48,3 +52,4 @@ internal fun pluralizedString( args = arrayOf(number) ) as String } + diff --git a/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/Utils.kt b/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/Utils.kt index b52e5675b..6420ebf5d 100644 --- a/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/Utils.kt +++ b/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/Utils.kt @@ -9,16 +9,23 @@ import platform.Foundation.NSString import platform.Foundation.stringWithFormat object Utils { + const val FALLBACK_FALLBACK_LOCALE = "en" + fun processArgs(args: List): Array { return args.map { (it as? StringDesc)?.localized() ?: it }.toTypedArray() } fun localizedString(stringRes: StringResource): String { val bundle = StringDesc.localeType.getLocaleBundle(stringRes.bundle) - val string = bundle.localizedStringForKey(stringRes.resourceId, null, null) - return if (string == stringRes.resourceId) { - stringRes.bundle.localizedStringForKey(stringRes.resourceId, null, null) - } else string + val stringInCurrentLocale = bundle.localizedStringForKey(stringRes.resourceId, null, null) + return if (stringInCurrentLocale == stringRes.resourceId) { + val stringInDefaultBundle = stringRes.bundle.localizedStringForKey(stringRes.resourceId, null, null) + if (stringInDefaultBundle == stringRes.resourceId) { + val fallbackLocale = stringRes.bundle.developmentLocalization ?: FALLBACK_FALLBACK_LOCALE + val fallbackLocaleBundle = StringDesc.LocaleType.Custom(fallbackLocale).getLocaleBundle(bundle) + fallbackLocaleBundle.localizedStringForKey(stringRes.resourceId, null, null) + } else stringInDefaultBundle + } else stringInCurrentLocale } fun stringWithFormat(format: String, args: Array): String { From dc51d601c42b5b8238c67d4c56a0c6db9e0fe252 Mon Sep 17 00:00:00 2001 From: Konstantin Kolchurin Date: Thu, 6 Jun 2024 14:17:26 +0700 Subject: [PATCH 2/3] #118 rework on usage of Base.localization content, add sample with case in resource-gallery --- .../desc/PluralFormattedStringDesc.kt | 4 +-- .../dev/icerock/moko/resources/desc/Utils.kt | 36 ++++++++++++++----- .../kotlin/com/icerockdev/library/Testing.kt | 1 + .../moko-resources/base/strings.xml | 1 + 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/PluralFormattedStringDesc.kt b/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/PluralFormattedStringDesc.kt index 14cd43f32..156892dfc 100644 --- a/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/PluralFormattedStringDesc.kt +++ b/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/PluralFormattedStringDesc.kt @@ -5,7 +5,7 @@ package dev.icerock.moko.resources.desc import dev.icerock.moko.resources.PluralsResource -import dev.icerock.moko.resources.desc.Utils.FALLBACK_FALLBACK_LOCALE +import dev.icerock.moko.resources.desc.Utils.BASE_LOCALIZATION import kotlinx.cinterop.BetaInteropApi import platform.Foundation.NSBundle import platform.Foundation.NSLocale @@ -40,7 +40,7 @@ internal fun pluralizedString( resourceId: String, number: Int ): String { - val fallbackLocale = bundle.developmentLocalization ?: FALLBACK_FALLBACK_LOCALE + val fallbackLocale = bundle.developmentLocalization ?: BASE_LOCALIZATION val localized = bundle .localizedStringForKey(resourceId, null, null) .takeUnless { it == resourceId } diff --git a/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/Utils.kt b/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/Utils.kt index eb9b6b80a..1320113bc 100644 --- a/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/Utils.kt +++ b/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/Utils.kt @@ -9,7 +9,7 @@ import platform.Foundation.NSString import platform.Foundation.stringWithFormat object Utils { - const val FALLBACK_FALLBACK_LOCALE = "en" + const val BASE_LOCALIZATION: String = "Base" fun processArgs(args: List): Array { return args.map { (it as? StringDesc)?.localized() ?: it }.toTypedArray() @@ -17,15 +17,35 @@ object Utils { fun localizedString(stringRes: StringResource): String { val bundle = StringDesc.localeType.getLocaleBundle(stringRes.bundle) - val stringInCurrentLocale = bundle.localizedStringForKey(stringRes.resourceId, null, null) + val stringInCurrentLocale = bundle.localizedStringForKey( + key = stringRes.resourceId, + value = null, + table = null + ) + return if (stringInCurrentLocale == stringRes.resourceId) { - val stringInDefaultBundle = stringRes.bundle.localizedStringForKey(stringRes.resourceId, null, null) + val stringInDefaultBundle = stringRes.bundle.localizedStringForKey( + key = stringRes.resourceId, + value = null, + table = null + ) + if (stringInDefaultBundle == stringRes.resourceId) { - val fallbackLocale = stringRes.bundle.developmentLocalization ?: FALLBACK_FALLBACK_LOCALE - val fallbackLocaleBundle = StringDesc.LocaleType.Custom(fallbackLocale).getLocaleBundle(bundle) - fallbackLocaleBundle.localizedStringForKey(stringRes.resourceId, null, null) - } else stringInDefaultBundle - } else stringInCurrentLocale + val fallbackLocale = stringRes.bundle.developmentLocalization ?: BASE_LOCALIZATION + val fallbackLocaleBundle = StringDesc.LocaleType + .Custom(fallbackLocale) + .getLocaleBundle(stringRes.bundle) + fallbackLocaleBundle.localizedStringForKey( + key = stringRes.resourceId, + value = null, + table = null + ) + } else { + stringInDefaultBundle + } + } else { + stringInCurrentLocale + } } fun stringWithFormat(format: String, args: Array): String { diff --git a/samples/resources-gallery/mpp-library/src/commonMain/kotlin/com/icerockdev/library/Testing.kt b/samples/resources-gallery/mpp-library/src/commonMain/kotlin/com/icerockdev/library/Testing.kt index bd9a5e03d..943a58183 100644 --- a/samples/resources-gallery/mpp-library/src/commonMain/kotlin/com/icerockdev/library/Testing.kt +++ b/samples/resources-gallery/mpp-library/src/commonMain/kotlin/com/icerockdev/library/Testing.kt @@ -28,6 +28,7 @@ import dev.icerock.moko.resources.getImageByFileName public object Testing { public fun getStrings(): List { return listOf( + MR.strings.text_only_in_base.desc(), MR.strings.test_simple.desc(), MR.strings.test2.desc(), MR.strings.test3.desc(), diff --git a/samples/resources-gallery/mpp-library/src/commonMain/moko-resources/base/strings.xml b/samples/resources-gallery/mpp-library/src/commonMain/moko-resources/base/strings.xml index c173d9ca6..94193e268 100644 --- a/samples/resources-gallery/mpp-library/src/commonMain/moko-resources/base/strings.xml +++ b/samples/resources-gallery/mpp-library/src/commonMain/moko-resources/base/strings.xml @@ -7,4 +7,5 @@ first line\nsecond line\nthird line. Alex009 said "hello world" & "write tests". Alex009 said 'hello' + Text from base locale From fab0b79c296eda3165d6c99929addbd780f7fef9 Mon Sep 17 00:00:00 2001 From: Konstantin Kolchurin Date: Thu, 6 Jun 2024 14:26:42 +0700 Subject: [PATCH 3/3] #118 added ios missing localization tests --- .../desc/AppleLocalizationBundleTests.kt | 47 +++++++++++++++++++ .../PluralFormattedStringDescStringTests.kt | 10 ++++ .../Resources/Base.lproj/Localizable.strings | 2 + .../Resources/es-US.lproj/Localizable.strings | 1 + 4 files changed, 60 insertions(+) create mode 100644 resources/src/iosTest/kotlin/dev/icerock/moko/resources/desc/AppleLocalizationBundleTests.kt create mode 100644 resources/src/iosTest/resources/tests.bundle/Contents/Resources/Base.lproj/Localizable.strings create mode 100644 resources/src/iosTest/resources/tests.bundle/Contents/Resources/es-US.lproj/Localizable.strings diff --git a/resources/src/iosTest/kotlin/dev/icerock/moko/resources/desc/AppleLocalizationBundleTests.kt b/resources/src/iosTest/kotlin/dev/icerock/moko/resources/desc/AppleLocalizationBundleTests.kt new file mode 100644 index 000000000..b9b0eb509 --- /dev/null +++ b/resources/src/iosTest/kotlin/dev/icerock/moko/resources/desc/AppleLocalizationBundleTests.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2024 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.resources.desc + +import dev.icerock.moko.resources.StringResource +import platform.Foundation.NSBundle +import kotlin.test.Test +import kotlin.test.assertEquals + +class AppleLocalizationBundleTests { + + @Test + fun localizedStringWithLocalizationCaseTest() { + val resource = StringResource( + resourceId = "noResultsFound", + bundle = NSBundle.bundleWithPath(NSBundle.mainBundle.bundlePath + "/tests.bundle")!! + ) + StringDesc.localeType = StringDesc.LocaleType.Custom("es-US") + val stringDesc = ResourceStringDesc( + resource + ) + assertEquals( + expected = "No se han encontrado resultados", + actual = stringDesc.localized() + ) + StringDesc.localeType = StringDesc.LocaleType.System + } + + @Test + fun localizedStringMissingLocalizationCaseTest() { + val resource = StringResource( + resourceId = "noInternetConnection", + bundle = NSBundle.bundleWithPath(NSBundle.mainBundle.bundlePath + "/tests.bundle")!! + ) + StringDesc.localeType = StringDesc.LocaleType.Custom("es-US") + val stringDesc = ResourceStringDesc( + resource + ) + assertEquals( + expected = "No internet connection", + actual = stringDesc.localized() + ) + StringDesc.localeType = StringDesc.LocaleType.System + } +} diff --git a/resources/src/iosTest/kotlin/dev/icerock/moko/resources/desc/PluralFormattedStringDescStringTests.kt b/resources/src/iosTest/kotlin/dev/icerock/moko/resources/desc/PluralFormattedStringDescStringTests.kt index a6a9eb6ea..7326b2b89 100644 --- a/resources/src/iosTest/kotlin/dev/icerock/moko/resources/desc/PluralFormattedStringDescStringTests.kt +++ b/resources/src/iosTest/kotlin/dev/icerock/moko/resources/desc/PluralFormattedStringDescStringTests.kt @@ -50,6 +50,16 @@ class PluralFormattedStringDescStringTests { ) } + @Test + fun testMissingLocalizationCase() { + StringDesc.localeType = StringDesc.LocaleType.Custom("es-US") + assertEquals( + expected = "6/10 items", + actual = createPluralFormatted(6).localized() + ) + StringDesc.localeType = StringDesc.LocaleType.System + } + private fun createPluralFormatted(number: Int): PluralFormattedStringDesc { val pluralResource = PluralsResource( resourceId = "stringFormatted", diff --git a/resources/src/iosTest/resources/tests.bundle/Contents/Resources/Base.lproj/Localizable.strings b/resources/src/iosTest/resources/tests.bundle/Contents/Resources/Base.lproj/Localizable.strings new file mode 100644 index 000000000..d8a3af0a7 --- /dev/null +++ b/resources/src/iosTest/resources/tests.bundle/Contents/Resources/Base.lproj/Localizable.strings @@ -0,0 +1,2 @@ +"noResultsFound" = "No results found"; +"noInternetConnection" = "No internet connection"; \ No newline at end of file diff --git a/resources/src/iosTest/resources/tests.bundle/Contents/Resources/es-US.lproj/Localizable.strings b/resources/src/iosTest/resources/tests.bundle/Contents/Resources/es-US.lproj/Localizable.strings new file mode 100644 index 000000000..d42e46e4a --- /dev/null +++ b/resources/src/iosTest/resources/tests.bundle/Contents/Resources/es-US.lproj/Localizable.strings @@ -0,0 +1 @@ +"noResultsFound" = "No se han encontrado resultados"; \ No newline at end of file