The strings parser accepts a strings
file, typically Localizable.strings
. It will parse each string in this file, including the type information for formatting parameters.
The strings file will be converted into a structured tree version, where each string is separated into components by the .
character (note: you can choose another separator if you need, using the separator
option, see Customization below). We call this the dot syntax
, each component representing a level. For example, the following strings:
"some.deep.structure"
"some.deep.something"
"hello.world"
will be parsed into the following structure (not showing the rest of the structure, such as values and types):
[
"some": [
"deep": [
"structure",
"something"
]
],
"hello": [
"world"
]
]
The default filter for this command is: [^/]\.(?i:strings|stringsdict)$
. That means it'll accept any file with the extension strings
or stringsdict
.
You can provide a custom filter using the filter
option, it accepts any valid regular expression. See the Config file documentation for more information.
Option Name | Default Value | Description |
---|---|---|
separator |
. |
Each key is separated into components using the given separator, to form a structure as described in the explanation above. |
- See here for a list of templates bundled with SwiftGen and their documentation.
- If you want to write custom templates, make sure to check the stencil context documentation to see what data is available after parsing.
SwiftGen supports definitions of plurals in .stringsdict
files. (Note: only non-nested plural variables are supported for now)
Basic Example
This example should cover the most common use case of plurals that is also supported by most of the translation management services.
<key>competition.event.number-of-matches</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@Matches@</string>
<key>Matches</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>zero</key>
<string>No matches</string>
<key>one</key>
<string>%ld match</string>
<key>other</key>
<string>%ld matches</string>
</dict>
</dict>
Mixed placeholders and variables in format key
<key>mixed.placeholders-and-variables.string-int</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ %#@has_rating@</string>
<key>has_rating</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>zero</key>
<string>has no rating</string>
<key>one</key>
<string>has one rating</string>
<key>other</key>
<string>has %d ratings</string>
</dict>
</dict>
Variables with positional arguments in format key
<key>multiple.placeholders-and-variables.int-string-string</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<!-- Your <Grocery> list contains <3 items. You should buy them> <today>. -->
<string>Your %3$@ list contains %1$#@first@ %2$@.</string>
<key>first</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>zero</key>
<string>no items. Add one</string>
<key>one</key>
<string>one item. You should buy it</string>
<key>other</key>
<string>%1$d items. You should buy them</string>
</dict>
</dict>
Multiple variables in format key
<key>multiple.variables.three-variables-in-formatkey</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@files@ (%#@bytes@, %#@minutes@)</string>
<key>files</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d file remaining</string>
<key>other</key>
<string>%d files remaining</string>
</dict>
<key>bytes</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d byte</string>
<key>other</key>
<string>%d bytes</string>
</dict>
<key>minutes</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d minute</string>
<key>other</key>
<string>%d minutes</string>
</dict>
</dict>
Nested format keys in variables
Note: in practice this should hopefully be very rare. Especially, if you're using tools like Lokalize, PhraseApp, POEditor, or similar to export your stringsdict
, it's unlikely that they'll ever generate that kind of convoluted structure for your stringsdict
.
<key>nested.formatkey-in-variable</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@geese@</string>
<key>geese</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<!-- This uses a nested key, i.e. you're referencing goose_fields variable inside the definition of geese variable -->
<!-- This is currently not properly supported as it's not parsed recursively by SwiftGen. -->
<string>A goose landed on %#@goose_fields@</string>
<key>other</key>
<string>%d geese landed on %#@geese_fields@</string>
</dict>
<key>goose_fields</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>its own field</string>
<key>other</key>
<string>its own %d fields</string>
</dict>
<key>geese_fields</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>their shared field</string>
<key>other</key>
<string>their %d fields</string>
</dict>
</dict>
Placeholders that are only used in the variables but not in the format key
This plural entry would work with plain NSLocalizedString
, as Foundation will pass the whole list of arguments to each substituted format specifier – e.g. in this case passing a String
and an Int
would work with NSLocalizedString
.
But SwiftGen only parses the NSStringLocalizedFormatKey
in a stringsdict
to find possible placeholders, because parsing all possible plural rules for placeholders as well could result in different amounts of placeholders for different amounts or different languages.
<key>unsupported-use.placeholders-in-variable-rule.string-int</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@elements@</string>
<key>elements</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>zero</key>
<string>%@ has no rating</string>
<key>one</key>
<string>%@ has one rating</string>
<key>other</key>
<string>%@ has %d ratings</string>
</dict>
</dict>