The Tingdu wordset format

Version 1 · for your own words, phrases, pictures and sounds

A Tingdu wordset is one JSON file. Everything an item needs travels inside it: the text, its pronunciation, its translation and, if you like, a picture and a sound, written as data URLs (the binary file encoded as text). One file is all you share, back up or import: open Tingdu, tap Import, and choose the file or paste its text.

Prefer a spreadsheet? Tingdu also imports a simple CSV table. Want to start from something that works? Download the example wordset (nine words for a TV episode, with pictures).

The file at a glance

{
  "format": "tingdu-wordset",
  "version": 1,
  "wordset": {
    "id": "my-first-set",
    "name": "My first set",
    "language": "zh-CN",
    "items": [
      { "id": "w1", "text": "你好", "phonetic": "nǐ hǎo", "translation": "hello" }
    ]
  }
}

Wordset fields

Field Required Rules
id yes 1 to 64 characters, only letters, digits, ., _ and - (the pattern ^[A-Za-z0-9._-]{1,64}$). It identifies the wordset: importing a file with an id you already have asks whether to replace it (its records stay) or keep both.
name yes Not empty, at most 80 characters. Shown in the library.
language yes The language of text as a language tag: a lowercase code of 2 or 3 letters, optionally followed by - parts of 2 to 8 letters or digits, at most 35 characters. Examples: zh-CN (Mandarin, simplified), zh-TW, ja-JP, en-GB, fr. It chooses the text-to-speech voice, so be precise.
collection no At most 80 characters. Wordsets with the same collection are grouped together in the library, for example one collection per TV series.
items yes An array of 1 to 2000 items.

Item fields

Field Required Rules
id yes Not empty, at most 64 characters, unique within the wordset. Your records follow it, so keep it when you fix a typo in the text.
text yes The word or phrase being learnt, for example 咖啡. Not empty, at most 200 characters.
phonetic no How to say it, for example pinyin with tone marks kāfēi. At most 200 characters. Shown under the text when “Show phonetic” is on in Settings.
translation yes The meaning in your language, for example coffee. At most 200 characters.
picture no A data URL of an image: image/svg+xml, image/png, image/jpeg or image/webp; the whole data URL at most 5 MB (5,242,880 characters). See Pictures.
sound no A data URL of a recording with any audio/… type; the whole data URL at most 10 MB (10,485,760 characters). See Sounds.
extra no An object for your own notes. Tingdu checks that it is an object and does not use or keep it.

A whole file may be up to 200 MB; above 20 MB Tingdu asks before importing, because it can be slow. Fields Tingdu does not know are ignored.

Pictures and sounds inside the JSON: data URLs

A data URL is a whole file written as text: data:, the file type, and the content. For a binary file (PNG, JPEG, WebP, MP3…) the content is base64:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA…
data:audio/mpeg;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4…

Make one from a file with a single command and paste the result into the JSON:

Windows (PowerShell)

"data:image/png;base64," + [Convert]::ToBase64String([IO.File]::ReadAllBytes("$PWD\cat.png")) | Set-Clipboard

Linux

echo "data:audio/mpeg;base64,$(base64 -w0 cat.mp3)" > cat.txt

macOS

echo "data:audio/mpeg;base64,$(base64 -i cat.mp3)" | pbcopy

Or skip the commands: add pictures and recordings in Tingdu’s own editor and use Export. The exported file is this format, with every picture and sound already inside.

Pictures

"picture": "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><circle cx='32' cy='36' r='20' fill='%23e4573d' stroke='currentColor' stroke-width='3'/><path d='M32 16c0-6 4-8 8-8' fill='none' stroke='currentColor' stroke-width='3' stroke-linecap='round'/></svg>"

The same idea in base64 (a water drop):

"picture": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+PHBhdGggZD0iTTMyIDhDMjIgMjQgMTYgMzIgMTYgNDBhMTYgMTYgMCAwIDAgMzIgMGMwLTgtNi0xNi0xNi0zMnoiIGZpbGw9IiMzYTg2ZDQiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjMiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4="

The picture games need enough pictures to choose from: at least 4 items with different pictures for Choose and Pairs, 6 for Rush.

Sounds (optional)

A complete example

Two pictured items and one without a picture. Copy it, paste it into the box on Tingdu’s Import page, tap Check pasted text, and it imports as it is. The example file is a longer one.

{
  "format": "tingdu-wordset",
  "version": 1,
  "wordset": {
    "id": "fruit-and-water",
    "name": "Fruit and water",
    "language": "zh-CN",
    "collection": "My first sets",
    "items": [
      {
        "id": "pingguo",
        "text": "苹果",
        "phonetic": "píngguǒ",
        "translation": "apple",
        "picture": "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><circle cx='32' cy='36' r='20' fill='%23e4573d' stroke='currentColor' stroke-width='3'/><path d='M32 16c0-6 4-8 8-8' fill='none' stroke='currentColor' stroke-width='3' stroke-linecap='round'/></svg>"
      },
      {
        "id": "shui",
        "text": "水",
        "phonetic": "shuǐ",
        "translation": "water",
        "picture": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+PHBhdGggZD0iTTMyIDhDMjIgMjQgMTYgMzIgMTYgNDBhMTYgMTYgMCAwIDAgMzIgMGMwLTgtNi0xNi0xNi0zMnoiIGZpbGw9IiMzYTg2ZDQiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjMiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4="
      },
      {
        "id": "ni-hao",
        "text": "你好",
        "phonetic": "nǐ hǎo",
        "translation": "hello",
        "extra": { "note": "the first word of every series" }
      }
    ]
  }
}

An item with its own recording looks the same, with one more field (shortened here):

{ "id": "xie-xie", "text": "谢谢", "phonetic": "xièxie", "translation": "thank you",
  "sound": "data:audio/mpeg;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4…" }

The CSV alternative

A table saved as CSV from a spreadsheet works too, one item per row. The first row names the columns:

text,phonetic,translation
咖啡,kāfēi,coffee
手机,shǒujī,mobile phone
"没关系",méi guānxi,"it's fine, no problem"

When the import says “The file is not valid”

Tingdu checks the whole file before it saves anything and lists the first ten problems, each with where it is: wordset.items[3].text is the text of the fourth item (counting from 0).

Message What it means
(file): not valid JSON (…) The text is not JSON: a missing comma or bracket, a comma after the last item, comments, curly “smart” quotes, or a sentence of an AI chat before or after the JSON. Paste only the part from { to the last }; a surrounding ```json code block is removed for you.
format: must be "tingdu-wordset" The format field is missing or misspelt.
version: must be 1 Missing, or written as a string "1".
(file): must hold either "wordset" or "wordsets" Neither or both of them are there.
wordset.id: may contain only letters, digits, ".", "_" and "-" Spaces, Chinese characters or other symbols in the wordset id.
wordset.language: must be a language tag such as zh-CN A name such as "Chinese", or an uppercase code "ZH".
….text: must be a non-empty string An item without text, or with an empty one.
….translation: is required An item without a translation.
….id: duplicates the id "w3" Two items share an id; give each its own.
….picture: must be a data URL of an SVG, PNG, JPEG or WebP image A link instead of a data URL, a missing data:image/… start, or another type such as GIF.
….sound: must be a data URL of an audio file A link, or a type that does not start with audio/.
…: must be at most 200 characters A text, phonetic or translation that is too long (80 for names, 64 for ids).
wordset.items: must hold at least one item An empty list.
header: needs a "translation" column A CSV whose first row lacks a required column name.

Making a list for a TV series with an AI chat? The blog post Learn Chinese with the TV series you love has a ready-to-copy prompt that asks for exactly this format.