普通の辞書

辞書インポート形式 辞書形式

od-dict/1 · 自作辞書をインポートするための仕様

アプリは自分の辞書を読み込めます。1 つの辞書は od-dict/1 形式の1 つの JSON ファイルです。既存の辞書(例:Yomitan 辞書)を — 手作業または LLM で — 変換して用意すると、 アプリがそこから自前のデータベースを構築します。

この形式は jmdict-simplified のスーパーセットscriptin/jmdict-simplified)です。 jmdict-simplified の正しい語はそのままここでも有効なので、その出典ならほぼ変換不要です。

このページは読みやすくまとめた要約です。コードと突き合わせた完全な仕様はリポジトリにあります: docs/od-dict-format.md

1. ファイル全体

{
  "format": "od-dict/1",          // 必須、この文字列ちょうど
  "source": "custom",             // 必須;この辞書の id(§2)
  "metadata": {                   // 任意;表示・出自情報のみ
    "title": "My Dictionary",
    "license": "CC BY-SA 4.0",
    "url": "https://…"
  },
  "tags": { "v1": "Ichidan verb" }, // 任意;使用されません(§6)
  "words": [
    {
      "id": "1259420",            // 必須;ファイル内で一意(§3)
      "kanji": ["食べる"],         // 任意;かなのみの語では省略
      "kana":  ["たべる"],         // 少なくとも 1 つの形(kanji か kana)が必要
      "sense": [                  // 必須;1 つ以上
        {
          "partOfSpeech": ["v1"], // 任意;コードのみ、自由文は不可(§4)
          "misc": ["transitive"], // 任意;自由なラベル、そのまま表示
          "gloss": [              // 訳語
            { "lang": "en", "text": "to eat" },
            "食べる"               // 裸の文字列 = { lang: "ru", origin: "original" }
          ],
          "examples": [ ["ご飯を食べる", "ご飯を食べる"] ],  // 任意;[日本語, 訳] の組
          "references": []        // 任意;相互参照(§5)
        }
      ]
    }
  ]
}

2. トップレベル

フィールド必須意味
formatはいちょうど "od-dict/1"
sourceはい辞書全体の id 文字列。安定したスラッグ("custom""jitendex" など)。id と相互参照の名前空間になります。未知の source は組み込み辞書の後ろに並ぶだけで、拒否はされません。
metadataいいえ自由なオブジェクト(title, license, url)。表示用に保存されるだけで、ビルダーは読みません。
tagsいいえjmdict-simplified 互換の コード → ラベル マップ。使用されません(§6)。表示したいラベルは misc に直接入れてください。
wordsはい項目の配列。

セキュリティ:インポート時に source = "custom" を強制し、ファイルが "jmdict" 等を名乗れないようにする設計ですが、未実装です。検証付きインポータが入るまで source は参考値として扱ってください。

3. 語と同一性

{
  "id": "1259420",
  "homograph": "II",          // 任意;見出し+読みが衝突する際の区別子
  "label": "colloquial",      // 任意;カードに表示される項目レベルのタグ
  "isExpression": true,       // 任意;複数語の表現
  "common": true,             // 任意;高頻度の項目
  "kanji": ["食べる", "喰べる"],  // 0…n の表記
  "kana":  ["たべる"],          // 0…n の読み
  "sense": [ /* … */ ]
}

同一性は (source, id) で、UNIQUE です。

  • id はファイル内で一意である必要があります。 テーブルは UNIQUE(source, source_entry_id) に対する単純な INSERT で書かれるため、 id の重複はインポートのバッチを失敗・中断させます(黙って無視され ません)。出典の id を使うか、無ければ安定した一意の値(連番や見出し語)を作ってください。
  • kanji/kana の要素は裸の文字列(通常)か jmdict-simplified の オブジェクト { "text": "…" }読まれるのは text だけで、 残りは受理されますが破棄されます。裸の文字列を推奨。
  • 語には少なくとも 1 つの形が必要です。日本語では kana を与え、 かなのみの語では kanji を省略します。

グループ化。 アプリは(見出し + 読み)のグループごとに 1 枚のカード を、辞書をまたいで統合して表示します。自分のファイルでは項目ごとに 1 語 を出力し、すべての表記を kanji に、すべての読みを kana に、すべての意味を sense にまとめてください。出典が 1 項目を複数行に分けている場合(Yomitan は共有の sequence で行う)、先に 1 語へ統合しないと 1 項目が複数カードになります。

4. partOfSpeech — 検索を静かに壊しうる唯一のフィールド

誤った値がエラーなしに語を検索から消す唯一のフィールドです。POS は辞書形や読みでの 検索には影響しません食べるたべる も常に見つかります。POS は たった 1 か所、活用解除のゲートでのみ使われます — ユーザーが入力した活用形食べた静かな)から語を見つける処理です。

項目の POS判定効果
無し / 活用クラスでないweakそれでも見つかる(順位がやや下がる)
一致する活用クラスconfirmed見つかる(通常順位)
不一致の活用クラスrejected除外 — その活用形からは見つからない

活用クラスが分からなければ partOfSpeech ごと省いてください。 無しは安全(weak)、誤りは致命的(rejected)。当てずっぽうより省略が安全です。

  • コードのみ、自由文は不可。 読めるラベル(「verb」「honorific」)は misc に入れれば、そのまま表示されます。
  • 意味を持つのは活用クラスのみ。他のコード(nexpvtadv など)は検索では無視されます — 無害ですが無意味です。
  • Yomitan の罠:潰れた v5 をコピーしないこと。 エンジンに v5 クラスは無く、具体的なもの(v5kv5r …)が必要です。 裸の "v5" は何にも一致せず rejected となり、無タグより悪いです。 definitionTags から具体コードを取るか、辞書形の末尾かなで展開するか、省略を。

エンジンが理解する活用クラス:

v1                              一段(-ru):        食べる, 見る
v5u v5k v5g v5s v5t v5n v5b v5m v5r   五段(辞書形の末尾かなで区別)
vk                              来る(kuru)
vs vs-i vs-s                    する動詞
adj-i                           い形容詞:            高い, 良い
adj-na                          な形容詞:            静か, 綺麗

5. 語釈・言語・相互参照

"гулять"                                  // 裸の文字列 = { "lang": "ru", "origin": "original" }
{ "lang": "en", "text": "to take a walk" }
{ "lang": "ru", "text": "то же, что {0}", "origin": "original" }
  • 裸の文字列はロシア語lang: "ru")。他の言語ではオブジェクト形式で lang を指定します。
  • origin"original"(既定)か "machine"(AI 生成);表示のみ。
  • lang と検索の関係: lang: "ru" の語釈はロシア語検索 チャンネルへ、それ以外の lang はすべて英語チャンネルへ入ります。 チャンネルはユーザーが入力した文字種で選ばれます(キリル → ru、ラテン → en)。よって和英辞書の 語釈は英語検索に届くよう lang: "en" にする必要があります。単言語の日本語語釈 (lang: "ja")は en チャンネルに入り、事実上「表示専用」になります — 見出しと読みでは 見つかりますが、定義文では見つかりません。

相互参照 — 語釈文中の ICU プレースホルダ {0}{1} … を references 配列で解決します:

{
  "gloss": [ { "lang": "en", "text": "polite form of {0}" } ],
  "references": [ { "label": "", "to": "1234567", "text": "言う" } ]
}
  • {0} はその位置で references[0].text に、タップ可能なリンクとして置き換えられます。
  • to同じファイル内の対象語の id で、リンクは { source: <この辞書>, id: to } を開きます。一致しない to は何も開きません。
  • label は関係マーカー("see""cf.")で、{n} の無い 末尾参照に使います。語釈文中のリテラル {'{'(ICU エスケープ)と書きます。

6. この形式が持たないもの

次のものはアプリが表記・読みをキーに自前データから付与し、辞書間で一致させます — 指定不要 です:ピッチアクセント、ふりがな、ローマ字、頻度/「common」、音声、JLPT・WaniKani レベル、漢字の 内訳。また(互換のため受理はされるが)使用されないもの:トップレベルの tags マップ、 形ごと・語釈ごとの追加属性。カードは misc/field/dialect自由文字列としてそのまま表示します(コード展開なし)ので、読めるラベルを直接入れてください。

7. 最小例

最小の語 — かなのみと語釈 1 つ:

{ "id": "w1", "kana": ["ありがとう"], "sense": [ { "gloss": [ { "lang": "en", "text": "thank you" } ] } ] }
// (a) JA→EN 五段。POS は具体クラス v5k で、Yomitan の "v5" ではない。
{ "id": "1578850", "kanji": ["書く"], "kana": ["かく"],
  "sense": [ { "partOfSpeech": ["v5k", "vt"],
    "gloss": [ { "lang": "en", "text": "to write; to compose; to pen" } ] } ] }

// (b) JA→EN 内部相互参照つき。
{ "id": "敷衍", "kanji": ["敷衍", "敷延"], "kana": ["ふえん"],
  "sense": [ { "gloss": [ { "lang": "en", "text": "amplification (cf. {0})" } ],
    "references": [ { "label": "", "to": "演繹", "text": "演繹" } ] } ] }

// (c) かなのみの な形容詞。adj-na は活用クラスなのでタグ付けが有効。
{ "id": "1000230", "kana": ["きれい"],
  "sense": [ { "partOfSpeech": ["adj-na"], "gloss": [ { "lang": "en", "text": "pretty; clean; neat" } ] } ] }

8. POS 許可リスト

これらのいずれか(またはそれで始まる jmdict サブクラス)の場合のみ partOfSpeech に コードを入れてください。それ以外は人間向けラベルを misc に入れ、ここでは省略します。

v1
v5u v5k v5g v5s v5t v5n v5b v5m v5r
vk
vs vs-i vs-s
adj-i
adj-na

潰れた Yomitan の "v5" → 辞書形の末尾かなで展開: う→v5u く→v5k ぐ→v5g す→v5s つ→v5t ぬ→v5n ぶ→v5b む→v5m る→v5r。 不明なら省略。

← トップへ