File formats

Apple

Apple .strings, .stringsdict and Xcode String Catalogs (.xcstrings) for iOS, macOS and other Apple platforms.

FormatIdentifierExtensionHolds
Apple Stringsios_strings.stringsSimple strings
Apple Stringsdictios_stringsdict.stringsdictPlural strings only
Apple String Catalogios_xcstrings.xcstringsSimple and plural strings

With .strings and .stringsdict, keep simple strings in one and plural strings in the other, as Xcode does. A String Catalog holds both.

Strings

fr.lproj/Localizable.strings
/* Home screen title */
"home.title" = "Bon retour";
"home.greeting" = "Bonjour, %@ !";
"share.hint" = "Appuyez sur \"Partager\"";
  • Each entry is "key" = "value";. Both sides must be double-quoted.
  • /* ... */ and // comments are skipped, including in the middle of the file; the same characters inside a quoted string are kept. Comments are not imported as descriptions and are not written on export.
  • Escapes decoded: \", \\, \n, \t, \r. Any other backslash sequence, including \U Unicode escapes, loses its backslash.
  • A duplicate key, a missing = or ;, or an unterminated string or comment is an import error that names the problem.
  • The file must be UTF-8. Convert UTF-16 .strings files first, for example with iconv -f UTF-16 -t UTF-8.

On export, each key is one line, \\, \" and newlines are escaped, and plural keys are left out (they belong in .stringsdict).

Stringsdict

fr.lproj/Localizable.stringsdict
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>items</key>
    <dict>
        <key>NSStringLocalizedFormatKey</key>
        <string>%#@value@</string>
        <key>value</key>
        <dict>
            <key>NSStringFormatSpecTypeKey</key>
            <string>NSStringPluralRuleType</string>
            <key>NSStringFormatValueTypeKey</key>
            <string>d</string>
            <key>one</key>
            <string>%d article</string>
            <key>other</key>
            <string>%d articles</string>
        </dict>
    </dict>
</dict>
</plist>

Each top-level <key> is a plural key. Its NSStringLocalizedFormatKey must reference a variable (%#@name@, any name), and that variable's dictionary must be NSStringPluralRuleType, with one <string> per plural category.

  • Each category must be one the locale uses. zero in an English file is an import error, because English has only one and other.
  • One variable per entry. When the format key references several variables (%#@files@ in %#@folders@), only the first variable's forms are imported, with a warning.
  • The format key is not kept. Export always writes %#@value@ as the format key, a variable named value, and NSStringFormatValueTypeKey d. Text around the variable in your format key (%#@count@ remaining) is not carried; put it in each plural form instead.
  • The standard Apple DOCTYPE is accepted. A DOCTYPE with its own declarations is rejected.

On export, simple keys are left out, so a project with no plural keys exports an empty plist. Export uses four-space indentation.

String Catalog

Xcode 15 String Catalogs are JSON files holding every language of a table:

Localizable.xcstrings
{
  "sourceLanguage": "en",
  "strings": {
    "home.title": {
      "comment": "Home screen title",
      "localizations": {
        "fr": { "stringUnit": { "state": "translated", "value": "Bon retour" } }
      }
    },
    "items": {
      "localizations": {
        "fr": {
          "variations": {
            "plural": {
              "one": { "stringUnit": { "state": "translated", "value": "%lld article" } },
              "other": { "stringUnit": { "state": "translated", "value": "%lld articles" } }
            }
          }
        }
      }
    }
  },
  "version": "1.0"
}

Import

A catalog is read for one locale at a time: the locale you import picks the matching localizations entry (pt-BR and pt_BR match). Keys with no localization for that locale are skipped, which is normal for a catalog. When you import the catalog's sourceLanguage and a key has no explicit localization, the key itself is the value, as Xcode does.

  • comment becomes the key's description.
  • variations.plural becomes a plural key. Each category must be one the locale uses.
  • Device and width variations, and substitutions, are skipped with a warning.
  • The state of a string unit is not imported: an import never marks a translation as reviewed.
  • Only catalog version 1.0 is read.

Export

An export is a catalog with a single locale: version 1.0, sourceLanguage set to the project's source locale, comment from the key's description, and every unit with state translated. It is not a replacement for a multi-language catalog in your Xcode project, which holds every language in one file. transglot init does not set up String Catalogs.

Placeholders

Import and export keep format specifiers such as %@, %d, %lld and %1$@ exactly as written. The quality checks compare the printf-style ones (%d, %1$s) between source and translation; see Placeholders for the syntaxes they recognize.

On this page