Skip to main content

Placeholder Formats

When working with translations, handling placeholders correctly is crucial for proper formatting and localization. Different platforms and languages use different placeholder syntaxes. Here’s an overview of common placeholder formats and how they map to the ICU Message Format, which is the native and most powerful format supported by many modern localization tools.


Overview

Our platform supports multiple placeholder syntaxes commonly used in different ecosystems, converting them to and from ICU Message Format for consistent handling:

Placeholder FormatDescriptionNotes
ICU Message FormatNative powerful format for localization like {varName}. Example usage Hello, {name}.This format is the default format used by SejHey internally.
PHP sprintfStandard PHP placeholders like %s, %dLimited specifiers supported, no advanced flags.
Java String.formatJava’s format specifiers (%s, %d, %f)Similar limitations as PHP sprintf.
C sprintfC-style placeholders, similar to PHP/JavaLimited specifiers, no advanced flags.
Apple sprintfApple-specific format placeholders (%@, %lld)Supports positional specifiers and %@.
Ruby sprintfRuby format with named and positional placeholdersSupports named placeholders like %<name>s.

Common Placeholder Specifiers Supported

SpecifierICU EquivalentDescriptionNotes
%%Literal percent sign%% in source maps to % in ICU and back when exporting.
s{0}String placeholderRepresents a simple string.
d{0, number}Integer numberConverts numeric integer specifiers to ICU number format.
f{0, number, 0.000000}Floating point with default precisionDefaults to 6 decimal places, e.g. %f0.000000. Custom precision like %.2f0.00.
e{0, number, scientific}Scientific notation number%e supported, but %E (uppercase) is not supported.
@ (Apple only){0}Object placeholderUsed in Apple format strings; can be used for generic placeholders.
Named placeholders (Ruby only){name} or {name, type}Named argument placeholdersRuby supports named placeholders such as %<name>s.

Positional Specifiers

Most formats support positional placeholders, e.g., %2$s or %1$d. These are converted into zero-based ICU placeholders, e.g.:

  • I am %2$s and have %1$d dogs.
    I am {1} and have {0, number} dogs.

Details by Format

ICU Message Format

  • Native format, no conversion needed.
  • Supports advanced features like plurals, selects, and nested messages.

PHP sprintf

  • Supported specifiers: %, s, d, f, e.
  • No support for additional flags/modifiers (like width or padding).
  • Positional specifiers like %2$s supported and converted.

Java String.format

  • Same supported specifiers and limitations as PHP sprintf.

C sprintf

  • Same supported specifiers and limitations as PHP sprintf.

Apple sprintf

  • Supports %@ (generic placeholder), %lld (64-bit number), and positional specifiers.
  • No advanced flags/modifiers supported.

Ruby sprintf

  • Supports named placeholders, e.g., %<name>s.
  • Supports positional specifiers.
  • Same limited specifier set: %, s, d, f, e.

Notes

  • Unsupported or complex flags and modifiers in placeholders are not converted and may cause issues.
  • For unsupported placeholder types, use generic placeholders like %@ (Apple) or {0} (ICU) and handle formatting in code.
  • Always test your placeholders after importing/exporting to avoid runtime formatting errors.

This mapping ensures your translations stay consistent and placeholders work correctly regardless of the source or target format.


How Variable Interpolation Works

The system uses a two-phase approach to handle variables across different file formats:

1. Extraction Phase (Import)

When you upload translation files, the system:

  • Detects format-specific variable syntax (e.g., %@ in iOS, {0} in Java, :name in PHP)
  • Normalizes all variables to an internal format: {variableName} for named variables, # for count/plural markers
  • Stores translations in this normalized format in the database

Example:

  • Input (iOS .strings): "Hello %@, you have %d items"
  • Internal storage: "Hello {string0}, you have {int0} items"

2. Export Phase (Download)

When you export translations:

  • The system reads the normalized format from the database
  • Converts variables back to the target format's syntax
  • Generates files with format-appropriate placeholders

Example:

  • Internal storage: "Hello {string0}, you have {int0} items"
  • Output (iOS .strings): "Hello %@, you have %d items"
  • Output (Java .properties): "Hello {0}, you have {1} items"
  • Output (PHP Laravel): "Hello :string0, you have :int0 items"

Benefits

  • Consistency: All translations stored in a unified format
  • Flexibility: Export to any supported format regardless of import format
  • Accuracy: Variable semantics preserved across format conversions
  • QA Support: System can validate variable counts match across languages

Disabling Variable Conversion

If you need to preserve original variable syntax (e.g., for ICU MessageFormat), you can disable variable conversion in your project settings. When disabled, variables are stored exactly as they appear in source files.