SDK 2.3: Get "Multiple substitutions specified in non-positional format" error

11358 views
Skip to first unread message

Streets Of Boston

unread,
Dec 6, 2010, 2:47:23 PM12/6/10
to Android Developers
When this string is in my strings.xml

<string name="home_activity_header_name">%s %s</string>

I get this error when compiling the source-code:
"error: Multiple substitutions specified in non-positional format; did
you mean to add the formatted="false" attribute"

I just upgraded to the newest tools (v 8.0.0) and downloaded the
latest SDK (2.3).
I compile under apil-leverl 8 and i tried compiling under api-level 9.

Why does this error suddenly appear?
Is there a way to get rid of it?

Thanks!

Romain Guy

unread,
Dec 6, 2010, 2:56:29 PM12/6/10
to android-d...@googlegroups.com
To make this work correctly across multiple locales, you should use the following syntax:

$1%s $2%s


--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-d...@googlegroups.com
To unsubscribe from this group, send email to
android-develop...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en



--
Romain Guy
Android framework engineer
roma...@android.com

Note: please don't send private questions to me, as I don't have time to provide private support.  All such questions should be posted on public forums, where I and others can see and answer them

Streets Of Boston

unread,
Dec 6, 2010, 2:56:18 PM12/6/10
to Android Developers
The snipped from the strings.xml in my post above is just an example.
It happens when the value of a string-property has more than one
substitution, e.g.

<string name="page_number">Page %d out of %d</string>

has the same problem.

This has never been a problem before and I'm using it in my app
correctly.... until I upgraded to SDK 2.3/Tools 8.0.0 just now.

Please help...
Message has been deleted

Streets Of Boston

unread,
Dec 6, 2010, 3:08:18 PM12/6/10
to Android Developers
I tried this in the strings.xml:

<string name="home_activity_header_name">$1%s $2%s</string>

I still get the same error when compiling.


On Dec 6, 2:56 pm, Romain Guy <romain...@android.com> wrote:
> To make this work correctly across multiple locales, you should use the
> following syntax:
>
> $1%s $2%s
>
> On Mon, Dec 6, 2010 at 11:47 AM, Streets Of Boston
> <flyingdutc...@gmail.com>wrote:
>
>
>
>
>
> > When this string is in my strings.xml
>
> >   <string name="home_activity_header_name">%s %s</string>
>
> > I get this error when compiling the source-code:
> > "error: Multiple substitutions specified in non-positional format; did
> > you mean to add the formatted="false" attribute"
>
> > I just upgraded to the newest tools (v 8.0.0) and downloaded the
> > latest SDK (2.3).
> > I compile under apil-leverl 8 and i tried compiling under api-level 9.
>
> > Why does this error suddenly appear?
> > Is there a way to get rid of it?
>
> > Thanks!
>
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Android Developers" group.
> > To post to this group, send email to android-d...@googlegroups.com
> > To unsubscribe from this group, send email to
> > android-develop...@googlegroups.com<android-developers%2Bunsubs­cr...@googlegroups.com>
> > For more options, visit this group at
> >http://groups.google.com/group/android-developers?hl=en
>
> --
> Romain Guy
> Android framework engineer
> romain...@android.com
>
> Note: please don't send private questions to me, as I don't have time to
> provide private support.  All such questions should be posted on public
> forums, where I and others can see and answer them- Hide quoted text -
>
> - Show quoted text -

Romain Guy

unread,
Dec 6, 2010, 3:11:14 PM12/6/10
to android-d...@googlegroups.com
My bad, it's %1$s :)
roma...@android.com

Romain Guy

unread,
Dec 6, 2010, 3:08:20 PM12/6/10
to android-d...@googlegroups.com
It wouldn't. What if you translate your app in a language where the second value should appear first? The translation would be $2%s $1%s and the code wouldn't change.

On Mon, Dec 6, 2010 at 12:04 PM, Streets Of Boston <flying...@gmail.com> wrote:
Thank you!

That's new to me, though....

I thought that the position/order of the arguments of the code that
calls the getString method would take care of this.


On Dec 6, 2:56 pm, Romain Guy <romain...@android.com> wrote:
> To make this work correctly across multiple locales, you should use the
> following syntax:
>
> $1%s $2%s
>
> On Mon, Dec 6, 2010 at 11:47 AM, Streets Of Boston

>
>
>
>
>
> > When this string is in my strings.xml
>
> >   <string name="home_activity_header_name">%s %s</string>
>
> > I get this error when compiling the source-code:
> > "error: Multiple substitutions specified in non-positional format; did
> > you mean to add the formatted="false" attribute"
>
> > I just upgraded to the newest tools (v 8.0.0) and downloaded the
> > latest SDK (2.3).
> > I compile under apil-leverl 8 and i tried compiling under api-level 9.
>
> > Why does this error suddenly appear?
> > Is there a way to get rid of it?
>
> > Thanks!
>
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Android Developers" group.
> > To post to this group, send email to android-d...@googlegroups.com
> > To unsubscribe from this group, send email to

> > For more options, visit this group at
> >http://groups.google.com/group/android-developers?hl=en
>
> --
> Romain Guy
> Android framework engineer

>
> Note: please don't send private questions to me, as I don't have time to
> provide private support.  All such questions should be posted on public
> forums, where I and others can see and answer them- Hide quoted text -
>
> - Show quoted text -
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-d...@googlegroups.com
To unsubscribe from this group, send email to
android-develop...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Matt Quigley

unread,
Dec 6, 2010, 4:09:53 PM12/6/10
to Android Developers
On Dec 6, 3:08 pm, Romain Guy <romain...@android.com> wrote:
> It wouldn't. What if you translate your app in a language where the second
> value should appear first? The translation would be $2%s $1%s and the code
> wouldn't change.
>
That may be the case, sometimes, somewhere. It isn't all the time.
There may have been some developers giving strings to a translation
company who returned the string translations and didn't tell the
developers that the order of %s and %s was different, and the software
company didn't have any QA in place to catch this, so some strings
appeared funny for that particular translation.

I don't think the answer to solve this problem, that probably happened
once to someone, with a build error instead of a warning.

And please, it would be nice if someone could take the time to
document what exactly the "formatted" attribute of the <string>
element means. http://developer.android.com/guide/topics/resources/string-resource.html

Thanks,
-Matt

Daniel

unread,
Dec 6, 2010, 4:13:41 PM12/6/10
to Android Developers
What would be the proper way of outputting a % sign, it's giving me
this error on a regular string saying 3%




On Dec 6, 3:08 pm, Romain Guy <romain...@android.com> wrote:
> It wouldn't. What if you translate your app in a language where the second
> value should appear first? The translation would be $2%s $1%s and the code
> wouldn't change.
>
> On Mon, Dec 6, 2010 at 12:04 PM, Streets Of Boston
> <flyingdutc...@gmail.com>wrote:

Xavier Ducrohet

unread,
Dec 6, 2010, 4:31:32 PM12/6/10
to android-d...@googlegroups.com
This suddenly appears because, starting with tools r8, applications
are compiled using the latest version of aapt (the tool that compiles
the android resource).

We used to use version of aapt specific to the version of Android you
compiled against, but not anymore.

Benefits of using the latest versions:
- if we add a feature, you'll get it even if you compile against an
older version. For instance, the new mode that automatically insert
debuggable="true" in your manifest would not be usable on older
versions.
- you get bug fixes too, or behavioral changes. In this case, aapt is
more strict, and while that may be annoying at first, this is really
important to use positional format.

Xav

On Mon, Dec 6, 2010 at 11:47 AM, Streets Of Boston

> --
> You received this message because you are subscribed to the Google
> Groups "Android Developers" group.
> To post to this group, send email to android-d...@googlegroups.com
> To unsubscribe from this group, send email to
> android-develop...@googlegroups.com

> For more options, visit this group at
> http://groups.google.com/group/android-developers?hl=en
>

--
Xavier Ducrohet
Android SDK Tech Lead
Google Inc.

Please do not send me questions directly. Thanks!

Matt Quigley

unread,
Dec 6, 2010, 4:42:13 PM12/6/10
to Android Developers
On Dec 6, 4:13 pm, Daniel <velaz...@gmail.com> wrote:
> What would be the proper way of outputting a % sign, it's giving me
> this error on a regular string saying 3%
>

Outputting just a % sign? Probably %%.
Or, you can leave it as 3% and add formatted="false".

Streets Of Boston

unread,
Dec 6, 2010, 5:18:24 PM12/6/10
to Android Developers
I agree that for internationalization the order spec is important.

However, i read through the changes in the tools and SDK2.3 and I
didn't read about this particular change in aapt (where position is
now required, unless formatted="false" is used). Therefore, the error
came by surprise and it took me a while to figure out (thanks
Romain!).

Also, I only found an example of the positional parameters (1$, 2$,
etc) in an example on this page:
http://developer.android.com/guide/topics/resources/string-resource.html.
I assume that the format is "n$", where n is a digit (or more digits?)
that should appear right after the '%' character. Is this correct? If
not, where can i find more info on this particular format (the
Formatter java-doc does not say anything about the positional
parameters)..
> Please do not send me questions directly. Thanks!- Hide quoted text -

Mark Murphy

unread,
Dec 6, 2010, 5:23:00 PM12/6/10
to android-d...@googlegroups.com
On Mon, Dec 6, 2010 at 5:18 PM, Streets Of Boston
<flying...@gmail.com> wrote:
> Also, I only found an example of the positional parameters (1$, 2$,
> etc) in an example on this page:
> http://developer.android.com/guide/topics/resources/string-resource.html.
> I assume that the format is "n$", where n is a digit (or more digits?)
> that should appear right after the '%' character. Is this correct? If
> not, where can i find more info on this particular format (the
> Formatter java-doc does not say anything about the positional
> parameters)..

Sure it does. Sixth paragraph under Class Overview:

"Argument index. Normally, each format specifier consumes the next
argument to format. For convenient localization, it's possible to
reorder arguments so that they appear in a different order in the
output than the order in which they were supplied. For example, "%4$s"
formats the fourth argument (4$) as a string (s)."

--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy

Android App Developer Books: http://commonsware.com/books

Streets Of Boston

unread,
Dec 6, 2010, 5:29:16 PM12/6/10
to Android Developers
Yep, i stand corrected. It is mentioned. But only as another example.
Nowhere it says that is has to be right after the '%' character.


On Dec 6, 5:23 pm, Mark Murphy <mmur...@commonsware.com> wrote:
> On Mon, Dec 6, 2010 at 5:18 PM, Streets Of Boston
>
> <flyingdutc...@gmail.com> wrote:
> > Also, I only found an example of the positional parameters (1$, 2$,
> > etc) in an example on this page:
> >http://developer.android.com/guide/topics/resources/string-resource.html.
> > I assume that the format is "n$", where n is a digit (or more digits?)
> > that should appear right after the '%' character. Is this correct? If
> > not, where can i find more info on this particular format (the
> > Formatter java-doc does not say anything about the positional
> > parameters)..
>
> Sure it does. Sixth paragraph under Class Overview:
>
> "Argument index. Normally, each format specifier consumes the next
> argument to format. For convenient localization, it's possible to
> reorder arguments so that they appear in a different order in the
> output than the order in which they were supplied. For example, "%4$s"
> formats the fourth argument (4$) as a string (s)."
>
> --
> Mark Murphy (a Commons Guy)http://commonsware.com|http://github.com/commonsguyhttp://commonsware.com/blog|http://twitter.com/commonsguy

Bob Kerns

unread,
Dec 7, 2010, 12:57:42 AM12/7/10
to Android Developers
As someone who's been involved with internationalization of software
for over 25 years -- while I'm certainly glad you provide this syntax,
I think signalling an error is just a bit over the top. A warning
would be sufficient.

Here's why: In my experience (perhaps not comprehensive), the workflow
goes like this: A developer writes the message, in his language of
choice, usually English, but perhaps, say, Japanese, and plops in %s
and friends where appropriate, and arranges the arguments to the
formatting code in the same order as they occur in his format string.

Then someone comes along and whacks him over the head for not
externalizing it for translation, and it is moved to strings.xml or
other localization resource.

Finally, maybe one time in 100, the application is successful enough
to be localized to other languages. One might wish for this to be more
often, but actually I think I'm being generous here. But it's a pain
to do if the previous step hasn't been done, as a matter of practice.
So we'd like to make that as easy as possible. Really, I don't think
we're even close to making it as easy as we should make it! Especially
since the programmer, and likely his manager as well, will correctly
perceive that the effort stands a high probability of being wasted.

Then finally, if we're lucky, we get to translate the app. If we're
really, really lucky, we'll have a QA department that will try to
reproduce as many of the messages as possible, in the original
language.

Now, off goes string.xml and friends to the localization service,
translator, team member, or maybe the developer's wife. Much of the
time, maybe 80% or more, the strings with multiple %s's will not be
using them in a way that is particularly sensitive to language. They
may be constructing an identifier name, or a list, or may occur in
different sentences, which would not in most cases require reordering.

Your mileage may vary on the frequency, of course. But I'd say the
most common use would be something like "%d cats and %d dogs" -- and
ordering is not the problem you face here, but rather, handling of
plurals.

And you get big kudos for addressing it. I hadn't noticed until now
that <plurals/is documented. I don't know if I'd missed seeing it, or
it's a recent addition to the documentation, but thank you! But "%d
gatos y %d perros" or "%d猫と%d犬?" are perfectly fine, from an ordering
standpoint.

BUT! Your Spanish translator is barfing right now, and it has nothing
to do with positionals. The programmer didn't think about plurals.
(yeah, yeah, he should have. See above for the unfortunate reality).
Your translator has to get the programmer to change the code. Bletch.
That likely requires a whole new release. more expensive QA, etc.
Yikes! Maybe we live with it for now, instead.

Now (next release) it goes to the Japanese translator. Who goes, WTF
is this? Well, OK, maybe more like 「なにこれ?」

What used to be easily translated as "%d猫と%d犬" is now just "%d %s and
%d %s", or maybe by now "%1$d %2$s and %3$d %4$s". What's the context?
Should this be "%1$d%2$sと%3$d%4$s", "%1$d%2$sで、%3$d%4$s", or a dozen
other possibilities? Yes, the first guess is still really the only
likely answer given the presence of %d, but still, you've made the
translation job harder.

Given that the original was in English, which has plurals, the
programmer might have supplied that -- but consider if the original
were in Japanese, which almost entirely lacks the concept. Just like
English lacks the concept of a different set of number words for long
skinny things like pencils, vs flat sheets like paper. In that case,
the first time that plurals will enter the picture will be when the
app gets to the English translator, who will get to barf.

Note that even if the Japanese programmer writes it in English
originally, you're still probably going to have the same situation. In
fact, you're likely to have it even if English is your programmer's
native tongue.

In addition to translation, often the text and wording are manipulated
separately from the code, for marketing and/or usability and/or
branding purposes. So the original text may have been "Pigs: %d,
Cattle: %d", and now it's being rebranded for a pet store by someone
who doesn't even have access to the source, and they want to make the
text style more friendly -- and THIS is the first context in which
plurals need to be handled.

Bottom line on that point is that plurals are a linguistic concern,
and should not be institutionalized in Java code. Plural handling
should be fully externalized -- as part of the format syntax. Say,
perhaps, %(3:MyPlural)$s, which rather than directly referencing an
argument, references a <plural/>, and selects the case based on the
numeric value in parameter 3.

The bottom bottom line is, there really isn't much value in asking
programmers to write in the positional arguments. It's more economical
to do so at the point of reordering, which is only a small subset of
the cases - if you get to that point at all.

If you want to force programmers to do something useful -- force them
to define and document what each parameter MEANS. For example, if you
forced the programmer to give each parameter a NAME, instead of a
position in a getString(...) call, the extra effort would not be
duplicative, and you get some improved robustness for your efforts.

For a really radical suggestion:
in strings.xml: <string id='cats_and_dogs'>%(CATS)d %
(CATS:cat_plural)s and %(DOGS)d %(DOGS:dog_plural)s</string>
in Java: getFormatted(R.string.cats_and_dogs).p("DOGS",
dogCount).p("CATS", catCount).asText();

This fully removes order from the picture, provides some self-
documenting characteristics, separates the concerns properly -- and of
course, is completely incompatible with Java's formatting. Though it
is detectable which is which.

And maybe a translate='no' attribute -- then an automated script could
detect where a translator has mistakenly translated an identifier used
as a database key...very annoying...translation isn't the only reason
strings are externalized.

Bob Kerns

unread,
Dec 7, 2010, 1:57:50 AM12/7/10
to Android Developers
Reformatted for readability after the newsgroup reformats it:

For a really radical suggestion:

in strings.xml:
<string id='cats_and_dogs'>
%(CATS)d %(CATS:cat_plural)s and %(DOGS)d %(DOGS:dog_plural)s
</string>

in Java:
getFormatted(R.string.cats_and_dogs)
.p("DOGS", dogCount)
.p("CATS", catCount)
.asText();

Also, as I think this is an issue which transcends Android, I've
posted a reworded version of this on my blog:

http://bobkerns.typepad.com/bob_kerns_thinking/2010/12/dear-java-better-text-formatting-please.html

Feel free to comment about non-Android aspects there.

Ecthelion

unread,
Dec 7, 2010, 4:42:32 AM12/7/10
to Android Developers
I agree with Bob that an error is a bit over the top. E.g. I include
software from another company as a library project in one of my apps.
This foreign software uses the old formatting using %s %s inside a few
strings, which is now reported as an error. Now I can neither change
the string, because this might break functionality, nor may I use the
new SDK because this produces an error where a warning would have been
sufficient. So I am stuck with Android 2.2 SDK :-(.

Mark Murphy

unread,
Dec 7, 2010, 7:45:24 AM12/7/10
to android-d...@googlegroups.com
On Tue, Dec 7, 2010 at 4:42 AM, Ecthelion <ep...@joergjahnke.de> wrote:
> I agree with Bob that an error is a bit over the top. E.g. I include
> software from another company as a library project in one of my apps.
> This foreign software uses the old formatting using %s %s inside a few
> strings, which is now reported as an error. Now I can neither change
> the string, because this might break functionality, nor may I use the
> new SDK because this produces an error where a warning would have been
> sufficient. So I am stuck with Android 2.2 SDK :-(.

If it is an Android library project, you can definitely change the
string. That's half of the point of *having* Android library projects
-- so developers can modify resources as needed. In your project,
override the library's string resource with one of your own with the
same name, and it will be used. You do not have to modify the actual
library project yourself.

--

Warescription: Three Android Books, Plus Updates, One Low Price!

Ecthelion

unread,
Dec 7, 2010, 10:35:10 AM12/7/10
to Android Developers
Yes, if the library project includes all the sources. But in this case
part of the foreign code is inside a jar file. And can I really be
sure that the string is not used somewhere inside this library (e.g.
via getResources().getIdentifier(...)) in a way that breaks once I
modify the resource? In any case I still believe that issueing an
error instead of a warning is over the top.

On 7 Dez., 13:45, Mark Murphy <mmur...@commonsware.com> wrote:
> If it is an Android library project, you can definitely change the
> string. That's half of the point of *having* Android library projects
> -- so developers can modify resources as needed. In your project,
> override the library's string resource with one of your own with the
> same name, and it will be used. You do not have to modify the actual
> library project yourself.
>
> --
> Mark Murphy (a Commons Guy)http://commonsware.com|http://github.com/commonsguyhttp://commonsware.com/blog|http://twitter.com/commonsguy

Mark Murphy

unread,
Dec 7, 2010, 10:39:51 AM12/7/10
to android-d...@googlegroups.com
On Tue, Dec 7, 2010 at 10:35 AM, Ecthelion <ep...@joergjahnke.de> wrote:
> Yes, if the library project includes all the sources. But in this case
> part of the foreign code is inside a jar file.

Resources cannot be in a JAR file.

> And can I really be
> sure that the string is not used somewhere inside this library (e.g.
> via getResources().getIdentifier(...)) in a way that breaks once I
> modify the resource?

Yes.

> In any case I still believe that issueing an
> error instead of a warning is over the top.

I am not disputing that.

--

Bob Kerns

unread,
Dec 7, 2010, 11:20:03 AM12/7/10
to Android Developers
There's a terminology conflict at work here.

Class.getResource(String) and friends vs. Context.getResources() and
friends. To add to the confusion, they really *are* performing the
same task, albeit differently and on disjoint data.

The stuff inside a .jar file is accessed with
Class.getResource(String), while strings.xml is accessed via
Context.getResources().

To add further to the confusion, most of my comments could apply to
either, but the main discussion is referring to
Context.getResources().

Matt Quigley

unread,
Dec 7, 2010, 5:12:11 PM12/7/10
to Android Developers
To all the various responses:

1. To the guys asking about plurals, have you seen
http://developer.android.com/guide/topics/resources/string-resource.html#Plurals
?

2. To the guys who think the errors for the multiple formatters is
over the top... it isn't just over the top, it has really screwed us
over!

I guarantee you what happened is that someone working with Google
wasn't using positional formatters in the strings, and in the latest
batch of translations, one of the positions was supposed to be moved
and it wasn't. So, one person at Google (maybe Romain? he was talking
about it's reasoning earlier) decided that it should be an error for
all people everywhere, because of the screwup in the translation. It
wouldn't have been a problem if this was the way it started out when
Android was initially released, but what actually happened is that the
innocent upgrading of the latest SDK (even though you're supposed to
be able to use any older API levels you want) has made all of our
projects break.

It has made a lot of unnecessary work for me and my team. We've got
multiple projects with a build machine, everything's F'd now. If you
upgrade the SDK Tools on the build machine, half the projects don't
release. Not only that, the same project can have multiple branches
in git. Even as good as git's merging abilities are, after changing
all of the various strings in various branches (which change often),
now the strings.xml is hell to merge when you add in formatted="false"
to the line. To create a hotfix on an older version, we are forced to
make manual changes on these old branches.

To put it succinctly, this seemingly innocuous "feature" to error on
all these types of strings whereas before it didn't has invalidated
every old build in our system, period. There's no way to turn it off,
even if you set the API level to 1. We can no longer build anything
before 12/6/2010, without creating a special separate build machine
which has an old version of the tools on it.

Okay, this rant is over, have a good rest of your day!

Ecthelion

unread,
Dec 8, 2010, 4:01:06 AM12/8/10
to Android Developers
On 7 Dez., 16:39, Mark Murphy <mmur...@commonsware.com> wrote:
> On Tue, Dec 7, 2010 at 10:35 AM, Ecthelion <ep...@joergjahnke.de> wrote:
> > Yes, if the library project includes all the sources. But in this case
> > part of the foreign code is inside a jar file.
>
> Resources cannot be in a JAR file.

Yes, but I never said so. I said foreign "code" is inside the jar
file.

>
> > And can I really be
> > sure that the string is not used somewhere inside this library (e.g.
> > via getResources().getIdentifier(...)) in a way that breaks once I
> > modify the resource?
>
> Yes.

Sorry, but the answer is "no".
Context.getResources().getIdentifier(...) allows any resource inside
the project to be accessed via its name. So there could be code inside
the library jar that accesses the string properties that I am to
modify because they contain "%s %s" or similar text. And I can't be
sure that such text then gets processed correctly.

Mark Murphy

unread,
Dec 8, 2010, 9:14:18 AM12/8/10
to android-d...@googlegroups.com
On Wed, Dec 8, 2010 at 4:01 AM, Ecthelion <ep...@joergjahnke.de> wrote:
>> > And can I really be
>> > sure that the string is not used somewhere inside this library (e.g.
>> > via getResources().getIdentifier(...)) in a way that breaks once I
>> > modify the resource?
>>
>> Yes.
>
> Sorry, but the answer is "no".

No, the answer is yes.

> Context.getResources().getIdentifier(...) allows any resource inside
> the project to be accessed via its name.

Correct.

> So there could be code inside
> the library jar that accesses the string properties that I am to
> modify because they contain "%s %s" or similar text.

Correct.

> And I can't be
> sure that such text then gets processed correctly.

Sure you can. It will be no different than if they accessed the string
via R.string.whatever.

_Android Programming Tutorials_ Version 3.0.1 Available!

Ecthelion

unread,
Dec 8, 2010, 2:40:06 PM12/8/10
to Android Developers
On 8 Dez., 15:14, Mark Murphy <mmur...@commonsware.com> wrote:
>
> Sure you can. It will be no different than if they accessed the string
> via R.string.whatever.
>

Yes. And how would you know how the jar library is processing the
string if the code lies (obfuscated btw.) inside the library? I might
grep the library for all resource names with "%s %s" (or the like)
where I made changes. But if I should find one of these resource names
thereby, how will I know whether the code inside the library relies on
the old string format or whether it works fine with the new "%1$s
%2$s"?

Mark Murphy

unread,
Dec 8, 2010, 2:52:57 PM12/8/10
to android-d...@googlegroups.com
On Wed, Dec 8, 2010 at 2:40 PM, Ecthelion <ep...@joergjahnke.de> wrote:
> Yes. And how would you know how the jar library is processing the
> string if the code lies (obfuscated btw.) inside the library? I might
> grep the library for all resource names with "%s %s" (or the like)
> where I made changes. But if I should find one of these resource names
> thereby, how will I know whether the code inside the library relies on
> the old string format or whether it works fine with the new "%1$s
> %2$s"?

Testing.

Ecthelion

unread,
Dec 9, 2010, 3:50:31 AM12/9/10
to Android Developers
On 8 Dez., 20:52, Mark Murphy <mmur...@commonsware.com> wrote:
> On Wed, Dec 8, 2010 at 2:40 PM, Ecthelion <ep...@joergjahnke.de> wrote:
> > But if I should find one of these resource names
> > thereby, how will I know whether the code inside the library relies on
> > the old string format or whether it works fine with the new "%1$s
> > %2$s"?
>
> Testing.

Brilliant. But that essentially means that I cannot be 100% sure that
my changes would not cause undesired side effects.

Mark Murphy

unread,
Dec 9, 2010, 8:20:55 AM12/9/10
to android-d...@googlegroups.com
On Thu, Dec 9, 2010 at 3:50 AM, Ecthelion <ep...@joergjahnke.de> wrote:
> Brilliant. But that essentially means that I cannot be 100% sure that
> my changes would not cause undesired side effects.

You can't be 100% sure of anything with a third-party library.

How do you ensure that you are passing the proper parameters to
methods? Testing.

How do you ensure that you are covering all RuntimeExceptions the
library might throw? Testing.

How do you ensure that the third-party library handles edge cases
(e.g., WiFi failing over to 3G)? Testing.

And so on.

Resources are, in effect, part of the public API, just like method
parameters and exceptions.

Now, don't get me wrong -- I agree with the general sentiment that the
String.format()/string resource stuff should be a warning, not an
error.

However, modifying resources, particularly string resources, is an
important part of the reuse of an Android library project. No
developer should say "well, we have to live with a messy translation
of this string, because they did not use indexed substitutions, and so
we have to keep everything in the same order, even if that makes no
sense in such-and-so language".

If the developer of a library failed to use indexed substitutions, and
they somehow rely upon the implicit ordering, that is a bug in the
library, plain and simple. Like any other bug in the library, reusers
find out about it via testing, plain and simple.

_The Busy Coder's Guide to *Advanced* Android Development_ Version 1.9
Available!

chaozh

unread,
Dec 9, 2010, 11:18:15 AM12/9/10
to android-d...@googlegroups.com
I still can not solve it with adding 'n$' prefix for every format string. The error still exist.
I'm using android-8 tools but compile with android 2.1 sdk. Is it only used for android 2.3 sdk compiling enviroment?
I tried to add formatted="false" in this string line, just like:
<string name="my name" formatted="false">something %d %s</string>
Still can not pass compilation. How do I do? it make me annoy.
Thanks a lot!

chaozh

unread,
Dec 9, 2010, 11:37:13 AM12/9/10
to android-d...@googlegroups.com
If there is only one format tag in single string line, do I need add '1$' prefix for it?
I don't know what happened on my strings file. I also tried to add the prefix for that string line reported by aapt, but It also tell me the same error is on this line.
I don't know what it really used for format syntax, is only for strict check? or you will add some feature on it in the feature?
If we need replace all format tags even there is only one tag in single string. I don't think this is good way since this change make us do more useless work as so far  I can see.
This change also still not be made clear tag on SDK document. At least, i didn't find it.
Another question, I'm not sure my app can work well on old version if it is compiled with this new change. From my understanding, I think no problem.
Sorry for my poor English. It really make me annoy. Please forgive that my words. I just only want to know how to solve this problem.

chaozh

unread,
Dec 9, 2010, 11:54:48 AM12/9/10
to android-d...@googlegroups.com
The problem solved now. 
The error reported by Eclipse made me confusion. It also made me think this change does not work. Seems there is redundancy error after I made a right change.
Anyway, everything is ok now. Thanks a lot!

Ecthelion

unread,
Dec 10, 2010, 5:21:28 AM12/10/10
to Android Developers
On 9 Dez., 14:20, Mark Murphy <mmur...@commonsware.com> wrote:
> On Thu, Dec 9, 2010 at 3:50 AM, Ecthelion <ep...@joergjahnke.de> wrote:
> > Brilliant. But that essentially means that I cannot be 100% sure that
> > my changes would not cause undesired side effects.
>
> You can't be 100% sure of anything with a third-party library.
>
> How do you ensure that you are passing the proper parameters to
> methods? Testing.
>
> How do you ensure that you are covering all RuntimeExceptions the
> library might throw? Testing.
>
> How do you ensure that the third-party library handles edge cases
> (e.g., WiFi failing over to 3G)? Testing.
>
> And so on.

The obvious difference is that - at least we should hope so when using
other libraries - testing for existing string resources (and other
stuff too) in the library has already been done by the company/person
creating the library, so that if I do not change code of the library I
don't have additional testing effort for checking whether the library
works. This necessity only evolves because of the mentioned change in
the resource compiler forcing me to modify library resources.

Bob Kerns

unread,
Dec 13, 2010, 6:15:13 PM12/13/10
to Android Developers
OK, having actually converted a project with a significant number of
format strings: this thing is MUCH more serious than I thought.

This isn't just a matter of an over-the-top error message.

That's bad enough, of course. But combine that with a BROKEN DETECTOR?

Consider this format string: "foo%nbar%nbaz"

The resource compiler wants me to write this as "foo%1$nbar$1nbaz" or
similar garbage.

Meanwhile, String.format wants me to NOT write such garbage.

It does look like the detector special-cases '%%'.

And while we're on the topic of strange processing of strings.xml --
can you explain just WHY it has this weird behavior with quotation
marks and backslashes? As near as I can tell, it adds zero value but
contributes headaches.

While does mean I can use "\n" as a (non-portable) workaround for the
above problem -- I could have included a newline at least two
different ways without it.

effigy

unread,
Dec 16, 2010, 12:15:03 PM12/16/10
to Android Developers
I love that no one on the ADK team has the balls to admit they fucked
this one up, and us dev's in the process...
> Mark Murphy (a Commons Guy)http://commonsware.com|http://github.com/commonsguyhttp://commonsware.com/blog|http://twitter.com/commonsguy

Richard

unread,
Dec 23, 2010, 7:22:56 AM12/23/10
to Android Developers
I totally agree with people who say that it should only be a warning,
not an error. People at Google must be out of their mind. Sure
positional arguments are a good idea for translations but to suddenly
*force* you to use them is tyrannical, it's like killing you for your
own good!

I was aware of the positional problem and it the rare cases it
mattered I used java.text.MessageFormat instead of String.format.

I updated the SDK to 8 and now suddenly everything is fucked up. I
have an app with 14 translations and another with 5 translations, and
before I can get back to be able to simply compile my apps again I
have to fix them all.

Come on Google, replace the error with a Warning ASAP.

Richard

Bob Kerns

unread,
Dec 23, 2010, 9:24:21 PM12/23/10
to Android Developers
Sorry for the delayed response; I missed seeing your reply until now.

I wasn't asking about plurals. I was commenting that having them as a
string resource but not integrated with the format system is a FAIL,
when you consider the actual translation workflow and lifecycle,
because using them requires a coding change.

But, on those occasions where you are dealing with one language, or
carefully work out IN ADVANCE how to make it all work out with
multiple languages (i.e. supply plurals for every possible argument
that might need them, as an additional argument, and sorting it all
out with positionals in the format string) -- on those occasions, it's
nice to have. Of course, you could have done the same thing with a
string array, but it captures the intent more nicely.

But it does require the programmer to know a lot about translation,
and to get it all set up right in advance.

On Dec 7, 2:12 pm, Matt Quigley <matthew.quig...@gmail.com> wrote:
> To all the various responses:
>
> 1. To the guys asking about plurals, have you seenhttp://developer.android.com/guide/topics/resources/string-resource.h...
> ?

Bob Kerns

unread,
Dec 23, 2010, 9:40:18 PM12/23/10
to Android Developers
Um, no, on this point. Implicit indexing vs explicit indexing is still
ALWAYS exactly the same order.

When you use implicit ordering, say "%s %s", this is always, ALWAYS,
exactly equivalent to "%1$s $2$s". The latter adds NO INFORMATION
WHATSOEVER, and does not remove any ordering dependency. The order of
the ordinals, and the implicit ordering, are both inextricably tied to
the ordering in the code. Now, if %1$s is an adjective, and %2$s is a
noun, and you translate to Spanish, you would have to reverse the
order, and use "%2$s %1$s", but that translation is ALSO tied to the
specific ordering in the Java code.

Not using indexed substitutions in a library resources is NOT A BUG.

I can't even make a decent case, despite seriously trying, for why you
should even PREFER to write "%1$s %2$s" over "%s %s". The closest I
can come boils down to, "it's educational!". And that leads me to the
position that THIS SHOULD NOT EVEN BE A WARNING! (And yes, ALL CAPS
means I AM YELLING!)

The real issue here that Ecthelion is raising is that if you are
mistaken about HOW a string is used, and it is not passed to
String.format, and you introduce the explicit ordinals, then you have
INJECTED A NEW BUG, just to shut up the resource compiler.

(And if you use %n, and you shut up the resource compiler, then you
have INJECTED A NEW BUG, because String.format does not support that,
regardless of what the resource compiler may think!)

In short, this change fixes NO bugs, but does cause or even force
developers to inject new ones. I'm glad I thought to test for %1$n,
rather than blindly accede to the resource compiler's demands!

Bob Kerns

unread,
Dec 23, 2010, 9:43:00 PM12/23/10
to Android Developers
That's rare enough to be noteworthy when it happens. And to be fair, I
have seen a few Mea Culpas expressed on this list.

But I'd be more interested in a commitment to doing something about
it. Unfortunately, it's already too late for many, if not most, of us.

Mr Pants

unread,
Jan 27, 2011, 6:02:09 PM1/27/11
to Android Developers
I might being dense here but in the scenario where I've got an string-
array of URL encoded string eg. urls with %20, how should I handle
these - have tried formatted="false" to no avail - not sure where this
attribute would live in the string-array or the item....neither seem
to have any effect

eg.
<string-array name="teamurls">
<item>http://www.mysttrings.com/string/string%20one</item>
<item>http://www.mysttrings.com/string/string%20one%20two</item>
<item>http://www.mysttrings.com/string/string%20one
%20three</item>
<item>http://www.mysttrings.com/string/string%20one%20four</item>
</string-array>

I use these in a preference list which previously fine prior to
updating the toolset

Cheers

Streets Of Boston

unread,
Jan 28, 2011, 3:33:31 PM1/28/11
to Android Developers
I'm not sure if this would fix it, but have you tried '\%' instead of
just '%'? (escaping the percent sign).

Mr Pants

unread,
Jan 28, 2011, 7:19:18 PM1/28/11
to Android Developers
Hi Streets,

Yes - have tried that but with no success. I've managed to work around
the issue, but it's not ideal.
Seems to me the formatted attribute should be available on strings-
array or item but it's not. This would solve my problem.
Reply all
Reply to author
Forward
0 new messages