Skip to main content
Lokalise universal placeholders

Our internal placeholders are automatically converted to those required by your file format.

Nick Ustinov avatar
Written by Nick Ustinov
Updated over a week ago

We recommend storing all your platform keys (for example, web and mobile) in the same project to avoid duplicate translations. Problem is, different platforms usually require placeholders in different formats. To overcome this issue, we've introduced Lokalise universal placeholders.

The idea of this feature is really simple: all your placeholders can be stored on Lokalise in universal format so that you don't need to worry about platform differences. However, when you export your translations for a chosen platform, these universal placeholders will automatically be replaced with the platform-specific ones.

Moreover, when a translation file is uploaded to Lokalise, it's possible to automatically detect all the platform-specific platforms and convert them to the universal ones.

You might also be interested in learning about custom placeholders.

Lokalise placeholders

Universal placeholders

You can use the following universal placeholders on Lokalise to represent various data types:

  • [%s], [%1$s], [%s:name]  – string.

  • [%i], [%1$i], [%i:name]  – integer.

  • [%f], [%.2f], [%1$.2f], [%.2f:name]  – float.

The name postfix :name is only used in placeholder formats that actually support named placeholders. This postfix will be ignored for other formats.

Special placeholders

Lokalise also supports certain "special" placeholders:

  • [%] – will be automatically exported as %% for printf and iOS placeholder formats if the string contains at least one placeholder (will be exported as % otherwise).

  • [VOID] – this placeholder simply means "translation is absent" and it will be exported as an empty string. However, it will be counted as "translated" on Lokalise. This placeholder can come in handy when you do not have a proper translation yet but you want to pretend that it is actually present.

    • Please note that translations with the [VOID] value won't be saved to the translation memory.

  • [TRUE], [FALSE] – these placeholders will be exported as platform-specific boolean values.

Please note that [VOID], [TRUE], and [FALSE] placeholders should be the only text in a given translation. For example, This sentence is [FALSE] is incorrect usage of the [FALSE] placeholder and will be simply exported as a plain text.

Reference placeholder

[%key_id:key_id%]  represents key referencing. Please find more information in the corresponding article.

Universal placeholders usage

Let's suppose that we have a mobile and a web-based version of an app. We also have two English translation files for Android and for Web.

en.json (Web)

"your_order": "Here's your order, {{name}}!"

en.xml (Android)

<?xml version="1.0" encoding="UTF-8"?>
<string name="your_order">Here's your order, %s!</string>

As you can see we have similar translation keys and values but the placeholders are different and written as {{name}} (Web) and %s (Android).

Importing translation files with placeholders

Let's proceed to the Upload page and choose our JSON and XML translation files. If you upload these files without enabling any upload options, your keys will be merged into a single entry automatically as they have identical names. Problem is, one of the translation values will be lost as it's impossible to have multiple translations for the same languages in a single key. But if you lose one of the translations, it effectively means that one of the platform-specific placeholders will also be lost!

Of course, you can enable the Differentiate keys by file option so that keys are not merged into a single entry: rather, they will be assigned to different filenames and both keys will be preserved. It may sound like a good solution but that would mean you'll have two nearly identical texts that should be translated twice.

Instead, let's enable Convert to universal placeholders option so that all our placeholders are automatically converted to the universal ones:

Press Import files and return to the editor. Here's the result:

We can see that the placeholder was replaced with a universal one. Note that you can display all placeholders as blocks instead as explained in the following article.

Now we have a single translation key linked to both Web and Android platforms and to JSON and XML files. Still, we don't have to translate the same text twice and our placeholder is in place as well!

Downloading translation files and replacing with platform-specific placeholders

Once you're ready, let's proceed to the Download page. Pick an export format: for example, Android Resources (XML) or JSON:

Next, choose Placeholder format in the Advanced settings section:

Finally, click Build and download or Preview. Here's the result:

As you can see, the universal placeholder was properly replaced with {{name}}. Great job!

The same result can be achieved when downloading your files with the API or CLI.

Platform-specific placeholder formats

Suppose we have the following string with Lokalise universal placeholders: My name is [%s:name]. I have [%.2f] dollars.. Let's see how these universal placeholders will be replaced with the platform-specific ones.


Printf-style placeholders: My name is %s. I have %.2f dollars. 

%i is converted to %d. Other variants remain unchanged.


iOS-style placeholders: My name is %@. I have %.2f dollars. 

%s is converted to %@ and %i is converted to %li (%li  is used to support both 32 and 64 bit integers). Other variants remain unchanged.


ICU Message Format placeholders: My name is {name}. I have {0} dollars. 

Placeholders that have a name, will be exported as {name}, other placeholders will be exported as {n} where n is the positional index of the placeholder. When used in ICU plurals, the placeholder with positional index of 1 will be exported as #.


.NET placeholder format: My name is {0}. I have {0:0.00} dollars.


Symfony placeholder format: My name is %name%. I have %placeholder_1% dollars. 

Unnamed placeholders will be exported as exported as placeholder_n where n is the positional index of the placeholder.


Common format used in many tools and frameworks (for example, in certain i18n solutions for JavaScript-based apps): My name is {{name}}. I have {{0}} dollars.


No formatting will be applied to the placeholders as they will be exported as is.

Did this answer your question?