辞書インポート形式
od-dict/1 · 自作辞書をインポートするための仕様
jmdict-<言語>-*.json.zip または .tgz。例:jmdict-eng、
jmdict-rus、jmdict-ger)をダウンロードして、そのままインポートすることです。
この形式はスーパーセットなので、変換も解凍も不要です。jmdict-all(全言語が 1 ファイル)は
巨大で扱いにくいので選ばないでください。
→ jmdict-simplified のリリース別の出典(Yomitan 辞書・CSV・自作データ)から自分で作りたい場合は、以下で形式を詳しく説明します。
アプリは自分の辞書を読み込めます。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 つ以上(空はコーパス項目のみ、§3)
{
"partOfSpeech": ["v1"], // 任意;コードのみ、自由文は不可(§4)
"misc": ["transitive"], // 任意;自由なラベル、そのまま表示
"gloss": [ // 訳語
{ "lang": "en", "text": "to eat" },
"食べる" // 裸の文字列 = { lang: "ru", origin: "original" }
],
"examples": [ ["ご飯を食べる", "ご飯を食べる"] ], // 任意;例文(§5a)
"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", // 任意;カードに表示される項目レベルのタグ
"headnote": "文語形は「食ぶ」", // 任意;語義の前に表示される自由テキスト(下記参照)
"isExpression": true, // 任意;複数語の表現
"common": true, // 任意;高頻度の項目
"kanji": ["食べる", "喰べる"], // 0…n の表記
"kana": ["たべる"], // 0…n の読み
"sense": [ /* … */ ],
"examples": [ /* … */ ] // 任意;項目レベルのコーパス例文(§5a)
}
同一性は (source, id) で、UNIQUE です。
idはファイル内で一意である必要があります。 テーブルはUNIQUE(source, source_entry_id)に対する単純なINSERTで書かれるため、idの重複はインポートのバッチを失敗・中断させます(黙って無視され ません)。出典の id を使うか、無ければ安定した一意の値(連番や見出し語)を作ってください。kanji/kanaの要素は裸の文字列(通常)か jmdict-simplified の オブジェクト{ "text": "…" }。読まれるのはtextだけで、 残りは受理されますが破棄されます。裸の文字列を推奨。- 語には少なくとも 1 つの形が必要です。日本語では
kanaを与え、 かなのみの語ではkanjiを省略します。 headnoteは語義の前にある項目のテキストです — 元の辞書が見出し語と 最初の語義のあいだに印刷しているもの(文法の注記、用法の前書きなど)を、1 つの自由テキストとして 保持します。語義の上に通常の本文としてそのまま表示され、出典ごとに独立です(統合カードでは各辞書が 自分のものを表示)。表示専用で、検索には索引されず、形態素解析にも読まれません — 機械可読な文法をここに入れないでください。label(チップとして表示される短いタグ) とは別物です。空白のみは無しとして扱われます。- 項目レベルの
examplesは例文だけの辞書(コーパス)のためのものです: 特定の語義ではなく語全体に属する例文で、各例文は出典のtag(§5a の形 (c))を 持てます。このコーパス項目だけが空のsenseを許される唯一の場合です。 通常の項目は例文を語義の中に入れ、senseは 1 つ以上必要です。
グループ化。 アプリは(見出し + 読み)のグループごとに 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に入れれば、そのまま表示されます。 - 意味を持つのは活用クラスのみ。他のコード(
n、exp、vt、advなど)は検索では無視されます — 無害ですが無意味です。 - Yomitan の罠:潰れた
v5をコピーしないこと。 エンジンにv5クラスは無く、具体的なもの(v5k、v5r…)が必要です。 裸の"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 エスケープ)と書きます。
5a. 例文 — 受理される 3 つの形
examples の各要素は次の 3 つの形のどれでも構いません —
インポータが自動判別します:
// (a) od-dict/1 の位置ペア — [日本語, 訳];
// 任意の第 3 要素はイディオムの印。
"examples": [ ["ご飯を食べる", "to eat a meal"] ]
// (b) jmdict-simplified のオブジェクト — jmdict-examples-eng リリースの形。
// jpn の文が例文、eng の文がその訳になる。
"examples": [ {
"source": { "type": "tatoeba", "value": "162365" },
"text": "食べる",
"sentences": [ { "lang": "jpn", "text": "私はリンゴを食べる。" },
{ "lang": "eng", "text": "I eat an apple." } ]
} ]
// (c) od-dict/1 のコーパス・オブジェクト — ペアでは持てないもの:
// 例文ごとの出典 tag。
"examples": [ { "text": "彼は走った。", "translation": "He ran.", "tag": "一/坊っちゃん" } ]
- 形 (b) について:文のキーは
lang(3 文字の ISO 639-3:jpn/eng)。jpnの文が無い要素はスキップされ、訳が無ければ 空文字列になります。これにより生のjmdict-examples-engファイルが例文ごと そのままインポートできます。 - 形 (c) はテキストから引用した例文のためのものです:
tagは「どこから取ったか」 (章・作品)を示す自由な出典ラベルで、例文の横に表示されます。コーパス・ビルダーはこれを 項目レベルに出力します(§3 — 例文だけの辞書)が、sense.examplesでも同様に 受理されます。
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" } ] } ] }
// (d) 内蔵テキスト『坊っちゃん』の実際のコーパス項目:本文から引用した項目レベルの例文、
// 出典 tag(章番号)、sense は無し(§3、§5a)。訳は PD の英訳(Morri 1918)。
{ "id": "無鉄砲·むてっぽう", "kanji": ["無鉄砲"], "kana": ["むてっぽう"],
"examples": [ { "text": "親譲りの無鉄砲で小供の時から損ばかりしている。",
"translation": "Because of an hereditary recklessness, I have been playing always a losing game since my childhood.",
"tag": "一" } ] }
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。
不明なら省略。