The Lexipair wordset format
Version 1 · for your own words, phrases, pictures and sounds
A Lexipair 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 Lexipair, tap Import, and choose the file or paste its text.
Prefer a spreadsheet? Lexipair 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": "lexipair-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" }
]
}
}
formatis always the string"lexipair-wordset".-
versionis the number1(not the string"1"). -
Then exactly one of:
wordset, a single wordset object, orwordsets, an array of 1 to 500 wordset objects (this is what Lexipair writes when you export a whole collection). - Other top-level fields are ignored.
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.
|
translationLanguage |
no |
The language of the translations, a language tag like
language. Without it, English (en-US).
|
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 “Pinyin in word lists” 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. Lexipair checks that it is an object, keeps it with
the word and writes it back when you export. One key has a meaning:
picturePrompt, a string that says what the picture shows, for example
"a steaming cup of black coffee on a café table". The word's edit form
shows it under the picture, ready to paste into an image AI to draw the picture
again. Two more keys show on the word card, under the meaning: note, a
short explanation of the word, and example, an example sentence with
its own play button:
{ "text": …, "phonetic": …, "translation": …, "sound": … }, only
text required. The example’s sound is
{ "dataUrl": "data:audio/…" }, a recording of the sentence; without one
the sentence is spoken by the device’s voice. See Sounds.
|
A whole file may be up to 200 MB; above 20 MB Lexipair asks before importing, because it can be slow. Fields Lexipair 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 Lexipair’s own editor and use Export. The exported file is this format, with every picture and sound already inside.
Pictures
-
Allowed types: SVG (
image/svg+xml), PNG, JPEG and WebP. A link such ashttps://…/cat.pngis not accepted: the picture must be inside the file, so the wordset works offline. - PNG, JPEG and WebP pictures larger than 256 px on their longer side are scaled down to 256 px (and stored as WebP) when you import, so big photos do not fill your device. SVG is kept as it is.
-
SVG is the best choice for simple pictograms: tiny, sharp at every size, and easy to write
by hand (or to ask an AI chat for). Use
viewBox="0 0 64 64"and draw lines withstroke="currentColor", so they turn light in the dark theme. Lexipair removes<style>,style="…",<image>,<foreignObject>, links and scripts from an SVG before showing it; use plain attributes such asfill="#e4573d". -
An SVG can go in as base64, or as readable text with
;utf8,. In the text form use single quotes inside the SVG (the JSON string uses double quotes) and write#as%23:
"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, as many as the pairs (2–4) for Pairs, and 7 for Rush.
Sounds (optional)
-
You do not need sounds. An item without a
soundin a Chinese wordset is spoken by Lexipair’s recorded voices (Serena or Dylan, chosen in Settings) when its text and pinyin match one of the built-in HSK words. Any other item is spoken by the device’s text-to-speech voice for the wordset’slanguage. Add a recording when you want a real voice, a particular accent, or a line from a scene. -
Any
audio/…type is accepted; what plays depends on the device. MP3 (audio/mpeg) plays almost everywhere;audio/ogg,audio/webmandaudio/mp4are fine in current browsers and on Android. - Keep recordings short: a word or a phrase, not a whole scene.
-
An example sentence can have its own recording too, in
extra.example.soundas{ "dataUrl": "data:audio/mpeg;base64,…" }(an object, unlike the item’ssound, which is the data URL itself). Like every picture and sound in a file, it is inside the file: a link is not accepted. Its play button plays it; without it, or if it does not play, the device’s voice reads the sentence. Export writes it back with the word.
A complete example
Two pictured items and one without a picture. Copy it, paste it into the box on Lexipair’s Import page, tap Check pasted text, and it imports as it is. The example file is a longer one.
{
"format": "lexipair-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"
-
Columns:
textandtranslationare required;phonetic,pictureandsoundare optional. Names are not case-sensitive, any order works, and other columns are ignored. -
Standard CSV quoting: a cell with a comma, a quote or a line break goes in double quotes,
and a quote inside it is doubled (
""). A data URL always contains a comma, so apictureorsoundcell must be quoted. - Spaces around a cell are trimmed; empty rows are skipped; a byte order mark is fine; line ends may be LF or CR LF.
-
The wordset’s name is the file name (or “My wordset” for pasted text) and its language is
guessed: Chinese (
zh-CN) when at least half of the texts contain Chinese characters, otherwise English (en-US). You can change both before saving. Item ids are numbered for you. - Errors name the row, counting the header as row 1:
row 4.text.
When the import says “The file is not valid”
Lexipair 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 "lexipair-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/. |
….extra.example.sound: must be { "dataUrl": … } with a
data URL of an audio file
|
The example’s recording is a link ("url"), a bare string, or not
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.