← Help

The language config

The Language config page is your personal copy of the JSON file the app is built around. It controls which languages appear in the options menu, how the teacher behaves in each, and your own flash-card decks. The Meta Quest downloads it when the app launches (restart the app to apply changes). Every save is validated first — invalid edits are rejected with a message pointing at the problem, nothing broken ever reaches the Meta Quest, and Reset to default always restores the app's built-in config.

The file has three top-level sections:

{
  "Prompts":    { ... the prompts, written once and shared by every language ... },
  "languages":  [ ... one entry per language in the picker ... ],
  "flashDecks": [ ... optional hand-made decks ... ]
}

Prompts

The prompts live here once, not per language. Anything that genuinely differs between languages is a placeholder the app fills in — so one well-written teacher prompt serves all of them, and adding a language does not mean rewriting it.

FieldWhat it does
teacherDesc requiredThe teacher's system prompt — her personality, how much target language vs. English she uses, and any house rules. She answers as JSON with an emotion and her line; keep that part intact, and keep it strict JSON with double quotes.
suggestionDesc / suggestionDesc2Prompts for the two reply suggestions offered after each teacher line (typically one safe, one adventurous).
analysisDesc / analysisDesc2Prompts for the analysis panel — how sentences get broken down and explained.
quizSystemPrompt requiredGenerates multiple-choice quiz questions. Keep the format rules intact — the app parses the output.
wordOrderQuizPromptGenerates word-order questions, the other test type on the quiz's start page. Leave it out and that choice falls back to multiple choice.
quizExplainPrompt requiredPrompt for the explanation shown when you miss a question.
flashCardsPrompt requiredPrompt that generates Auto and Standard flash decks.

Languages

Each entry in languages defines one tile in the language picker. Note there are no prompts here — only the things that really are per-language:

FieldWhat it does
indexIts position in the array (0, 1, 2, …). Must match — decks refer to languages by this number.
languageCodeTwo-letter ISO code ("es", "zh", "ko"…). Tells speech synthesis and recognition which language to expect.
languageNameThe name shown in the dropdown.
elevenLabsIDThe ElevenLabs voice id for the teacher (8–64 letters/digits — copy it from your ElevenLabs voice library).
fontIndexWhich of the app's bundled fonts renders this language (0–31). Needed for scripts like Chinese, Korean, or Devanagari. For a language you add yourself, use -1 (or any number outside the bundled range): the app then uses its universal font, which renders Latin, Cyrillic, Greek, Chinese, Japanese, Korean, and Devanagari scripts on demand. Right-to-left scripts (Arabic, Hebrew) are not supported yet.
aiOptionWhich chat provider powers this language: chatgpt, deepseek, claude, grok, gemini, or mistral. You need that provider's key saved on the API keys page.
transliterationHow this language writes pronunciation — "pinyin", "romaji", "romanization", or for a Latin-alphabet language something like "a simple English-style phonetic respelling like \"may-ZOHN\" — never IPA". This is what {TRANSLITERATION} becomes.
quizCorrect / quizWrongThe short phrases shown for right and wrong answers, in this language.
levelsThe Difficulty dropdown for this language, e.g. ["N5", "N4", "N3"]. At least one required.

Inside any prompt you can use placeholders that the app fills in at runtime — this is what lets one shared prompt serve every language:

{LANGUAGE}The language being taught. Use this rather than naming a language — a prompt that says "You are a Korean teacher" stays Korean whichever tile you pick.
{LEVEL}The selected difficulty, from that language's levels.
{TOPIC}The current conversation topic.
{TRANSLITERATION}That language's transliteration — pinyin, romaji, a phonetic respelling. Use it anywhere you would otherwise write "pinyin".
{WORDS}The words on the active flash deck, so tests cover what you are studying. Quiz and flash-card prompts.
{COUNT}How many questions the test asked for. Quiz prompts — the app steps through exactly this many.
{EXPLANATION_LANGUAGE}The language explanations are written in. quizExplainPrompt only.

Flash decks

Entries in flashDecks appear in the Test & Cards dropdown after (None), Auto (AI), and Standard:

{
  "name": "Directions",
  "languageIndex": 1,
  "cards": [
    { "character": "北", "transliteration": "běi", "translation": "north" },
    { "character": "南", "transliteration": "nán", "translation": "south" }
  ]
}
  • name — the dropdown label.
  • languageIndex — the index of the language this deck belongs to. The deck only shows while that language is selected, and it inherits the language's font.
  • cards — 1 to 500 cards, dealt in full and in order. character (the word being studied) is required; transliteration (the pronunciation) and translation are optional and shown on the back of the card.
Optional: a hand-written test

Normally the quiz generates questions from the deck's words. Add a quiz list to a deck to use your own fixed questions instead. Each entry is one question: the question line, then the options, each wrapped in a link tag that marks it right or wrong (that tag is also what makes the option tappable in VR):

"quiz": [
  "Which direction is 'north'?\n<link=\"correct\">A. 北</link>\n<link=\"wrong\">B. 南</link>\n<link=\"wrong\">C. 西</link>\n<link=\"wrong\">D. 东</link>"
]

For put-these-in-order questions, number the links by each option's correct position instead: <link="1"> through <link="4">. Up to 100 questions per deck; the test runs through all of them.

Saving and applying

  • Validate & save checks the whole file first: JSON syntax (including misspelled field names, which are rejected rather than silently ignored), required fields, and cross-references like languageIndex. Errors list the exact entry and field.
  • Each save bumps your config's version number. The Meta Quest checks the version at launch and only re-downloads when it changed — so restart the app to pick up an edit.
  • If the Meta Quest is unlinked (or your config can't be read), the app falls back to its built-in config — you can't lock yourself out.