![]() |
Composite Format Strings and Interpolated Strings |
Most applications use composite format strings or interpolated strings to create dynamic strings. This means that you do not know the values of the string at design or compile time, but they depend on parameters at runtime. The classic example of a composite format string is C's printf function. It has a pattern that contains one or more placeholders for the parameters. The function takes the pattern and a variable number of parameters, puts the parameter values into the placeholders, and returns a single string. For example:
printf("Hello %s", name);
If the name is "John", we get "Hello John".
You can have any number of parameters as long as the number of placeholders in the pattern matches the number of parameters.
printf("Hello %s and %s", name1, name2);
If name1 is "John" and name2 is "Jill", we get "Hello John and Jill".
Composite format strings are also used with plurals and genders.
Each platform or programming language uses its own placeholder format. The following table shows the formats that Soluling handles.
| Platform | Sample composite format string |
|---|---|
| .NET | Hello {0}, welcome to {1} |
| Android | Hello %s, welcome to %s Hello %1$s, welcome to %2$s |
| Angular | Hello {{name}}, welcome to {{place}} (ngx-translate and templates) In XLIFF files, Angular stores the placeholders as <x id="INTERPOLATION"/> elements. |
| C/C++ | Hello %s, welcome to %s |
| Delphi | Hello %s, welcome to %s |
| Flutter | Hello {name}, welcome to {place} |
| Go (go-i18n) | Hello {{.Name}}, welcome to {{.Place}} |
| i18next | Hello {{name}}, welcome to {{place}} |
| iOS and macOS | Hello %@, welcome to %@ Hello %s, welcome to %s |
| Java | Hello %s, welcome to %s Hello {0}, welcome to {1} |
| Magento | Hello %s, welcome to %s Hello %name, welcome to %place |
| gettext/po and PHP | Depends on the programming language of the strings, e.g., Hello %s, welcome to %s |
| Python | Hello {name}, welcome to {place} Hello %s, welcome to %s |
| Qt | Hello %1, welcome to %2 |
| React (React Intl) | Hello {name}, welcome to {place} |
| Ruby on Rails | Hello %{name}, welcome to %{place} |
| Svelte (svelte-i18n) | Hello {name}, welcome to {place} |
| Vue (vue-i18n) | Hello {name}, welcome to {place} |
| WiX | Welcome to [ProductName] [ProductVersion] |
Because there are many formats, Soluling converts the platform-specific format into a platform-independent format when it shows the strings in the grid. Whatever the source of the composite format string is, the string looks the same in Soluling.
![]()
Translators do not need to know the format syntax of each platform. The grid shows each placeholder as a single item. The translator can move the placeholder within the string, and the editor makes sure that the translation has the same placeholders as the original. To give the translator more information, use the Extended render mode. Translate in Soluling Cloud shows the placeholders in the same way, as protected chips.
Some platforms, such as Angular, have the variable name or expression inside the placeholder. In that case, Soluling shows the variable name or expression instead of the index of the placeholder.
![]()
If such a string has two or more named placeholders, Soluling also shows the index.
![]()
This is because some platforms let you use an expression instead of a single variable in the placeholder. An expression is more likely to change than a variable name. The index makes it possible to find the right placeholder even if the expression has changed.
Note! With right-to-left languages, such as Arabic and Hebrew, the editor shows the placeholders in their original format (e.g., %s and %d).
When you start editing a translation, Soluling automatically adds the placeholders to the translation. To add a missing placeholder later, go to the edit mode (press F2 or double-click the cell), right-click, and choose Insert Placeholders | <the placeholder>.
To edit a single placeholder, press F2 to go to the edit mode and click the placeholder. The placeholder edit dialog appears and lets you edit the placeholder.
There are four ways to render composite format strings. To change the mode, use the General sheet of the project options. The possible values are:
| Value | Description | Example |
|---|---|---|
| Compact | Soluling renders composite format strings in a universal, platform-independent format. Each placeholder is shown as a yellow box with the placeholder number. | |
| Extended | As above, but in addition to the placeholder number, the placeholders show the format-specific items. | |
| Original | Soluling renders the placeholders in the original format in a yellow box. The format depends on the platform of the source file. | |
| Plain text | Soluling renders composite format strings as plain text and handles the patterns as plain strings without checking the placeholders. |
Note! The first three options turn on placeholder checking. It helps you keep the same number and type of placeholders in the translations.
Note! The Soluling project file stores the strings in the original (platform-specific) format. The above settings define only how the patterns are rendered.
When Soluling creates a new project, it uses the Original placeholder method by default. You can change the default on the Options | General sheet.
When you export a project, for example, to Excel or XLIFF, you can choose the format of the exported placeholders on the Select sheet of the Export Wizard, or with the -placehol option of the SoluMake export command (-placehol:compact, -placehol:extended, or -placehol:original). The default is the compact universal format.
| Value | Description | Example |
|---|---|---|
| Compact | Soluling exports composite format strings in a universal, platform-independent format. | Hello {0}! |
| Extended | As above, but in addition to the placeholder number, the placeholders contain the format-specific items. | Hello {0:s}! |
| Original | Soluling exports the placeholders in the original format. The format depends on the platform of the source file. | Hello %s! |
Many languages have string interpolation, where you write the expressions directly in the string (e.g., $"Hello {name}" in C# and `Hello ${name}` in JavaScript). In a compiled language, such as C#, the compiler turns an interpolated string into code, so you cannot move it into a resource file and localize it. To localize a dynamic string in a compiled language, use a composite format string from a resource, for example, string.Format(Resources.Hello, name) or IStringLocalizer in .NET. Many JavaScript libraries, such as i18next and React Intl, use their own interpolation syntax in the resource files, which Soluling handles as placeholders.
Resource strings are generally harder to translate than user interface strings, because there is no visual context. The translator has to figure out the meaning from the value of the string and its comment, if there is one. Composite format strings are even harder to translate, because parts of the complete string (the placeholders) are missing. This is why it is important to provide a comment that explains the pattern and each of its placeholders. The most convenient way is to add the comments to the source. Most platforms provide a way to add comments to resource strings, so use it. Because it is easy to forget a comment, Soluling contains a composite comment checker. It works when Soluling scans, and it writes the missing comments to the log file. The checker helps you find the resource strings that do not have comments.