same across languages 11 en: <string name=“message”>{username} has {number} items</string> fr: <string name=“message”>{username} a {number} articles</string> ja: <string name=“message”>{username} {number} ͭͷΛ͍࣋ͬͯ·͢</string> Shibuya.apk #21
same across languages 12 en: <string name=“message”>{username} has {number} items</string> fr: <string name=“message”>{username} a {number} articles</string> ja: <string name=“message”>{username} {number} ͭͷΛ͍࣋ͬͯ·͢</string> Shibuya.apk #21
defined in values/strings.xml @RunWith(RobolectricTestRunner::Class) class PlaceholderTest { private val strings: MutableMap<Int, String> = HashMap() // default strings @Before fun setUp() { R.string::class.java.fields.forEach { val id = it.getInt(null) val value = RuntimeEnvironment.application.resources.getString(id) strings.put(id, value) } } } 20 Shibuya.apk #21
each strings @RunWith(RobolectricTestRunner::Class) class PlaceholderTest { @Test fun validatePlaceholders() { strings.forEach { entry -> // …… val placeholders = ArrayList<String>() var idx = 0 do { val open = entry.value.indexOf(“{“, idx) val close = entry.value.indexOf(“}”, idx) idx = close + 1 placeholders.add(entry.value.substring(open, idx)) } while (entry.value.indexOf(“{“, idx) != -1) } } } 23 Shibuya.apk #21