Strings in resource files often use placeholders that represent dynamic variable content. Placeholders are words in a string that should not be translated, but should be included in the translation using the same syntax.
Placeholders are also known as “formatting strings”, “format specifiers” or just “specifiers”.
Example
Welcome %{username}, you have $%{balance} in your account.
Smartling's string placeholder feature allows translators to position them as needed in the translated string without having to manually enter the often complex syntax. This helps translators produce an accurate translation that will be linguistically correct at runtime and have no syntax errors when your application is being built or is executing.
Emoji's and formatting tags such as HTML and markdown are NOT considered placeholders. Smartling provides features to help translators work with formatting tags as well. Please review Standard behavior and customization for localization resource files for more information. Do not use placeholder directives to capture formatting tags.
Standard placeholders and customization
For most file formats, Smartling will automatically capture standard placeholders. The standard named placeholder captured by default depends on the file format. In most cases, you do not need to customize this behavior if you are using standard placeholders that correspond to the file format.
Smartling offers two directives to customize the placeholder behavior:
- The placeholder_format directive lets you specify that your placeholders are in a common, well-known syntax. Options are C, IOS, PYTHON, JAVA, YAML, QT, or RESX.
- The placeholder_format_custom directive lets you specify custom placeholders using a regular expression. Anything in a string matching the regular expression will be captured as a placeholder.
If your strings use the syntax that is standard for the file format, then no customization with directives is needed. If your strings use a different standard, or you are using custom placeholder syntax then you can customize the behavior with these directives.
The standard placeholders will always apply to a given file format unless you explicitly turn it off. This means that in a single file, strings can be processed with multiple placeholder formatting directives, depending on the integration and the location of the string in the file. If needed, you can usually turn off the standard behavior with a directive of placeholder_format = NONE.
Customers using the Strings API can also integrate their strings using placeholder directives. All the information here applies to Strings created via API.
Named placeholder_format directives are better and easier to use than custom placeholder_format_custom directives when they are applicable to your strings. You won't have to write a regular expression and some of them will automatically apply positional location (see below) which can be critical for proper translation.
Positional Information
For some standard placeholder formats, Smartling automatically adds positional information.
An n example of a string with positional information in its placeholders: A room at %1$s is reserved for %2$s.
Positional information is important because in these formatting syntaxes if a string has multiple placeholders, the order of placeholders could be ambiguous. If a translator needs to switch the order of placeholders for proper translation, the positional information will make sure the right variable is used at run time.
For example, if you upload the string: "A room at %s is reserved for %s." Smartling will capture, "A room at %1$s is reserved for %2$s." Smartling will always add positional data to the placeholders for the formats that support it to ensure there is no ambiguity in the translation. Even if your original string didn't have positional data, it will be added by Smartling if the string is being captured with one of those named placeholder directives.
This positional information is always supported by the underling string formatting APIs for all programming languages. Positional data is not applied to custom placeholder formats, so if you have more than one custom placeholder in a string, make sure that a translator can tell them apart. For example: "A room at #[hotel] has been reserved for #[user]." is safer than "A room at #[var] has been reserved for #[var].".
Named placeholder formats
The following table gives examples of text that will be converted to a placeholder using the standard named placeholders. The examples are not exhaustive; please refer to the corresponding linked documentation for complete description of the formatter.
Named Placeholder (placeholder_format) |
Example of text that will be converted to a placeholder |
File types using as default |
C |
%s, %1$s, %2$s %d, %1$d, %2$d %0.1d Positional automatically applied to make sure the correct placeholder is used, even if the translators re-orders them. |
|
JAVA |
%s, %1$s, %2$s %d, %1$d, %2$d %0.1d Positional automatically applied to make sure the correct placeholder is used, even if the translators re-orders them. |
|
IOS |
%s, %1$s, %2$s %@, %1$@, %2$@ %d, %1$d, %2$d Positional automatically applied to make sure the correct placeholder is used, even if the translators re-orders them. |
|
PYTHON |
Python "old" string formatting (< 2.7)
%(firstName)s %(count)d |
Gettext python-format |
QT |
%1 %2 |
QT Linguist |
RESX |
{0} {1} |
|
YAML |
%{firstName} %{count} |
Yaml |
Some files support a string_format directive. This directive can also cause placeholders to be captured. Only the files listed below can support string_format directives for placeholders.
The string_format directive can be used in other file formats for controlling HTML parsing behavior. Please check the documentation for the individual file for supported directives and uses cases.
Named string format (string_format) |
Example of text that will be converted to a placeholder |
Supported File Types |
ICU |
See ICU MessageFormat article
|
JSON |
MESSAGE_FORMAT |
{0} {1} |
Java Properties* |
*Java properties use both the placeholder_format=JAVA and the string_format=MESSAGE_FORMAT directives by default; both generate placeholders. See the Java Properties documentation for more information on how these two formats interact and how to customize the behavior of string parsing in your file.
The default behavior for JSON files in Smartling is to use a default custom placeholder directive to captures multiple placeholder syntaxes that are common in various localization frameworks. You can customize your JSON file with a named or custom placeholder if the Smartling default custom placeholder doesn't capture your strings with placeholders. See the JSON file format article for more information and examples of the text patterns that are captured by the default behavior.
Specifying Standard and Custom Formats
These two directives work in tandem. For example, if you were specifying placeholder behavior inside a custom XML file you could specify both:
<!-- smartling.placeholder_format = PYTHON -->
and
<!-- smartling.placeholder_format_custom = \[\[.+?\]\] -->
Both the standard Python style placeholders, and a custom placeholder will be recognized when found in a string. In this example the custom placeholder is delineated by having two open and closed square bracket characters with text in between them: [[firstName]].
Example Placeholder Formats
Here is a list of some common placeholders formats and custom placeholder directives to capture the text "first name" as a placeholder in the string.
Regardless if your source file follows the directive format; # smartling.[directive_name] = [value], <!-- smartling.[directive_name] = [value] -->, or // smartling.[directive_name] = [value], the directive name and value outlined in the table below still applies.
Placeholder Format |
Directive Name and Value |
{{first name}} | placeholder_format_custom=(\{\{.+?\}}) |
{first name} | placeholder_format_custom=\{([^}]+)\} |
${first name} | placeholder_format_custom=\$\{.+?\} |
$t(firstname) | placeholder_format_custom=["\\$t\\(.+?\\)"] |
%{first name} | placeholder_format_custom=%\{.+?\} |
%#first name# | placeholder_format_custom=(%\#.+?\#) |
#first name# | placeholder_format_custom=#.+?# |
[[first name]] | placeholder_format_custom=\[\[.+?\]\] |
The syntax for declaring the placeholder_format_custom directive and its regular expression value may differ for different file types or integrations methods such as the API. See the documentation of the file format for details on how to format inline directives and the API documentation for API directives. The context (inside the file or via API integration) will determine the exact syntax of the directive and its value and whether or not you need to have any special escaping in addition to the escaping that is required to generate a valid regular expression.
Placeholders are captured based on the regex match, not the capture group.
The placeholder processor interprets `\<` and `\>` as word boundaries, also known as GNU word boundaries.
If you are using a custom file format, have custom placeholder syntax, or use non-standard placeholders you can integrate to get the behavior you want. Integration can be performed either in the file or via the API. So-called “file inline” integration gives you extra customization options - for example, you may be able to change placeholder behavior throughout the file - but requires you to customize the file for Smartling. API-based integration allows you to avoid adding Smartling specific code to your file but will affect all the strings in the file.
Escaping
When defining the regular expression for a custom placeholder you may need to escape characters that are part of the expression to account for the environment (file or shell). After escaping is accounted for the expression will be evaluated as a Java regular expression (JREGEX).
So, in the above example because brackets have special meaning, they must be escaped with a backslash for the regular expression engine. However, in another context the backslash itself may need to be escaped.
Verify Placeholders
To check that your placeholders are being captured as expected, check the string in the Strings View in the Smartling Dashboard. Placeholders will be highlighted gray, as seen below.
Result - Strings View |
Result - CAT Tool |
A common mistake is to create a custom placeholder that is too aggressive (or greedy) and captures the entire string or excessive parts of the string as the placeholder. Make sure only the placeholder is highlighted and the translatable text appears as normal.
A common example is seen in JSON where the backslash character in the value of name/value pair already has special meaning for JSON, and so must be escaped to be valid a character in JSON. Also note when defining a custom placeholder inline of a JSON file we require the expressions to be listed in an array. So the above directives modified to be inside a JSON file would be:
JSON
"smartling": {
"placeholder_format" : "PYTHON",
"placeholder_format_custom" : ["\\[\\[.*?\\]\\]"]
}
Not Specifying Placeholder Formats
If your file has non-standard placeholders, and you do not integrate to define them Smartling will capture the string with the placeholder as ‘plain text’; they will typically be counted as “words” for translation, translators will have to manually enter the placeholder using the correct syntax, and the Smartling CAT tool will not be able to warn the translators about missing placeholders or incorrect syntax.