Localizing Batch Import Values
Liferay DXP 2026.Q3+
Localized field values appear in _i18n maps, such as value_i18n and name_i18n. Each entry in the map pairs a language ID with a translated string.
Instead of listing every language ID by hand, you can add the [$FOR_EACH_LANGUAGE_ID$] token and name a language key. A language key is an entry in a Language.properties file that holds a term’s translations. Use the token when the translations you want already exist in a language key.
Adding the Token
Add a single entry whose key is [$FOR_EACH_LANGUAGE_ID$] and whose value is the language key:
"value_i18n": {
"[$FOR_EACH_LANGUAGE_ID$]": "welcome-to-liferay"
}
The token is the entry’s key rather than its value, so the file is still valid JSON.
The import replaces that entry with one entry per enabled language. For example, the import produces these entries on an instance with English, Spanish, and Brazilian Portuguese enabled:
"value_i18n": {
"en_US": "Welcome to Liferay",
"es_ES": "Bienvenido a Liferay",
"pt_BR": "Bem vindo ao Liferay"
}
The token resolves in any data imported through the Batch Engine, including data from a batch client extension. In a Site Initializer, it also resolves in page definitions, display page templates, and object definition files.
Everywhere else in a Site Initializer, including roles.json and notification templates, the token isn’t expanded and the field stays untranslated. Some asset types log nothing when this happens. Check the imported data rather than the log.
To add your own language keys rather than reuse the ones Liferay ships, see Language Client Extensions.
Languages in the Expanded Map
The import writes one entry for each language enabled in the Liferay instance, not for every language Liferay ships. A language with no translation of its own falls back through Liferay’s language chain to the English value in Language.properties. Every enabled language therefore gets an entry.
Language entries you write by hand take precedence, and the import fills in only the languages missing from the map. In this example, en_US keeps the value Custom, and the remaining languages take their translations from the welcome-to-liferay key:
"value_i18n": {
"en_US": "Custom",
"[$FOR_EACH_LANGUAGE_ID$]": "welcome-to-liferay"
}
The import removes the [$FOR_EACH_LANGUAGE_ID$] entry during expansion, so the raw token never appears as a translation.
Expansion is deterministic, so importing the same file twice produces the same result. Data you export after an import contains resolved translations rather than the token, and a later import of that data passes the values through unchanged.
Unresolved Language Keys
When no language has a translation for the key, the import doesn’t fail. Liferay logs a warning from com.liferay.batch.engine.internal.language.LanguageKeyResolverImpl and removes the token entry, so only the entries you wrote by hand remain:
Unable to resolve language key "[key]"
A map with no hand-written entries is empty.
The token’s value must be a single language key string. When the value is an object or an array, Liferay leaves the entry in place and logs nothing.
Enabling Language Key Resolution
The Language Key Resolution Enabled setting turns resolution on or off for a Liferay instance. To change it, go to Global Menu → Instance Settings → Batch Engine and open the Batch Engine Task Configuration entry.
The setting is enabled by default. When it’s disabled, the import skips resolution and stores the literal [$FOR_EACH_LANGUAGE_ID$] key in the map as written.