Localization variable formatting options

There is a mixed approach when it comes to variable formatting. Android and iOS supports some similar formatting features based on the IEEE printf standard but they have custom features. A common approach for web localization is that only preformatted strings are placed in the localized text and the localization library does not format the received values. In same tools - like i18n - you can apply a custom formatting function but there are no standard, built in formatters by default.
This is why Respresso supports a printf based formatting that unifies Android and iOS features but lets you override platform-specific variable placeholders to support any localization library. If you don't want to use Respresso's variable formatting features, you can simply use the default %s format that means a simple preformatted string variable.

To clarify: Respresso doesn't format your variables but lets you specify formatting instructions that are converted to platform specific variants (when possible).

Change localization variable formatting

Respresso lets you register variables for each localization (key). You can specify variable formatting for each registered variable.

Respresso provides 2 types of variable formatting:

  • Printf based formatting that is required. (Defaults to %s that means you will provide a preformatted string value.)
  • Custom variable placeholders where you get full control over variable formatting.

Follow these steps to change a variable's formatting:

  1. Open the detailed editor panel of the localization by clicking on its key.
  2. Click the edit button next to the variable's name to open the variable editor dialog.
  3. Change the format to the desired formatting.
  4. Click the OK button to apply your change.
Steps to change a localization variable's formatting

Respresso's printf based formatting

As mentioned above, Respresso tries to unify the variable formatting of Android and iOS. To do so, we implemented a variable formatting tool that supports almost all the features of the Android Formatter, iOS format specifiers, and the IEEE printf standard.

The syntax is the following:
%[$<argument index>][<flag>*][<width>][.<precision>][<length modifier>]<conversion>[<conversion modifier>]

Some examples:

  • %s: Preformatted string from the next argument position. (conversion)
  • %2$d: Whole number (integer) from the 2nd argument. (argument index)
  • %5.3f: Real number (float/double) with minimum 3 characters long that translates to at least 2 decimal places before the decimal separator and 3 decimal places after it. (width and precision)
  • %,d or %'d: A whole number with thousands separator. (Android , and iOS ' flag is also supported that are equivalent)
  • %Lf: Real number (float/double). (L length modifier means that iOS should treat the received value as a long double)
  • %tH: Date time formatted as 24h hours (0-23) with leading zero if necessary. (conversion modifier from Android)

Although Respresso understands these, it doesn't mean that the target format/platform supports all features.
When you specify a format that is not supported in the target format, it will translate it to the preformatted string variant. E.g. %tH will remain %tH in Android strings xml while you will get %@ in iOS strings.
In the few cases when there is an alternative form for the same thing, Respresso will handle it. E.g. %'d will remain %'d in iOS strings while it will be transformed to %,d in Android strings xml.

Argument index

There is no change or extension to the IEEE printf standard.

Using the argument index, you can specify which argument/parameter should be formatted and placed to that location. This allows you to use the same argument/parameter multiple times. E.g. a string like Time: %1$tH:%1$tM on Android would print the something like this Time: 14:24 from a single argument.

The argument index name may be a bit confusing as you will never use something like %0$s. This is because it indexes the arguments of the printf("Welcom %1$s!", "John") function. As a result the first real variable is indexed with 1 instead of 0.
To fix this, Respresso gives you the {{index}} (arg. index - 1) and the {{position}} (arg. index) placeholders when using custom variable placeholders.

Flags

There is a single extension from Android compared to the IEEE printf standard.

You can use multiple flags within a single format but keep in mind that not all flags are supported for every conversion. Respresso will use all the specified flags converted to the target format and won't check if they are actually valid. It can cause runtime errors if you define an invalid format.

These are the flags Respresso understands:

  • -: Left justified (Pad from right if width is specified)
  • #: Alternate form
  • +: Force the + sign for positive numbers
  • (space): Use a single leading space for positive numbers
  • 0: Pad numbers with 0 instead of space
  • ' or ,: Use local specific thousand group separators
  • (: Parenthesize negative numbers

Width

There is no change or extension to the IEEE printf standard.

This is positive (non-zero) number that specifies the minimum length of the formatted string. It is padded when the result is shorter. If not specified otherwise, it is left padded with spaces.

Please note that 0 is not valid width parameter as it will mean the 0 flag.

Precision

There is no change or extension to the IEEE printf standard.

A . followed with a non-negative whole number that specifies the decimal places after the decimal separator.

Length modifier

There is a single exclusion due to Android compared to the IEEE printf standard.

This modifier specifies how the received parameter should be treated on native languages, like Objective-C. This parameter is not present in Android strings xml.

These are the length modifiers Respresso understands:

  • hh: Char
  • h: Short int
  • l: Long int
  • ll: Long long int
  • j: Int max
  • z: Size (size_t)
  • L: Long double

Length modifiers can use signed or unsigned representation depending on the conversion that is applied to. To learn more, you can visit the C++ reference page of printf.

Please note that the IEEE printf standard t length modifier is excluded as it is colliding with the Android's Date/Time conversion which is much more useful.

Conversion

There are a few extensions compared to the IEEE standard.

The applied conversion defines the formatting function, this is why this is the only required part of the format.

These are the standard conversions Respresso understands:

  • s, S or @: String value (preformatted string or an object converted to string)
  • d or i: Whole number in decimal representation.
  • f or F: Real number in decimal representation.
  • c or C: Single character.
  • o: Whole number in octal representation.
  • x or X: Whole number in hexadecimal representation.
  • e or E: Real number in decimal representation in scientific notation.
  • g or G: Real number in compact decimal representation.
  • a or A: Real number in hexadecimal representation.
  • p: Pointer address. (Android doesn't support it)
  • %: Percent literal. (Not argument consuming variable. Used to escape the % character - %% will translate to %.)

Do NOT use the percent literal (%%) in variable formatting, it is only supported to properly import localizations.)

These are the non-standard conversions Respresso understands:

  • b or B: Boolean value. (Android only)
  • h or H: String in hexadecimal representation. (Android only)
  • t or T: Date/Time conversion that is followed by a conversion modifier. (Android only)

Conversion modifier (Android only)

This is not part of the IEEE printf standard. It is an extension from Android's Date/Time conversion. Usable only with conjunction with the t or T conversion.

These are the conversion modifiers Respresso understands:

  • H: Hour of day (24h - 2 digits)
  • I: Hour of day (12h - 2 digits)
  • k: Hour of day (24h)
  • l: Hour of day (12h)
  • M: Minute
  • S: Second
  • M: Millisecond (3 digits)
  • N: Nanosecond (9 digits)
  • p: AM/PM indicator
  • z: Numeric time-zone offset
  • Z: Time-zone
  • s: Epoch seconds
  • Q: Epoch milliseconds
  • B: Full month name
  • b: Short month name
  • h: Short month name alias
  • A: Full day of week
  • a: Short day of week
  • C: Century (2 digits)
  • Y: Year (4 digits)
  • y: Year (2 digits)
  • j: Day of year (3 digits)
  • m: Month of year (2 digits)
  • d: Day of month (2 digits)
  • e: Day of month
  • R: Time in hours and minutes (24h)
  • T: Time in hours minutes and seconds (24h)
  • r: Time in hours minutes and seconds (12h)
  • D: Formatted date (Equivalent with %tm/%td/%ty)
  • F: ISO Date
  • c: Compact formatted date time (Equivalent with %ta %tb %td %tT %tZ %tY)