Skip to content

Commit 23b4182

Browse files
authored
Merge pull request #23 from LikeTheSalad/release/2.1.0
Release/2.1.0
2 parents 60a1026 + 61f066e commit 23b4182

File tree

29 files changed

+252
-23
lines changed

29 files changed

+252
-23
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Change Log
22
==========
33

4+
Version 2.1.0 *(16-05-2022)*
5+
---
6+
7+
* Added configuration param `includeLocalizedOnlyTemplates` ref #21.
8+
* Fix #20.
9+
* Fix #22.
10+
411
Version 2.0.0 *(19-02-2022)*
512
---
613

README.md

+32
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Table of Contents
1414
* [2.- Running it](#2--running-it)
1515
* [2.1- How to know if it worked?](#21--how-to-know-if-it-worked)
1616
* [2.2- Where can I find the resolved strings in my project?](#22--where-can-i-find-the-resolved-strings-in-my-project)
17+
* [3.- Configuration](#3--configuration)
1718
* [Use case examples](#use-case-examples)
1819
* [1.- Simple use case](#1--simple-use-case)
1920
* [2.- Multi files use case](#2--multi-files-use-case)
@@ -125,6 +126,37 @@ The following cases are supported:
125126
> '*my_message*', inside the 'values-es' folder, and you'll get the
126127
> translated '*my_message*' string in the 'resolved.xml' file inside the 'values-es' folder.
127128
129+
### 3.- Configuration
130+
131+
Stem should work out of the box as you'd expect it to, however, depending on each case, some projects
132+
might have special needs for which some parts of how Stem works might need to be adjusted to meet those needs.
133+
Stem can be configured in your `build.gradle` file where Stem is applied, as shown below along with the currently
134+
available configurable parameters.
135+
136+
```groovy
137+
// build.gradle file where "com.likethesalad.stem" or "com.likethesalad.stem-library" is applied.
138+
139+
androidStem {
140+
// Even though Stem resolves your templates no matter their localization, it searches for templates amongst your
141+
// string resources within the folder "values" only by default (which will be taken as reference for other languages
142+
// when resolving them).
143+
// This is because, ideally, if you have a string that will need a ${placeholder} in it, it should have it
144+
// inside any of that same string's different languages, including the default one ("values").
145+
// So in order to avoid checking for the same strings across different languages looking for ${placeholders}, which could mean
146+
// an expensive processing operation depending on the project, Stem by default only checks the default
147+
// strings when looking for templates, and then based on what it finds within the default strings, it applies
148+
// the placeholder resolving process to all other languages.
149+
//
150+
// However, in some cases some projects might have a string withing the "values" folder that has no ${placeholders}
151+
// in it, but its translations might have them instead (check issue #21 for context). For those cases, you
152+
// could enable this flag so that Stem looks for templates within string resources within the "values" dir
153+
// and also within any language-specific values folders as well.
154+
// Please bear in mind that this might cause performance penalties.
155+
includeLocalizedOnlyTemplates = false // disabled by default
156+
}
157+
158+
```
159+
128160
Use case examples
129161
---
130162
Here's a couple of examples for some of the use cases supported by Android Stem

build.gradle

+6-4
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ buildscript {
1515
classpath "com.likethesalad.tools:plugin-metadata-producer:$pluginMetadataTool_version"
1616
classpath "com.github.gmazzo:gradle-buildconfig-plugin:3.0.3"
1717
classpath 'com.likethesalad.tools:artifact-publisher:1.1.1'
18+
classpath 'com.likethesalad.dagger:remapper-plugin:1.0.1'
1819
}
1920
}
2021

2122
apply plugin: "artifact-publisher"
23+
apply plugin: "com.likethesalad.dagger-remapper"
2224

2325
artifactPublisher {
2426
displayName = "Android Stem"
@@ -29,14 +31,14 @@ artifactPublisher {
2931

3032
description = "This is a Gradle plugin for Android applications which resolves XML string references in other XML strings."
3133
group = 'com.likethesalad.android'
32-
version = '2.0.0'
34+
version = '2.1.0'
3335

3436
ext {
3537
dagger_version = '2.39.1'
3638
androidBuild_version = '7.1.0'
37-
testingUtilities_version = '1.0.7'
38-
resourceLocator_version = '1.1.0'
39-
androidTools_version = "1.1.0"
39+
testingUtilities_version = '1.0.8'
40+
resourceLocator_version = '1.1.1'
41+
androidTools_version = "1.2.0"
4042
}
4143

4244
allprojects {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.likethesalad.android.templates.common.configuration
2+
3+
import com.likethesalad.android.templates.common.plugins.extension.StemExtension
4+
import javax.inject.Inject
5+
import javax.inject.Singleton
6+
7+
@Singleton
8+
class StemConfiguration @Inject constructor(private val extension: StemExtension) {
9+
10+
fun searchForTemplatesInLanguages(): Boolean {
11+
return extension.includeLocalizedOnlyTemplates.get()
12+
}
13+
}

common-tools/src/main/java/com/likethesalad/android/templates/common/plugins/BaseTemplatesProcessorPlugin.kt

+11
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,32 @@
11
package com.likethesalad.android.templates.common.plugins
22

33
import com.likethesalad.android.string.resources.locator.StringResourceLocatorPlugin
4+
import com.likethesalad.android.templates.common.plugins.extension.StemExtension
45
import com.likethesalad.tools.android.plugin.base.AndroidToolsPluginConsumer
56
import com.likethesalad.tools.resource.locator.android.extension.AndroidResourceLocatorExtension
67
import org.gradle.api.Project
78

89
abstract class BaseTemplatesProcessorPlugin : AndroidToolsPluginConsumer() {
910

1011
protected lateinit var stringsLocatorExtension: AndroidResourceLocatorExtension
12+
lateinit var extension: StemExtension
13+
14+
companion object {
15+
private const val EXTENSION_NAME = "androidStem"
16+
}
1117

1218
override fun apply(project: Project) {
1319
validateHostProjectValidForThisPlugin(project)
1420
super.apply(project)
1521
project.plugins.apply(StringResourceLocatorPlugin::class.java)
22+
extension = createExtension(project)
1623
stringsLocatorExtension = project.extensions.getByType(AndroidResourceLocatorExtension::class.java)
1724
}
1825

26+
private fun createExtension(project: Project): StemExtension {
27+
return project.extensions.create(EXTENSION_NAME, StemExtension::class.java)
28+
}
29+
1930
private fun validateHostProjectValidForThisPlugin(project: Project) {
2031
val validHostPluginName = getValidProjectPluginName()
2132
if (!project.plugins.hasPlugin(validHostPluginName)) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.likethesalad.android.templates.common.plugins.extension
2+
3+
import org.gradle.api.model.ObjectFactory
4+
import org.gradle.api.provider.Property
5+
import javax.inject.Inject
6+
7+
@Suppress("UnstableApiUsage")
8+
open class StemExtension @Inject constructor(private val objectFactory: ObjectFactory) {
9+
val includeLocalizedOnlyTemplates: Property<Boolean> = objectFactory.property(Boolean::class.java)
10+
11+
init {
12+
includeLocalizedOnlyTemplates.convention(false)
13+
}
14+
}

common-tools/src/main/java/com/likethesalad/android/templates/common/tasks/identifier/action/TemplatesIdentifierAction.kt

+28-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package com.likethesalad.android.templates.common.tasks.identifier.action
22

3+
import com.likethesalad.android.templates.common.configuration.StemConfiguration
34
import com.likethesalad.android.templates.common.tasks.identifier.data.TemplateItem
45
import com.likethesalad.android.templates.common.tasks.identifier.data.TemplateItemsSerializer
56
import com.likethesalad.android.templates.common.utils.CommonConstants
67
import com.likethesalad.tools.resource.api.android.data.AndroidResourceType
78
import com.likethesalad.tools.resource.api.android.environment.Language
89
import com.likethesalad.tools.resource.api.android.modules.string.StringAndroidResource
10+
import com.likethesalad.tools.resource.api.collection.ResourceCollection
911
import com.likethesalad.tools.resource.locator.android.extension.configuration.data.ResourcesProvider
1012
import dagger.assisted.Assisted
1113
import dagger.assisted.AssistedFactory
@@ -15,6 +17,7 @@ import java.io.File
1517
class TemplatesIdentifierAction @AssistedInject constructor(
1618
@Assisted private val localResources: ResourcesProvider,
1719
@Assisted private val outputFile: File,
20+
private val configuration: StemConfiguration,
1821
private val templateItemsSerializer: TemplateItemsSerializer
1922
) {
2023

@@ -28,10 +31,32 @@ class TemplatesIdentifierAction @AssistedInject constructor(
2831
outputFile.writeText(templateItemsSerializer.serialize(templates))
2932
}
3033

31-
@Suppress("UNCHECKED_CAST")
3234
private fun getTemplatesFromResources(): List<TemplateItem> {
33-
val mainLanguageResources = localResources.resources.getMergedResourcesForLanguage(Language.Default)
34-
val stringResources = mainLanguageResources.getResourcesByType(AndroidResourceType.StringType)
35+
return if (configuration.searchForTemplatesInLanguages()) {
36+
getTemplatesFromAllCollections()
37+
} else {
38+
val mainLanguageResources = localResources.resources.getMergedResourcesForLanguage(Language.Default)
39+
getTemplatesForCollection(mainLanguageResources)
40+
}
41+
}
42+
43+
private fun getTemplatesFromAllCollections(): List<TemplateItem> {
44+
val resources = localResources.resources
45+
val allLanguages = resources.listLanguages()
46+
val templates = mutableSetOf<TemplateItem>()
47+
48+
allLanguages.forEach { language ->
49+
val collection = resources.getMergedResourcesForLanguage(language)
50+
val collectionTemplates = getTemplatesForCollection(collection)
51+
templates.addAll(collectionTemplates)
52+
}
53+
54+
return templates.toList()
55+
}
56+
57+
@Suppress("UNCHECKED_CAST")
58+
private fun getTemplatesForCollection(resourceCollection: ResourceCollection): List<TemplateItem> {
59+
val stringResources = resourceCollection.getResourcesByType(AndroidResourceType.StringType)
3560
val templates = filterTemplates(stringResources as List<StringAndroidResource>)
3661

3762
return templates.sortedBy { it.name() }.map {
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<resources>
33
<string name="welcome_message">Bienvenido a ${app_name}</string>
4+
<string name="language_only_template">Language only template with app name: ${app_name}</string>
45
</resources>

stem-plugin/src/functionalTest/assets/inputs/multi_languages/main/res/values/strings.xml

+1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44

55
<string name="welcome_message">Welcome to ${app_name}</string>
66
<string name="international_welcome_message">Welcome to ${app_name} also known as ${app_international_name}</string>
7+
<string name="language_only_template">This is not a template for main</string>
78
</resources>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<string name="welcome_message">Bienvenido a ${app_name}</string>
4+
<string name="language_only_template">Language only template with app name: ${app_name}</string>
5+
</resources>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<string name="app_name">Idiomas diferentes</string>
4+
</resources>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<resources>
2+
<string name="app_name">Different Languages</string>
3+
<string name="app_international_name" translatable="false">Babel</string>
4+
5+
<string name="welcome_message">Welcome to ${app_name}</string>
6+
<string name="international_welcome_message">Welcome to ${app_name} also known as ${app_international_name}</string>
7+
<string name="language_only_template">This is not a template for main</string>
8+
</resources>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<resources>
2+
<string name="language_only_template">Language only template with app name: Idiomas diferentes</string>
3+
<string name="welcome_message">Bienvenido a Idiomas diferentes</string>
4+
</resources>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<resources>
2+
<string name="international_welcome_message">Welcome to Different Languages also known as Babel</string>
3+
<string name="language_only_template">This is not a template for main</string>
4+
<string name="welcome_message">Welcome to Different Languages</string>
5+
</resources>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<resources>
2+
<string name="someString">Some value</string>
3+
<string name="someTemplate">Some template holding ${someString}</string>
4+
<string name="someLanguageOnlyTemplate">Some template that is not in main ${someString}</string>
5+
</resources>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<resources>
2+
<string name="someString">Some value</string>
3+
<string name="someTemplate">Some template holding ${someString}</string>
4+
</resources>

stem-plugin/src/functionalTest/kotlin/com/likethesalad/stem/CheckOutputsTest.kt

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.likethesalad.stem
22

33
import com.google.common.truth.Truth
4+
import com.likethesalad.stem.testtools.StemConfigBlock
45
import com.likethesalad.tools.functional.testing.AndroidProjectTest
56
import com.likethesalad.tools.functional.testing.app.layout.AndroidAppProjectDescriptor
67
import com.likethesalad.tools.functional.testing.app.layout.AndroidBlockItem
@@ -161,6 +162,18 @@ class CheckOutputsTest : AndroidProjectTest() {
161162
)
162163
}
163164

165+
@Test
166+
fun `verify multi-languages app outputs with localized-only templates`() {
167+
val inOutDirName = "multi_languages_localized_templates"
168+
val androidProjectDescriptor = createAndroidAppProjectDescriptor(
169+
inOutDirName,
170+
config = StemConfigBlock(true)
171+
)
172+
runInputOutputComparisonTest(
173+
inOutDirName, listOf("debug"), androidProjectDescriptor
174+
)
175+
}
176+
164177
@Test
165178
fun `verify app with gradle-generated strings outputs`() {
166179
val appName = "with_gradle_strings"
@@ -298,11 +311,15 @@ class CheckOutputsTest : AndroidProjectTest() {
298311
projectName: String,
299312
inputDirName: String = projectName,
300313
androidBlockItems: List<AndroidBlockItem> = emptyList(),
301-
dependencies: List<String> = emptyList()
314+
dependencies: List<String> = emptyList(),
315+
config: StemConfigBlock? = null
302316
): AndroidAppProjectDescriptor {
303317
val inputDir = getInputTestAsset(inputDirName)
304318
val blockItems = mutableListOf<GradleBlockItem>()
305319
blockItems.addAll(androidBlockItems)
320+
if (config != null) {
321+
blockItems.add(config)
322+
}
306323
val descriptor =
307324
AndroidAppProjectDescriptor(projectName, inputDir, ANDROID_PLUGIN_VERSION, blockItems)
308325
dependencies.forEach { dependency ->

stem-plugin/src/functionalTest/kotlin/com/likethesalad/stem/provider/TemplatesProviderPluginTest.kt

+27-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.likethesalad.android.templates.common.tasks.identifier.data.TemplateI
55
import com.likethesalad.android.templates.common.tasks.identifier.data.TemplateItemsSerializer
66
import com.likethesalad.android.templates.provider.api.TemplatesProvider
77
import com.likethesalad.android_templates.provider.plugin.generated.BuildConfig
8+
import com.likethesalad.stem.testtools.StemConfigBlock
89
import com.likethesalad.stem.utils.TemplatesProviderLoader
910
import com.likethesalad.tools.functional.testing.AndroidProjectTest
1011
import com.likethesalad.tools.functional.testing.layout.AndroidLibProjectDescriptor
@@ -83,6 +84,22 @@ class TemplatesProviderPluginTest : AndroidProjectTest() {
8384
)
8485
}
8586

87+
@Test
88+
fun `Take templates from all languages and main strings if feature enabled`() {
89+
val projectName = "multi_language_all"
90+
val project = setUpProject(projectName, config = StemConfigBlock(true))
91+
92+
runCommand(project, "assembleDebug")
93+
94+
val provider = getTemplatesProvider(project, "debug")
95+
commonVerification(provider, projectName)
96+
assertTemplatesContainExactly(
97+
provider,
98+
TemplateItem("someTemplate", "string"),
99+
TemplateItem("someLanguageOnlyTemplate", "string")
100+
)
101+
}
102+
86103
private fun getTemplatesProvider(project: ProjectDescriptor, variantName: String): TemplatesProvider {
87104
val aarFile = getAarFile(project.projectName, variantName)
88105
val jarFile = extractJar(aarFile)
@@ -135,10 +152,18 @@ class TemplatesProviderPluginTest : AndroidProjectTest() {
135152
return commandStr.split(Regex("[\\s\\t]+"))
136153
}
137154

138-
private fun setUpProject(projectName: String, sourceDirName: String = projectName): ProjectDescriptor {
155+
private fun setUpProject(
156+
projectName: String,
157+
sourceDirName: String = projectName,
158+
config: StemConfigBlock? = null
159+
): ProjectDescriptor {
139160
val inputDir = inputAssetsRoot.getAssetFile(sourceDirName)
140161

141-
val libProjectDescriptor = AndroidLibProjectDescriptor(projectName, inputDir, ANDROID_PLUGIN_VERSION)
162+
val blockItems = if (config != null) listOf(config) else emptyList()
163+
val libProjectDescriptor = AndroidLibProjectDescriptor(
164+
projectName, inputDir, ANDROID_PLUGIN_VERSION,
165+
blockItems
166+
)
142167
libProjectDescriptor.pluginsBlock.addPlugin(GradlePluginDeclaration("com.likethesalad.stem-library"))
143168
return libProjectDescriptor
144169
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.likethesalad.stem.testtools
2+
3+
import com.likethesalad.tools.functional.testing.layout.items.GradleBlockItem
4+
5+
class StemConfigBlock(private val includeLocalizedOnlyTemplates: Boolean) : GradleBlockItem {
6+
7+
override fun getItemText(): String {
8+
return """
9+
androidStem {
10+
includeLocalizedOnlyTemplates = $includeLocalizedOnlyTemplates
11+
}
12+
""".trimIndent()
13+
}
14+
}

stem-plugin/src/main/java/com/likethesalad/stem/ResolvePlaceholdersPlugin.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ class ResolvePlaceholdersPlugin : BaseTemplatesProcessorPlugin(), AndroidExtensi
7676
}
7777

7878
@Suppress("UNCHECKED_CAST")
79-
override fun <T : Task> findTaskByName(name: String): T {
80-
return project.tasks.findByName(name) as T
79+
override fun <T : Task> findTaskByName(name: String): T? {
80+
return project.tasks.findByName(name) as? T
8181
}
8282

8383
override fun getTaskContainer(): TaskContainer {

0 commit comments

Comments
 (0)