Est-il possible d'ajouter dynamiquement String à String.xml dans Android?

495

Est-il possible d'avoir des espaces réservés dans des valeurs de chaîne dans string.xmllesquelles des valeurs peuvent être affectées au moment de l'exécution?

Exemple:

de la chaîne PLACEHOLDER1 de la chaîne

SoftReference
la source
Duplication possible de la référence d'une chaîne d'une autre chaîne dans strings.xml?
Harish Gyanani
@HarishGyanani Non, celui-ci est plus ancien, celui-ci devrait être fusionné à celui-ci à la place
Danh

Réponses:

1036

Formatage et style

Oui, voir ce qui suit dans String Resources: Formating and Styling

Si vous devez formater vos chaînes à l'aide de String.format(String, Object...), vous pouvez le faire en plaçant vos arguments de format dans la ressource de chaîne. Par exemple, avec la ressource suivante:

<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>

Dans cet exemple, la chaîne de format a deux arguments: %1$sest une chaîne et %2$dest un nombre décimal. Vous pouvez formater la chaîne avec des arguments de votre application comme ceci:

Resources res = getResources();
String text = String.format(res.getString(R.string.welcome_messages), username, mailCount);

Utilisation de base

Notez qu'il y getStringa une surcharge qui utilise la chaîne comme chaîne de format:

String text = res.getString(R.string.welcome_messages, username, mailCount);

Pluriels

Si vous devez gérer des pluriels, utilisez ceci:

<plurals name="welcome_messages">
    <item quantity="one">Hello, %1$s! You have a new message.</item>
    <item quantity="other">Hello, %1$s! You have %2$d new messages.</item>
</plurals>

Le premier mailCountparamètre est utilisé pour décider du format à utiliser (simple ou pluriel), les autres paramètres sont vos substitutions:

Resources res = getResources();
String text = res.getQuantityString(R.plurals.welcome_messages, mailCount, username, mailCount);

Voir String Resources: Plurals pour plus de détails.

Megha Joshi - GoogleTV DevRel
la source
61
L'appel String.format dans le premier exemple de code n'est en fait pas nécessaire, Resources.getString () prend en charge le formatage, voir: developer.android.com/reference/android/content/res/… , java.lang.Object ...)
Arnaud
16
pour Plurals in String.xml, vous devez donner id comme R.plurals.welcome_messages au lieu de R.string.welcome_messages
om252345
chose plurielle ne renvoyant que la dernière chaîne d'élément ... toute idée de comment obtenir une chaîne d'ajout.
CoDe
1
Lorsque vous utilisez cette méthode pour formater votre chaîne, elle supprime toutes les balises META que vous avez pu utiliser, telles que des hyperliens, etc. qui auraient pu être contenues dans le texte de la chaîne xml
Jonathan
4
La chaîne représente% 1 $ s, la décimale pour% 2 $ d et l'entier signifie quoi? quelle est la signification de% 1,% 2.C'est ce comptage de paramètre? .si je veux que le troisième paramètre soit la mention% 3?
reegan29
260

Réponse supplémentaire

Quand j'ai vu pour la première fois %1$set %2$ddans la réponse acceptée, cela n'avait aucun sens. Voici un peu plus d'explication.

Ils sont appelés spécificateurs de format. Dans la chaîne xml, ils se présentent sous la forme de

%[parameter_index$][format_type] 
  • % : Le signe de pourcentage marque le début du spécificateur de format.
  • index des paramètres : il s'agit d'un nombre suivi d'un signe dollar. Si vous aviez trois paramètres que vous avez voulu insérer dans la chaîne, ils seraient alors appelés 1$, 2$et 3$. L'ordre dans lequel vous les placez dans la chaîne de ressources n'a pas d'importance, seul l'ordre dans lequel vous fournissez les paramètres.
  • type de format : Il existe de nombreuses façons de formater des éléments ( voir la documentation ). Voici quelques exemples courants:

    • s chaîne
    • d entier décimal
    • f nombre à virgule flottante

Exemple

Nous allons créer la chaîne formatée suivante où les parties grises sont insérées par programme.

Ma soeur Maryest12 ans.

string.xml

<string name="my_xml_string">My sister %1$s is %2$d years old.</string>

MyActivity.java

String myString = "Mary";
int myInt = 12;
String formatted = getString(R.string.my_xml_string, myString, myInt);

Remarques

  • je pourrais utiliser getString parce que j'étais dans une activité. Vous pouvez l'utiliser context.getResources().getString(...)s'il n'est pas disponible.
  • String.format() formatera également une chaîne.
  • Les termes 1$et 2$n'ont pas besoin d'être utilisés dans cet ordre. Autrement dit, 2$peut venir avant1$ . Cela est utile lors de l'internationalisation d'une application pour les langues qui utilisent un ordre de mots différent.
  • Vous pouvez utiliser un spécificateur de format comme %1$s plusieurs fois dans le xml si vous souhaitez le répéter.
  • Utilisez %%pour obtenir le réel% personnage .
  • Pour plus de détails, lisez le didacticiel utile suivant: Astuce rapide du SDK Android: Formatage des chaînes de ressources
Suragch
la source
125

Lorsque vous souhaitez utiliser un paramètre du fichier strings.xml réel sans utiliser de code Java:

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

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

Cela ne fonctionne pas entre les fichiers de ressources, c'est-à-dire que les variables doivent être copiées dans chaque fichier XML qui en a besoin.

Breed Oded
la source
C'est une bonne réponse, sauf lorsque vous avez un paramètre à l'intérieur de <! [CDATA [& param; ]]>
Hermann Poilpre
2
Existe-t-il un moyen de définir la <!DOCTYPE... ]>pièce dans un fichier séparé et de l'inclure dans plusieurs fichiers de ressources? Une astuce pour y parvenir?
prom85
18

Cherchait la même chose et a finalement trouvé la solution très simple suivante. Meilleur: cela fonctionne hors de la boîte.
1. modifiez votre ressource de chaîne:

<string name="welcome_messages">Hello, <xliff:g name="name">%s</xliff:g>! You have 
<xliff:g name="count">%d</xliff:g> new messages.</string>

2. utilisez la substitution de chaîne:

c.getString(R.string.welcome_messages,name,count);

où c est le contexte, le nom est une variable chaîne et comptez votre variable int

Vous devrez inclure

<resources xmlns:xliff="http://schemas.android.com/apk/res-auto">

dans votre res / strings.xml. Travaille pour moi. :)

user3016503
la source
2
À quoi xliffservent les balises autour des spécificateurs de format? Quelle valeur ajoutée ajoutent-ils au lieu d'utiliser uniquement les spécificateurs %set %d?
Richard Le Mesurier
L'attribut "nom" dans la balise xliff est juste un moyen de donner au traducteur un indice sur ce qui y sera substitué. Parfois, il n'est pas facile de deviner ce que signifie le «% s».
hugomg
3

Dans Kotlin, il vous suffit de définir la valeur de votre chaîne comme ceci:

<string name="song_number_and_title">"%1$d ~ %2$s"</string>

Créez une vue texte sur votre mise en page:

<TextView android:id="@+id/song_number_and_title"/>

Ensuite, faites cela dans votre code si vous utilisez Anko:

val song = database.use { // get your song from the database }
song_number_and_title.setText(resources.getString(R.string.song_number_and_title, song.number, song.title))  

Vous devrez peut-être obtenir vos ressources à partir du contexte de l'application.

msbodw001
la source
5
En quoi cela est-il différent des exemples java? Je ne vois aucune différence
Janusz Hain
1

dans res / values ​​/ string.xml

<resources>
    <string name="app_name">Hello World</string>
    <string name="my_application">Application name: %s, package name: %s</string>
</resources>

en code java

String[] args = new String[2];
args[0] = context.getString(R.string.app_name);
args[1] = context.getPackageName();
String textMessage = context.getString(R.string.my_application,(Object[]) args);
Chanh
la source
1

Si vous voulez écrire le pourcentage (%), dupliquez-le:

<string name="percent">%1$d%%</string>

label.text = getString(R.string.percent, 75) // Output: 75%.

Si vous écrivez simplement %1$d%, vous obtiendrez l'erreur: Format string 'percent' is not a valid format string so it should not be passed to String.format.

CoolMind
la source
0

Oui! vous pouvez le faire sans écrire de code Java / Kotlin, uniquement XML en utilisant cette petite bibliothèque que j'ai créée, qui le fait au moment de la construction, de sorte que votre application ne sera pas affectée par celle-ci: https://github.com/LikeTheSalad/android -string-reference

Usage

Vos cordes:

<resources>
    <string name="app_name">My App Name</string>
    <string name="template_welcome_message">Welcome to ${app_name}</string>
</resources>

La chaîne générée après la construction:

<!--resolved.xml-->
<resources>
    <string name="welcome_message">Welcome to My App Name</string>
</resources>
César Muñoz
la source
0

Une solution directe de Kotlin au problème:

strings.xml

<string name="customer_message">Hello, %1$s!\nYou have %2$d Products in your cart.</string>

kotlinActivityORFragmentFile.kt:

val username = "Andrew"
val products = 1000
val text: String = String.format(
      resources.getString(R.string.customer_message), username, products )
nyxee
la source
0

Dans votre fichier de chaîne, utilisez ceci

<string name="redeem_point"> You currently have %s points(%s points = 1 %s)</string>

Et dans votre code, utilisez en conséquence

coinsTextTV.setText(String.format(getContext().getString(R.string.redeem_point), rewardPoints.getReward_points()
                        , rewardPoints.getConversion_rate(), getString(R.string.rs)));
Soni Kumar
la source
-1

Version Kotlin de la réponse acceptée ...

val res = resources
val text = String.format(res.getString(R.string.welcome_messages), username, mailCount)
jesses.co.tt
la source
3
Une manière plus correcte consiste à utiliser la resources.getString(int, ... args)méthode avec des arguments au lieu de String.format. Il n'y a pas non plus de spécificité kotlin dans ce code, autre que valmot clé. Voir la réponse de msbodw001
dant3