Ditto
Search
K

Text Formats

Overview

To support diverse workflows that integrate Ditto into development, Ditto API endpoints that return text can send responses in a number of different formats.
If you're unsure whether or not a given endpoint supports format specification, please see the endpoint reference.

Formats

Flat JSON (?format=flat)
Content-Type: application/json
{
"[TEXT ID]": "[TEXT OF TEXT ITEM]",
"[TEXT ID]": "[TEXT OF TEXT ITEM]",
// Text items with plural values will have those plural
// values included in the output as individual key/value pairs
"[TEXT ID]_[PLURAL FORM]": "[TEXT OF PLURAL FORM]",
...
}
If this format is exported for a specific variant, two metadata keys for the variant will also be included:
{
"__variant-name": "French",
"__variant-description": "Copy localized for native French speakers",
...
}
Structured JSON (?format=structured)
Content-Type: application/json
{
"[TEXT ID]": {
"text": "[TEXT OF TEXT ITEM]",
"status": "[STATUS OF TEXT ITEM]", // optional
"notes": "[NOTES OF TEXT ITEM]", // optional
"tags": [ ... ], // optional: array of strings
"variables": {
"[VARIABLE NAME]": {
... // variable properties: example, fallback, etc
}
},
"plurals": { // optional: only if plurals are enabled for text
"zero": "[TEXT FOR ZERO FORM]", // optional: depends on plural form being configured
"few": "[TEXT FOR FEW FORM]", // optional: depends on plural form being configured
"many": "[TEXT FOR MANY FORM]", // optional: depends on plural form being configured
"other": "[TEXT FOR OTHER FORM]", // optional: depends on plural form being configured
},
"variants": { // optional: only present if text has variant values
"[VARIANT ID]": {
"text": "[TEXT OF VARIANT]",
"variables": { ... } // see previous `variables` property,
"plurals": { ... } // see previous `plurals` property
},
// This field is only included if `?includeRichText=true`
// is passed as a query parameter. Learn more:
// https://www.dittowords.com/docs/rich-text
"rich_text": "[HTML CONTENT OF TEXT ITEM]"
},
"[TEXT ID]": { ... },
...
}
If this format is exported for a specific variant, two metadata keys for the variant will also be included:
{
"__variant-name": "French",
"__variant-description": "Copy localized for native French speakers",
...
}
Nested JSON (?format=nested)
Content-Type: application/json
This format is only available for the component library.
1
{
2
"onboarding": {
3
"header": {
4
"title": "Welcome!",
5
"subtitle": "We're happy to have you here"
6
},
7
"body": {
8
"CTA": "Let's get started"
9
}
10
},
11
"authentication": {
12
"new-user-cta": "Create an account",
13
"existing-user-cta": "Sign in"
14
},
15
"toast": "Thanks for signing up!"
16
}
Component IDs are split according to the "forward slash" replacement character in a workspace's component ID configuration; each part of the ID split using this delimiter translates to a layer of depth in the generated nested output.
Read more about configuring component developer IDs here.
Assuming a "forward slash" replacement character of ., the JSON above would be generated from the following component IDs:
onboarding.header.title
onboarding.header.subtitle
onboarding.body.CTA
authentication.new-user-cta
authentication.existing-user-cta
toast
The nested export format is reverse-compatible with the nested import format: given the same workspace configuration, importing the nested JSON shown in this example will result in components being created with the component IDs listed above.
If this format is exported for a specific variant, two metadata keys for the variant will also be included:
{
"__variant-name": "French",
"__variant-description": "Copy localized for native French speakers",
...
}
ICU JSON (?format=icu)
Content-Type: application/json
{
"onboarding.header.title": "Welcome, {username}!",
"onboarding.header.subtitle": "We''re happy to have you here",
"authentication.message": "You are {role, select, admin {an administrator} viewer {a viewer} other {currently logged in}}.",
"cart.count": "{count, plural, =0 {No items in the cart} =1 {One item in the cart} other {{count} items in the cart}}"
}
  • A Map or List variable in Ditto translates to an ICU SelectFormat argument, with the variable's first value used as the other key
  • Single quotes (') will be escaped with another single quote i.e "You're logged in" -> "You''re logged in"
  • Pluralization in Ditto translates to an ICU PluralFormat argument:
    • The PluralFormat, if present, will always encompass the rest of the string, within which variables can be nested.
    • The name of the argument will always be count i.e. {count, plural, ...}
If this format is exported for a specific variant, two metadata keys for the variant will also be included:
{
"__variant-name": "French",
"__variant-description": "Copy localized for native French speakers",
...
}
Android XML (?format=android)
Content-Type: text/xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="welcome_text" ditto_api_id="welcome-text">Welcome to the app!</string>
<string name="logout" ditto_api_id="logout">Logout</string>
</resources>
  • Text items in Ditto are mapped to <string> tags and given name values that correspond to a given text item's API ID with - characters replaced with _. An additional ditto_api_id field is also added with the original api id.
  • Variables in Ditto are mapped to <xliff:g> tags and given id and example values that correspond to a given variable's name and example values, respectively.
  • A text item with plurals will have a <plurals> tag generated for it, along with an <item> for each plural form that is configured in Ditto (note: <item id="other"> will always be generated). Plural items also support variables via <xliff:g> tags.
Although an example is shown above, please see the Android strings documentation and the Android localization documentation for a complete reference.
If this format is exported for a specific variant, two comments containing variant metadata will also be included:
<?xml version="1.0" encoding="utf-8"?>
<!-- Variant Name: French -->
<!-- Variant Description: Copy localized for native French speakers -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="welcome_text" ditto_api_id="welcome-text">Welcome to the app!</string>
<string name="logout" ditto_api_id="logout">Logout</string>
</resources>
iOS .strings (?format=ios-strings)
Content-Type: text/plain
"welcome.title" = "Welcome, %1$@!";
/* This should only be used on the logout screen */
"logout" = "Logout";
Ditto Variables are replaced with interpolation placeholders with a string (@) format specifier -- in your client code, you'll need to ensure that all variables passed as arguments are first converted into strings.
Notes associated with text items will be included as comments above a given key-value pair.
If this format is exported for a specific variant, two comments containing variant metadata will also be included:
/* Variant Name: French */
/* Variant Description: Copy localized for native French speakers */
"welcome.title" = "Welcome, %1$@!";
...
iOS .stringsdict (?format=ios-stringsdict)
Content-Type: text/xml
<?xml version="1.0" encoding="utf-8"?>
<plist version="1.0">
<dict>
<!-- Variables: cartCount, username -->
<key>cart.header</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%1$#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%3$@, you have one item in the cart.</string>
<key>two</key>
<string>%3$@, you have a couple of items in the cart.</string>
<key>other</key>
<string>%3$@, you have %2$@ items in the cart.</string>
</dict>
</dict>
</dict>
</plist>
Text without pluralization enabled in Ditto is excluded from output; for integrating strings that are not pluralized, you should use .stringsdict in conjunction with iOS .strings.
The order in which variables are provided as arguments in Swift is relevant to the output. The following code could be used with the example output above:
let localizedString = String.localizedStringWithFormat(
NSLocalizedString(
"cart",
comment: "A description of the user's cart"
),
// The first argument should always be an integer to determine which plural
// form to use
pluralcount,
// Subsequent arguments should be provided in alphabetical order according
// to the names of the Ditto Variables used in a given text item
String(pluralcount),
username,
)
A comment structured like <!-- Variables: variable_one, variable_two, ... --> is included above each key in the .stringsdict file to indicate the order in which variables should be passed (this will always be alphabetical).
All Ditto Variables are replaced with interpolation placeholders with a string (@) format specifier -- in your client code, you'll need to ensure that all variables passed as arguments are first converted into strings.
If this format is exported for a specific variant, two comments containing variant metadata will also be included:
<?xml version="1.0" encoding="utf-8"?>
<!-- Variant Name: French -->
<!-- Variant Description: Copy localized for native French speakers -->
<plist version="1.0">
...
</plist>

Deprecated Formats

Deprecated formats are not recommended for integration into development and are unavailable in the latest API version.
Full JSON
Content-Type: text/json
{
{
"project_id": "[ID OF PROJECT",
"exported_at": "[UTC TIME OF EXPORT]",
"frames": {
"[FRAME ID]": {
"frame_name": "[NAME OF FRAME]",
"blocks": {
{
"[BLOCK ID]": {
"[TEXT ID]": {
"text": "[TEXT OF TEXT ITEM]",
"status": "[STATUS OF TEXT ITEM]", // optional
"notes": "[NOTES OF TEXT ITEM]", // optional
"variables": {
"[VARIABLE NAME]": {
... // variable properties: example, fallback, etc
}
},
"plurals": { // optional: only if plurals are enabled for text
"zero": "[TEXT FOR ZERO FORM]", // optional: depends on plural form being configured
"few": "[TEXT FOR FEW FORM]", // optional: depends on plural form being configured
"many": "[TEXT FOR MANY FORM]", // optional: depends on plural form being configured
"other": "[TEXT FOR OTHER FORM]", // optional: depends on plural form being configured
},
"tags": [ ... ], // optional: array of strings
"variants": { // optional: only present if text has variant values
"[VARIANT ID]": {
"text": "[TEXT OF VARIANT]",
"variables": { ... } // see previous `variables` property,
"plurals": { ... } // see previous `plurals` property
}
}
},
"[TEXT ID]": { ... }
}
},
"[BLOCK ID]": { ... }
},
"otherText": [ // text not in blocks
"[TEXT ID]": {
"text": "[TEXT OF TEXT ITEM]",
"status": "[STATUS OF TEXT ITEM]", // optional
"notes": "[NOTES OF TEXT ITEM]", // optional
"tags": [ ... ], // see previous `tags` property
"variants": { ... } // see previous `variants` property
},
"[TEXT ID]": { ... }
]
},
"[FRAME ID]": { ... },
...
}
}
}