{"id":15953160,"url":"https://github.com/likethesalad/android-stem","last_synced_at":"2025-04-04T05:07:49.739Z","repository":{"id":40260068,"uuid":"216664268","full_name":"LikeTheSalad/android-stem","owner":"LikeTheSalad","description":"This is a Gradle plugin for Android applications that concatenates XML strings during compilation","archived":false,"fork":false,"pushed_at":"2024-10-02T07:44:59.000Z","size":1056,"stargazers_count":182,"open_issues_count":3,"forks_count":12,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-10-08T13:11:01.615Z","etag":null,"topics":["android","gradle-plugin","resolved-strings","xml-strings"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LikeTheSalad.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":"FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"ko_fi":"likethesalad"}},"created_at":"2019-10-21T20:58:04.000Z","updated_at":"2024-10-02T07:44:08.000Z","dependencies_parsed_at":"2024-04-24T06:43:56.952Z","dependency_job_id":"cdf56ac2-4b06-47de-acde-846d320276d7","html_url":"https://github.com/LikeTheSalad/android-stem","commit_stats":null,"previous_names":["likethesalad/android-string-reference"],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LikeTheSalad%2Fandroid-stem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LikeTheSalad%2Fandroid-stem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LikeTheSalad%2Fandroid-stem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LikeTheSalad%2Fandroid-stem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LikeTheSalad","download_url":"https://codeload.github.com/LikeTheSalad/android-stem/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247123106,"owners_count":20887261,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","gradle-plugin","resolved-strings","xml-strings"],"created_at":"2024-10-07T13:11:00.950Z","updated_at":"2025-04-04T05:07:49.713Z","avatar_url":"https://github.com/LikeTheSalad.png","language":"Kotlin","funding_links":["https://ko-fi.com/likethesalad","https://www.paypal.com/donate/?hosted_button_id=VJWEQ767PEYCA","https://ko-fi.com/N4N31QU53"],"categories":[],"sub_categories":[],"readme":"![version](https://img.shields.io/maven-central/v/com.likethesalad.android/stem-plugin)\n[![Android Arsenal]( https://img.shields.io/badge/Android%20Arsenal-Android%20String%20XML%20Reference-green.svg?style=flat )]( https://android-arsenal.com/details/1/7967 )\n\n[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/donate/?hosted_button_id=VJWEQ767PEYCA)\n[\u003cimg src=\"https://cdn.ko-fi.com/cdn/kofi2.png?v=3\" alt=\"ko-fi\" width=\"100px\"/\u003e](https://ko-fi.com/N4N31QU53)\n\n# Android Stem\n\nTable of Contents\n---\n\n* [What is it](#what-is-it)\n* [How to use](#how-to-use)\n    * [1.- Templates](#1--templates)\n    * [2.- Running it](#2--running-it)\n    * [2.1- How to know if it worked?](#21--how-to-know-if-it-worked)\n    * [2.2- Where can I find the resolved strings in my project?](#22--where-can-i-find-the-resolved-strings-in-my-project)\n    * [3.- Configuration](#3--configuration)\n* [Use case examples](#use-case-examples)\n    * [1.- Simple use case](#1--simple-use-case)\n    * [2.- Multi files use case](#2--multi-files-use-case)\n    * [3.- Multi languages use case](#3--multi-languages-use-case)\n    * [4.- Flavors use case](#4--flavors-use-case)\n* [Adding it to your project](#adding-it-to-your-project)\n    * [1.- Where to find the build.gradle files](#1--where-to-find-the-buildgradle-files)\n    * [2.- What to add to the build.gradle files](#2--what-to-add-to-the-buildgradle-files)\n    * [2.1- Changes to your App's build.gradle file](#22--changes-to-your-apps-buildgradle-file)\n    * [2.2- Adding it to your own Android Libraries (Optional)](#23--adding-it-to-your-own-android-libraries-optional)\n    * [2.3- Sync your project](#24--sync-your-project)\n* [Running it manually](#running-it-manually)\n* [Donations](#donations-)\n* [License](#license)\n\nWhat is it\n---\nAndroid Stem is a Gradle plugin that resolves placeholders\nof XML strings referenced into other XML strings\nat build time. You won't have to write any Java or Kotlin code into your\nproject to make it work, and you will still be able to access to the 'resolved'\nstrings the same way as with any other manually added string to your\nXML files.\n\nIn other words, if you're looking to do something like this:\n\n#### Input:\n\n```xml\n\n\u003cresources\u003e\n    \u003cstring name=\"app_name\"\u003eMy App Name\u003c/string\u003e\n    \u003cstring name=\"welcome_message\"\u003eWelcome to ${app_name}\u003c/string\u003e\n\u003c/resources\u003e\n```\n\n#### Output:\n\n```xml\n\u003c!-- Auto generated during compilation --\u003e\n\u003cresources\u003e\n    \u003cstring name=\"welcome_message\"\u003eWelcome to My App Name\u003c/string\u003e\n\u003c/resources\u003e\n```\n\nWithout having to write any Java or Kotlin code, then Android Stem might help you.\n\nHow to use\n---\n\n### 1.- Templates\n\nAll you have to do is to define string templates inside your XML values' files,\nthe file to add these templates to can be any file inside your values folders,\nnot necessarily the \"strings.xml\" file but **any other XML file within the same directory will\nwork too**.\n\nIn order to create a template all you need to do is to add references to other strings in the form\nof \"placeholders\" into the string you want to use as template, the placeholder format is `${another_string_name}` where\n\"another_string_name\" will be the name of any other string you have in your project or in a library of yours that\nserves as a \"Stem provider\" one, more on it below.\n\nFollowing our example above for our \"my_message\" template, let's say that\nwe have another string in our project named \"app_name\" (which content is \"My app name\") and we want to place it inside\nour \"my_message\" template, we can do it like so:\n\n```xml \n\n\u003cstring name=\"my_message\"\u003eWelcome to ${app_name}\u003c/string\u003e\n```\n\nA template can contain from one to any amount of placeholders. Any string within your values' folder (even other\ntemplates) can be referenced inside a placeholder.\nAnd that's it, we've defined a template. Meaning that\nwhen we compile, we'll get as a result the following \"resolved\" string:\n\n```xml \n\u003c!-- Auto generated during compilation --\u003e\n\u003cstring name=\"my_message\"\u003eWelcome to My app name\u003c/string\u003e\n```\n\n### 2.- Running it\n\nThe process that resolves the string templates will run during\nyour app's compilation process, based on that, there's many ways of running it, some of those could be:\n\n- By pressing on the \"play\" button of Android Studio: ![Play button](./assets/run_button.png \"Play button\")\n- Or, by pressing on the \"make\" button on Android Studio: ![Make button](./assets/make_button.png \"Make button\")\n- Or, if you prefer command line, then you can run it by calling the build command: `./gradlew build` or the assemble\n  command: `./gradlew assemble` or by calling the specific task to resolve the strings which has the following\n  format: `./gradlew resolve[BUILD_VARIANT]Placeholders` more info on this command below under \"**Running it manually**\"\n  .\n\n### 2.1- How to know if it worked?\n\nAfter the task has run, now you will be able to access to the \"resolved\" strings where you'll see that your\nplaceholders have been replaced by the actual referenced values.\n\n### 2.2- Where can I find the resolved strings in my project?\n\nThe resolved strings go into your app's `build` folder, specifically under the `build/generated/resolved` path. That's\nwhere Android Stem places them into when it is run.\n\nThe following cases are supported:\n\n- Regular main strings.\n- Localized (language-specific) strings.\n- Flavor specific strings.\n- Flavor specific with localized strings.\n\n\u003e Both **values and templates** can be overridden for a different **language** and\n\u003e also for a different **flavor**. So if for example you have templates in your\n\u003e project which contain the app name placeholder (e.g. ${app_name}) then if you\n\u003e need to create a flavor with a different app name value, you just have\n\u003e to override the '*app_name*' string inside the flavor's 'values' folder\n\u003e and that's it, now for this flavor you'll get all the old strings but with\n\u003e the new app_name.\n\n\u003e Same for languages, based on the example above, if you need to translate your\n\u003e '*my_message*' string to spanish for example, you just have to override the template\n\u003e '*my_message*', inside the 'values-es' folder, and you'll get the\n\u003e translated '*my_message*' string in the 'resolved.xml' file inside the 'values-es' folder.\n\n### 3.- Configuration\n\nStem should work out of the box as you'd expect it to, however, depending on each case, some projects\nmight have special needs for which some parts of how Stem works might need to be adjusted to meet those needs.\nStem can be configured in your `build.gradle` file where Stem is applied, as shown below along with the currently\navailable configurable parameters.\n\n```groovy\n// build.gradle file where \"com.likethesalad.stem\" or \"com.likethesalad.stem-library\" is applied.\n\nandroidStem {\n    // Even though Stem resolves your templates no matter their localization, it searches for templates amongst your \n    // string resources within the folder \"values\" only by default (which will be taken as reference for other languages \n    // when resolving them).\n    // This is because, ideally, if you have a string that will need a ${placeholder} in it, it should have it\n    // inside any of that same string's different languages, including the default one (\"values\"). \n    // So in order to avoid checking for the same strings across different languages looking for ${placeholders}, which could mean\n    // an expensive processing operation depending on the project, Stem by default only checks the default\n    // strings when looking for templates, and then based on what it finds within the default strings, it applies\n    // the placeholder resolving process to all other languages.\n    //\n    // However, in some cases some projects might have a string withing the \"values\" folder that has no ${placeholders}\n    // in it, but its translations might have them instead (check issue #21 for context). For those cases, you\n    // could enable this flag so that Stem looks for templates within string resources within the \"values\" dir\n    // and also within any language-specific values folders as well.\n    // Please bear in mind that this might cause performance penalties.\n    includeLocalizedOnlyTemplates = false // disabled by default\n\n\n    // The \"placeholder\" config allows to change the format of placeholders which by default look like this: ${placeholder}.\n    placeholder {\n        start = '${' // This is the default value.\n        end = '}' // This is the default value\n    }\n}\n\n```\n\nUse case examples\n---\nHere's a couple of examples for some of the use cases supported by Android Stem\n\n### 1.- Simple use case\n\nWithin our `app/main/res/values` folder, we have the following file:\n\n```xml\n\u003c!--strings.xml--\u003e\n\u003cresources\u003e\n    \u003cstring name=\"app_name\"\u003eTest\u003c/string\u003e\n    \u003cstring name=\"welcome_message\"\u003eWelcome to ${app_name}\u003c/string\u003e\n\u003c/resources\u003e\n```\n\nAfter building our project we get:\n\n```xml\n\u003c!--Auto generated during compilation--\u003e\n\u003cresources\u003e\n    \u003cstring name=\"welcome_message\"\u003eWelcome to Test\u003c/string\u003e\n\u003c/resources\u003e\n```\n\n### 2.- Multi files use case\n\nWithin our `app/main/res/values` folder, we have the following files:\n\n```xml\n\u003c!--strings.xml--\u003e\n\u003cresources\u003e\n    \u003cstring name=\"app_name\"\u003eTest\u003c/string\u003e\n    \u003cstring name=\"welcome_message\"\u003eWelcome to ${app_name}\u003c/string\u003e\n    \u003cstring name=\"app_version_name\"\u003eThe version for ${app_name} is ${my_version}\u003c/string\u003e\n\u003c/resources\u003e\n```\n\n```xml\n\u003c!--my_configs.xml--\u003e\n\u003cresources\u003e\n    \u003cstring name=\"my_version\"\u003e1.0.0\u003c/string\u003e\n\u003c/resources\u003e\n```\n\nAfter building our project we get:\n\n```xml\n\u003c!--Auto generated during compilation--\u003e\n\u003cresources\u003e\n    \u003cstring name=\"app_version_name\"\u003eThe version for Test is 1.0.0\u003c/string\u003e\n    \u003cstring name=\"welcome_message\"\u003eWelcome to Test\u003c/string\u003e\n\u003c/resources\u003e\n```\n\nSo no matter which file contains a template or a value used in a template, as long as it's within your app's values\nfolders, then the plugin will find it.\n\n### 3.- Multi languages use case\n\nWithin our `app/main/res/values` folder, we have the following file:\n\n```xml\n\u003c!--strings.xml--\u003e\n\u003cresources\u003e\n    \u003cstring name=\"app_name\"\u003eTest\u003c/string\u003e\n    \u003cstring name=\"welcome_message\"\u003eWelcome to ${app_name}\u003c/string\u003e\n\u003c/resources\u003e\n```\n\nThen, Within our `app/main/res/values-es` folder, we have the following file:\n\n```xml\n\u003c!--any_file.xml--\u003e\n\u003cresources\u003e\n    \u003cstring name=\"welcome_message\"\u003eBienvenido a ${app_name}\u003c/string\u003e\n\u003c/resources\u003e\n```\n\nAfter building our project, what we get for our default `values` folder is:\n\n```xml\n\u003c!--Auto generated during compilation--\u003e\n\u003cresources\u003e\n    \u003cstring name=\"welcome_message\"\u003eWelcome to Test\u003c/string\u003e\n\u003c/resources\u003e\n```\n\nAnd then what we get for our spanish `values-es` folder is:\n\n```xml\n\u003c!--Auto generated during compilation--\u003e\n\u003cresources\u003e\n    \u003cstring name=\"welcome_message\"\u003eBienvenido a Test\u003c/string\u003e\n\u003c/resources\u003e\n```\n\n### 4.- Flavors use case\n\nLet's say we've defined a flavor in our project, named `demo`, then:\n\nWithin our `app/main/res/values` folder, we have the following files:\n\n```xml\n\u003c!--strings.xml--\u003e\n\u003cresources\u003e\n    \u003cstring name=\"app_name\"\u003eTest\u003c/string\u003e\n    \u003cstring name=\"welcome_message\"\u003eWelcome to ${app_name}\u003c/string\u003e\n    \u003cstring name=\"app_version_name\"\u003eThe version for ${app_name} is ${my_version}\u003c/string\u003e\n\u003c/resources\u003e\n```\n\n```xml\n\u003c!--my_configs.xml--\u003e\n\u003cresources\u003e\n    \u003cstring name=\"my_version\"\u003e1.0.0\u003c/string\u003e\n\u003c/resources\u003e\n```\n\nAnd for our `app/demo/res/values` folder we add the following file:\n\n```xml\n\u003c!--any_file.xml--\u003e\n\u003cresources\u003e\n    \u003cstring name=\"app_name\"\u003eDemo app\u003c/string\u003e\n\u003c/resources\u003e\n```\n\nAfter building the `demo` variant of our project, we'll get for such variant:\n\n```xml\n\u003c!--Auto generated during compilation--\u003e\n\u003cresources\u003e\n    \u003cstring name=\"app_version_name\"\u003eThe version for Demo app is 1.0.0\u003c/string\u003e\n    \u003cstring name=\"welcome_message\"\u003eWelcome to Demo app\u003c/string\u003e\n\u003c/resources\u003e\n```\n\nSo we see that the `app_name` value has been overridden by the demo's app_name, this doesn't only happen for values but\nalso for templates, we can also override templates within our demo's resources.\n\n\u003e Those were some of the use cases that you can achieve using Android Stem, there's more of them such as overriding\n\u003e flavors' multi languages from the base values folder and also working with multi-dimension flavors. You can play\n\u003e around\n\u003e with it, it all should work the way you'd expect it to work.\n\nAdding it to your project\n---\n\nWe're going to need to modify two `build.gradle` files in our project in order to make\nAndroid Stem work, those are:\n\n- **Root's** `build.gradle`\n- **App's** `build.gradle`\n- **Android libraries** `build.gradle` (Optional - If you want to define templates in your own android libraries)\n\n### 1.- Where to find the build.gradle files\n\nTo get a better idea of where you can find these files, take a look at this Android Studio\nscreenshot below:\n\n![Android studio tree dir](./assets/build_gradle_files.png \"Android studio tree dir\")\n\n- The **number 1** selection is to make sure that you've selected the \"Project\"\n  view in order to see the `build.gradle` files as shown on this image.\n- The **number 2** selection represents your **App's build.gradle** file, and it should look similar for Android\n  libraries, if you happen to have any in your project.\n- The **number 3** selection represents your **Root's build.gradle** file.\n\n### 2.- What to add to the build.gradle files\n\n### 2.1- Changes to your App's build.gradle file\n\nIn your `App's build.gradle` file you have to add the following line after the android's app\nplugin `com.android.application`\none:\n\n```groovy\nid \"com.likethesalad.stem\" version \"[latest_version]\"\n```\n\nYou can find the latest version [here](https://plugins.gradle.org/plugin/com.likethesalad.stem).\n\nExample:\n\n```groovy\n// App's build.gradle file\nplugins {\n    id \"com.android.application\"\n    id \"com.likethesalad.stem\" version \"[latest_version]\"\n}\n\nandroid {\n    //...\n}\n```\n\n### 2.2- Adding it to your own Android Libraries (Optional)\n\nIf you have parts of your project split into multiple android libraries where you'd like to define templates, you\ncan do so by applying a \"producer\" version of Stem into them like so:\n\n```groovy\n// Android library's build.gradle file\nplugins {\n    id \"com.android.library\"\n    id \"com.likethesalad.stem-library\" version \"[latest_version]\"\n}\n\nandroid {\n    //...\n}\n```\n\nYou can find the latest version [here](https://plugins.gradle.org/plugin/com.likethesalad.stem-library).\n\nPlease bear in mind that the \"producer\" plugin doesn't resolve templates, it only provides them along with values\nneeded to resolve those, so that the \"consumer\" (application) can use them later on when building the final app.\n\n### 2.3- Sync your project\n\n![Sync button](./assets/sync_now.png \"Sync button\")\n\nAfter your changes to the build.gradle files are done, you should see the above message in Android Studio\nthat has a \"Sync Now\" button. You have to click on that button for the changes to take effect. After the\nsync is done, you'll be ready to go! you can start adding your string templates to your app's resources.\n\nRunning it manually\n---\nIf you want to just run the gradle task that resolves\nthe templates without having to build your project, you can do so\nby running: `resolve[BUILD_VARIANT]Placeholders` depending\non your build configuration. For example, to run it for the debug variant,\nyou'll have to run: `resolveDebugPlaceholders`, or if you have flavors\nset up in your application, e.g. say you have 'demo' as a flavor defined,\nthen you can run `resolveDemoDebugPlaceholders` to generate the strings\nfor the demo flavor on the debug variant and so on.\n\nDonations ♥\n---\nIf this plugin is useful for you, and if it's within your possibilities, please consider making a one-off donation that\nwill help keeping the development of new features and bug support. And if you can't make a donation right now,\nyou could also support this plugin by sharing it with your dev friends and colleagues!\n\n```xml\n\n\u003cstring\u003e\"Thanks for your support, ${your_beautiful_name}!\"\u003c/string\u003e\n```\n\n[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/donate/?hosted_button_id=VJWEQ767PEYCA)\n[\u003cimg src=\"https://cdn.ko-fi.com/cdn/kofi2.png?v=3\" alt=\"ko-fi\" width=\"100px\"/\u003e](https://ko-fi.com/N4N31QU53)\n\nLicense\n---\n\n    MIT License\n    \n    Copyright (c) 2019 LikeTheSalad.\n    \n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n    \n    The above copyright notice and this permission notice shall be included in all\n    copies or substantial portions of the Software.\n    \n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n    SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flikethesalad%2Fandroid-stem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flikethesalad%2Fandroid-stem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flikethesalad%2Fandroid-stem/lists"}