Reference one string from another string in strings.xml?

95,112

Solution 1

A nice way to insert a frequently used string (e.g. app name) in xml without using Java code: source

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE resources [
      <!ENTITY appname "MyAppName">
      <!ENTITY author "MrGreen">
    ]>

<resources>
    <string name="app_name">&appname;</string>
    <string name="description">The &appname; app was created by &author;</string>
</resources>

UPDATE:

You can even define your entity globaly e.g:

res/raw/entities.ent:

<!ENTITY appname "MyAppName">
<!ENTITY author "MrGreen">

res/values/string.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE resources [
    <!ENTITY % ents SYSTEM "./res/raw/entities.ent">
    %ents;   
]>

<resources>
    <string name="app_name">&appname;</string>
    <string name="description">The &appname; app was created by &author;</string>
</resources>

Solution 2

It is possible to reference one within another as long as your entire string consists of the reference name. For example this will work:

<string name="app_name">My App</string>
<string name="activity_title">@string/app_name</string>
<string name="message_title">@string/app_name</string>

It is even more useful for setting default values:

<string name="string1">String 1</string>
<string name="string2">String 2</string>
<string name="string3">String 3</string>
<string name="string_default">@string/string1</string>

Now you can use string_default everywhere in your code and you can easily change the default at any time.

Solution 3

I think you can't. But you can "format" a string as you like:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="button_text">Add item</string>
    <string name="message_text">You don't have any items yet! Add one by pressing the %1$s button.</string>
</resources>

In the code:

Resources res = getResources();
String text = String.format(res.getString(R.string.message_text),
                            res.getString(R.string.button_text));

Solution 4

In Android you can't concatenate Strings inside xml

Following is not supported

<string name="string_default">@string/string1 TEST</string>

Check this link below to know how to achieve it

How to concatenate multiple strings in android XML?

Solution 5

I created simple gradle plugin which allows you to refer one string from another. You can refer strings which are defined in another file, for example in different build variant or library. Cons of this approach - IDE refactor won't find such references.

Use {{string_name}} syntax to refer a string:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="super">Super</string>
    <string name="app_name">My {{super}} App</string>
    <string name="app_description">Name of my application is: {{app_name}}</string>
</resources>

To integrate the plugin, just add next code into you app or library module level build.gradle file

buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "gradle.plugin.android-text-resolver:buildSrc:1.2.0"
  }
}

apply plugin: "com.icesmith.androidtextresolver"

UPDATE: The library doesn't work with Android gradle plugin version 3.0 and above because the new version of the plugin uses aapt2 which packs resources into .flat binary format, so packed resources are unavailable for the library. As a temporary solution you can disable aapt2 by setting android.enableAapt2=false in your gradle.properties file.

Share:
95,112

Related videos on Youtube

dbm
Author by

dbm

Always busy, never too busy

Updated on January 18, 2020

Comments

  • dbm
    dbm over 4 years

    I would like to reference a string from another string in my strings.xml file, like below (specifically note the end of the "message_text" string content):

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="button_text">Add item</string>
        <string name="message_text">You don't have any items yet! Add one by pressing the \'@string/button_text\' button.</string>
    </resources>
    

    I've tried the above syntax but then the text prints out the "@string/button_text" as clear text. Not what I want. I would like the message text to print "You don't have any items yet! Add one by pressing the 'Add item' button."

    Is there any known way to achieve what I want?

    RATIONALE:
    My application has a list of items, but when that list is empty I show a "@android:id/empty" TextView instead. The text in that TextView is to inform the user how to add a new item. I would like to make my layout fool-proof to changes (yes, I'm the fool in question :-)

    • mpkuth
      mpkuth over 7 years
      This answer to another similar question worked for me. No java necessary, but it only works within the same resource file.
  • dbm
    dbm over 13 years
    I was actually hoping for a "non-logic" solution. Nevertheless a fair enough answer (and a the sheer speed of it grants you a green check mark :-)
  • Andrey Novikov
    Andrey Novikov over 13 years
    String text = res.getString(R.string.message_text, res.getString(R.string.button_text)); is a little bit cleaner.
  • Stephen Hosking
    Stephen Hosking over 11 years
    Which also answers the question: how do I refer to the app_name string in an activity title. :)
  • sschuberth
    sschuberth over 11 years
    This should not read "as long as you reference the entire string" (which you always to by definition) but "as long as the referring string resource only consists of the reference name".
  • dbm
    dbm about 11 years
    Well, funny story: that's my answer to a similar question you're referencing :-)
  • Eric Woodruff
    Eric Woodruff over 10 years
    This is not really a reference, this is just an alias, which doesn't solve the problem of composing strings.
  • Eric Woodruff
    Eric Woodruff over 10 years
    This is the closest thing to an answer on this question. I think we need to look into hooking into the layout xml parsing.
  • Admin
    Admin over 8 years
    Is there a way to achieve this?
  • Mauro Panzeri
    Mauro Panzeri over 7 years
    this is the correct answer to the OP. This solution has other great benefits: (1) you can define the DTD in an external file and references it from any resource file to apply the substitution everywhere in your resources. (2) android studio let you rename/references/refactor the defined entities. Though , it does not autocomplete names while writing. (androidstudio 2.2.2)
  • usernotnull
    usernotnull over 7 years
    @MauroPanzeri can you plz provide examples?
  • Mauro Panzeri
    Mauro Panzeri over 7 years
    @RJFares You can go 2 ways: (a) "including" a whole entity file EG: look at this answer. OR (b): including every single entity defined in an external DTD as shown here. Note that neither one is perfect because with (a) you will loose the "refactoring" cabilities and (b) is very verbose
  • jpage4500
    jpage4500 about 7 years
    I like this idea.. but it fails for me with this error: > Could not get unknown property 'referencedString'
  • mr5
    mr5 about 7 years
    Does this technique works with translators? Especially, the one that offered by Google? I'm getting an error in Android Studio as of v2.2.3 when using this
  • zyamys
    zyamys almost 7 years
    Careful if you use this in a Android Library Project - you cannot overwrite it in your app.
  • Ghedeon
    Ghedeon almost 7 years
    @MauroPanzeri didn't manage to reference external entity file. Do you mind to post an example? Thanks.
  • Mauro Panzeri
    Mauro Panzeri almost 7 years
    @Ghedeon: for a working example look here you just need to pay attention to the relative paths. but you'll lose the refactoring ability and i've not checked what happens with androidstudio's GUI for translations.
  • Alvaro Gutierrez Perez
    Alvaro Gutierrez Perez almost 7 years
    @MauroPanzeri gradle gives an error when using the SYSTEM keyword to reference a external entity, so i think they are not supported on android xml files. The error is (in spanish, sorry): Error:(1, 3) Error: El contenido de los elementos debe constar de marcadores o datos de carácter con un formato correcto.
  • Alvaro Gutierrez Perez
    Alvaro Gutierrez Perez almost 7 years
    Ok, I managed to get it working with external entities references, using a mix of both methods that @MauroPanzeri wrote about in his comment. This is the way I got it working: <!DOCTYPE resources [ <!ENTITY % app_name SYSTEM "xml/resources/entities.dtd"> %app_name; ]> (sorry, line feeds not allowed here). Refactor ability is still maintained but only on the same file, the declaration of the entity in the external file is not recognized when refactoring. The path must be relative to the project root for gradle to take it (in the editor you will get a file not found error).
  • Snicolas
    Snicolas over 6 years
    This breaks with aapt2
  • Joseph Garrone
    Joseph Garrone over 6 years
    A example based on this answer of referencing external entities: stackoverflow.com/a/46017525/3731798
  • display name
    display name over 6 years
    has anyone been able to make it work with Android Plugin for Gradle 3.0.0 and Gradle 4.1 or later? I was working on Migrating my Android project and that suddenly stopped working? The error I get is 'The Entity 'something' was referenced, but not declared'
  • Zam Sunk
    Zam Sunk over 6 years
    This is litterally useless, I can't think of any case where this can be useful. Just reference the actual string instead of the "alias"
  • intrepidis
    intrepidis over 6 years
    This doesn't answer the question, they wanted one string embedded in another.
  • Myoch
    Myoch over 6 years
    is it possible to change the entity value when defining flavors in the gradle file?
  • vineeth
    vineeth over 6 years
    @JamesBond where you able to find any solution to make this work with Android Plugin for Gradle 3.0.0 and Gradle 4.1. If not, do you have any other suggestions?. I am still facing the same error - The Entity 'something' was referenced, but not declared' during migration. I had to copy all entities in all strings.xml to make it work.
  • Sarath Kn
    Sarath Kn about 6 years
    even I'm getting the same error something' was referenced, but not declared. Anyone found any solution?
  • maudem
    maudem almost 6 years
    Same problem : The entity "appname" was referenced, but not declared.
  • Davide Cannizzo
    Davide Cannizzo over 5 years
    External entities are not supported by Android Studio anymore, since a bug discussed here: stackoverflow.com/a/51330953/8154765
  • CoolMind
    CoolMind over 5 years
    It is a duplicate of @Francesco Laurita answer, how to programmatically replace a string.
  • CoolMind
    CoolMind over 5 years
    Now you have 53.
  • CoolMind
    CoolMind over 5 years
    You copy other solutions. When reference several strings, use %1$s, %2$s, etc. instead of %s.
  • Ismail Iqbal
    Ismail Iqbal over 5 years
    @CoolMind can you mention the reference to the copy.
  • TheRealChx101
    TheRealChx101 about 5 years
    How about referencing integers from within a string? For instance, in integers.xml, <integer name="min_len">30</integer>. And in strings.xml, <string name="placeholder">Your message needs to be at least @integer/min_len long</string>. I do not want to hard code this value because I know I will change it in the future.
  • César Muñoz
    César Muñoz over 4 years
    I've created a plugin that does pretty much the same and works with aapt2: github.com/LikeTheSalad/android-string-reference :)
  • Vadiraj Purohit
    Vadiraj Purohit over 4 years
    I tried your library. After following the steps you have given. It keeps giving build errors. Your library doesn't work at all
  • César Muñoz
    César Muñoz over 4 years
    I see, sorry to hear that. If you like, please create an issue here: github.com/LikeTheSalad/android-string-reference/issues with the logs and I can address it asap in case that it's a feature problem, or if it's a configuration issue I can also help you there. 👍
  • Jeff Padgett
    Jeff Padgett about 4 years
    This causes a org.xml.sax.SAXException: Scanner State 24 not Recognized for me, Android Studio 3.6.1
  • ban-geoengineering
    ban-geoengineering about 4 years
    Does anyone know if/how it's possible to get our custom entities recognised in a <![CDATA[ ... ]]> string resource?
  • MahNas92
    MahNas92 almost 3 years
    What if app_name looked somethin link <string name="app_name">My App %s$1</string> Can I reference to it and also pass a stringvalue to substitute %s$1 with? (Programatically similar to getString(R.String.app_name, "replacement");)
  • lenooh
    lenooh over 2 years
    This seems like the cleanest solution. Everything else is messy.