diff --git a/xwords4/android/XWords4/res/values/strings.xml b/xwords4/android/XWords4/res/values/strings.xml
index 6fce9acd2..e51362325 100644
--- a/xwords4/android/XWords4/res/values/strings.xml
+++ b/xwords4/android/XWords4/res/values/strings.xml
@@ -28,7 +28,7 @@
- %s (robot)
+ %1$s (robot)
Configured for room
- \"%s\"
+ \"%1$s\"
Waiting for players in room
- \"%s\"
+ \"%1$s\"
- Game in play in room \"%s\"
+ Game in play in room \"%1$s\"
- Game over in room \"%s\"
+ Game over in room \"%1$s\"
Game over
- %d moves played
+ %1$d moves played
- \"%s\" actions:
+ \"%1$s\" actions:
@@ -155,11 +155,11 @@
Change the name of this game to:
Are you sure you want to delete
- the %d selected game[s]? This action cannot be undone.
+ the %1$d selected game[s]? This action cannot be undone.
- Are you sure you want to reset the %d
+ Are you sure you want to reset the %1$d
selected game[s]?\n\n(Resetting erases all moves and any connection
information.)
@@ -222,24 +222,24 @@
Are you sure you want to
- delete the wordlist[s] %s?
+ delete the wordlist[s] %1$s?
+ of the language is substituted for %1$s. -->
%1$s is the only %2$s
wordlist installed. One or more games will be unopenable
without it.
+ name of the language is substituted for %1$s. -->
\u0020One game (at least)
- is using it, but there is another %s wordlist installed that can
+ is using it, but there is another %1$s wordlist installed that can
replace it.
-
- Settings for %s
+
+ Settings for %1$s
- %s settings (networked)
+ %1$s settings (networked)
- %s settings (via Bluetooth)
+ %1$s settings (via Bluetooth)
Languages (based on installed
@@ -468,13 +468,13 @@
- Wordlist (in %s)
+ "%1$s". -->
+ Wordlist (in %1$s)
- Installed wordlists (in %s)
+ will use is substituted in for "%1$s". -->
+ Installed wordlists (in %1$s)
Robot player
@@ -539,7 +539,7 @@
- %d player[s] missing
+ %1$d player[s] missing
All players are here in room
- \"%s\".
+ \"%1$s\".
@@ -674,7 +674,7 @@
able to remove this from non-debug versions of the game
because users should not have to do do this EVER. -->
Resend messages
- Resend finished; sent %d message[s].
+ Resend finished; sent %1$d message[s].
The robot made this move:\u0020
- exchanged %d tiles.
+ exchanged %1$d tiles.
- %s counts/values:\n
+ %1$s counts/values:\n
- + %d [all remaining tiles]
+ + %1$d [all remaining tiles]
- - %d [unused tiles]
+ - %1$d [unused tiles]
- New tiles: %s
+ New tiles: %1$s
- Cumulative score: %d\n
+ Cumulative score: %1$d\n
Remote player %1$s made this
move:\u0020
- - %d [time]
+ - %1$d [time]
- move (from %s across)\n
+ move (from %1$s across)\n
- move (from %s down)\n
+ move (from %1$s down)\n
- Rack at start: %s\n
+ Rack at start: %1$s\n
Exchanged %1$s for %2$s.
%1$s:%2$d
- Exchanged %d tiles
+ Number of tiles traded is substituted for %1$d-->
+ Exchanged %1$d tiles
@@ -737,9 +737,9 @@
Commit the current move?\n
-
- %s (remote)
+ %1$s (remote)
\u0020vs.\u0020
@@ -747,14 +747,14 @@
Bonus for using all tiles: 50\n
- Score for turn: %d\n
+ one turn is substituted for %1$d.-->
+ Score for turn: %1$d\n
- %d tiles left in pool.
+ %1$d tiles left in pool.
- %d tiles left in pool and all
+ %1$d tiles left in pool and all
tray[s]:\n
- Let\'s play Crosswords (Room %s)
+ Let\'s play Crosswords (Room %1$s)
- Send invitation via %s
+ Send invitation via %1$s
email
sms
Are you sure you want to exchange the
- selected tiles (%s)?
+ selected tiles (%1$s)?
- %s message history
+ substituted for %1$s. -->
+ %1$s message history
Me:\u0020
@@ -1288,9 +1288,9 @@
-->
+ language is substituted for %1$s. -->
To start a basic networked two-player
- game in %s:
+ game in %1$s:
@@ -1404,7 +1404,7 @@
Guest wordlists; Host wins.
- Downloading %s…
+ Downloading %1$s…
- Password for \"%s\":
+ Password for \"%1$s\":
- Game %d
+ Game %1$d
- Player %d
+ Player %1$d
Moves made
- Activity in game "%s"
+ Activity in game "%1$s"
- Look up %s
- Look up/study %s
+ Look up %1$s
+ Look up/study %1$s
Tap to look up
Tap to look up or study
Done
- Done with %s
+ Done with %1$s
- Look up %s at
+ Look up %1$s at
Pass
@@ -1824,7 +1824,7 @@
Pick for me
- Tile picker\n(so far: %s)
+ Tile picker\n(so far: %1$s)
Pick tiles face-up
@@ -1844,7 +1844,7 @@
This button opens the wordlist
browser on the wordlist of your choice.
- The wordlist %s contains only
+ The wordlist %1$s contains only
tile information. There are no words to browse.
@@ -1865,7 +1865,7 @@
(If relevant, please include the
- version: \"%s\"; and make/model of your phone or
+ version: \"%1$s\"; and make/model of your phone or
tablet.)
Turn Bluetooth on
@@ -1891,17 +1891,17 @@
New game via Bluetooth
- Paired device %s has invited you to
+ Paired device %1$s has invited you to
play
- Crosswords on %s wrong version for
+ Crosswords on %1$s wrong version for
Bluetooth play.
New move via Bluetooth
One or more moves has arrived
- Please select the %d device[s] you
+ Please select the %1$d device[s] you
want to include in this game. Use the Rescan button if you
don\'t see a device you expect.
@@ -1941,13 +1941,13 @@
New game via SMS
- %s has invited you to play
+ %1$s has invited you to play
New move via SMS
Import contact
- Please check the %d phone
+ Please check the %1$d phone
number[s] you want to invite to your new game, then tap \"Invite
checked\".
@@ -1971,7 +1971,7 @@
Connected number[s]:
- Game in play with %s
+ Game in play with %1$s
Are you certain this number is on an
account with unlimited texting? Click cancel if you are not.
@@ -2068,9 +2068,9 @@
New wordlist available
- Tap to update %s
+ Tap to update %1$s
- New version of %s
+ New version of %1$s
Tap to download and install
@@ -2124,14 +2124,14 @@
New games
Are you sure you want to delete
- the %d selected group[s]?
- \n\n(%d game[s] will
+ the %1$d selected group[s]?
+ \n\n(%1$d game[s] will
also be deleted.)
Change the name of this group to:
Name group
- The group for new games, %s,
+ The group for new games, %1$s,
cannot be deleted.
Moving is impossible until there
@@ -2163,8 +2163,8 @@
selection instead of exiting. Hit it again to exit the
app.
- Games: %d
- Groups: %d
+ Games: %1$d
+ Groups: %1$d
Thumbnail size
Disabled
@@ -2200,7 +2200,7 @@
Rate Crosswords
Google Play app not found
- Add %s to studylist
+ Add %1$s to studylist
Enable studylists
Offer to add to and display lists
of words to remember
@@ -2209,15 +2209,15 @@
Copy to clipboard
Delete
Are you sure you want to
- delete the %d selected word[s]?\n\n(This action cannot be undone.)
- %d word[s] copied
- %s added to list
- Studylist for %s
+ delete the %1$d selected word[s]?\n\n(This action cannot be undone.)
+ %1$d word[s] copied
+ %1$s added to list
+ Studylist for %1$s
Your words for:
You have not yet saved any words
- into a studylist for %s.
+ into a studylist for %1$s.
You have not yet saved any words
into a studylist.
@@ -2229,6 +2229,6 @@
Select all
Unselect all
- Selected: %d
+ Selected: %1$d
diff --git a/xwords4/android/scripts/gen_loc_ids.py b/xwords4/android/scripts/gen_loc_ids.py
index 2345db0d9..af5b5e2de 100755
--- a/xwords4/android/scripts/gen_loc_ids.py
+++ b/xwords4/android/scripts/gen_loc_ids.py
@@ -11,6 +11,17 @@ from lxml import etree
pairs = {}
+# Enforce some conventions: No %d/%s in strings, and anything that
+# does have formatting has a name ending in _fmt.
+HAS_FMT = re.compile('.*%\d\$[ds].*', re.DOTALL)
+OLD_PCT = re.compile('.*%[ds].*', re.DOTALL)
+ENDS_WITH_FMT = re.compile('.*_fmt$')
+for path in glob.iglob( "res/values*/strings.xml" ):
+ for action, elem in etree.iterparse(path):
+ if "end" == action and elem.text:
+ if OLD_PCT.match( elem.text ):
+ print "%d and %s no longer allowed: in", path, "text:", elem.text
+ sys.exit(1)
# Get all string IDs that are used in menus -- the ones we care about
TITLE = re.compile('.*android:title="loc:(.*)".*')