Skip to content

Subentries and links

An article can contain independently searchable compounds, idioms and examples. In 旺文社漢字典, a 熟語 search for ”ちょうご” opens 鳥語 within the 鳥 article:

The Dictionaries app with 鳥語 selected in KJT's 熟語 results and the compound visible within the 鳥 article.

The selected compound has its own headline and target. Its XML remains part of the 鳥 page. This shortened native excerpt shows the target on its container:

<SubItem id="08721-8006">
  <SubItemC>
    <SubItemHeadG>
      <headword class="熟語">…鳥語…</headword>
      <yomi>チョウ(テウ) ゴ</yomi>
    </SubItemHeadG>
    …
  </SubItemC>
</SubItem>

SubItem is KJT's markup. The example below uses a simpler structure and lets the writer allocate the IDs.

Start a kanwa product

Create a separate product using the kanwa profile. The steps follow the same pattern as the first dictionary, now with a compound inside the article. Use a new directory for destination.

product = mkd.ProductWriter.create(
    destination,
    mkd.DictionaryMetadata(
        display_name=mkd.LocalizedString(ja="鳥の漢字辞典"),
        version="1.0",
    ),
    profile=mkd.CreationProfile.KANWA,
)

dictionary = product.add_dictionary(mkd.DictionaryContent(
    identifier="example.birds.kanwa",
    directory="kanwa",
    dictionary_id=1001,
    title=mkd.LocalizedString(ja="鳥の漢字辞典"),
    languages=["ja"],
))
auto product = MKD::ProductWriter::create(destination, {
    .displayName = MKD::LocalizedString{.ja = "鳥の漢字辞典"},
    .version = "1.0",
}, MKD::CreationProfile::Kanwa).value();

auto dictionary = product.addDictionary({
    .identifier = "example.birds.kanwa",
    .directory = "kanwa",
    .dictionaryId = 1001,
    .title = MKD::LocalizedString{.ja = "鳥の漢字辞典"},
    .languages = std::vector<std::string>{"ja"},
}).value();

Allocate the article and compound

article = dictionary.create_entry()
target = article.target
compound = article.add_target(mkd.EntryTargetKind.COMPOUND)
auto article = dictionary.createEntry().value();
const auto target = article.target();
const auto compound = article.addTarget(MKD::EntryTargetKind::Compound).value();

target opens the whole 鳥 article. compound opens 鳥語 inside it. Allocate targets before writing the XML, then reuse them in headlines, keys and links. You do not choose numeric IDs or ranges.

Add headlines and keys

Kanwa parent entries use Headword. Their jukugo use Idiom, the same search scope used for phrases in general dictionaries.

dictionary.add_headline(mkd.HeadlineComponents(
    "鳥", target, sorting_headline="とり",
))
dictionary.add_search_key(mkd.SearchScope.HEADWORD, "とり", target)
dictionary.add_search_key(mkd.SearchScope.HEADWORD, "鳥", target)

dictionary.add_headline(mkd.HeadlineComponents(
    "鳥語", compound, sorting_headline="ちょうご",
))
dictionary.add_search_key(mkd.SearchScope.IDIOM, "ちょうご", compound)
dictionary.addHeadline({
    .headline = u"鳥", .sortingHeadline = u"とり", .entryId = target,
}).value();
dictionary.addSearchKey(MKD::SearchScope::Headword, "とり", target).value();
dictionary.addSearchKey(MKD::SearchScope::Headword, "鳥", target).value();

dictionary.addHeadline({
    .headline = u"鳥語", .sortingHeadline = u"ちょうご", .entryId = compound,
}).value();
dictionary.addSearchKey(MKD::SearchScope::Idiom, "ちょうご", compound).value();

Write the XML

Use the compound target as the container's id. Formatting it produces the native ID spelling, such as 00001-8001.

article.write_xml(f"""<html xmlns="http://www.w3.org/1999/xhtml" hmhtml="5">
  <head><title>鳥</title></head>
  <body>
    <headword>鳥</headword>
    <p>とり。</p>
    <div id="{compound}">
      <headword>鳥語</headword>
      <p>鳥の鳴き声。</p>
    </div>
  </body>
</html>""")
article.writeXml(std::format(R"(<html xmlns="http://www.w3.org/1999/xhtml" hmhtml="5">
  <head><title>鳥</title></head>
  <body>
    <headword>鳥</headword>
    <p>とり。</p>
    <div id="{}">
      <headword>鳥語</headword>
      <p>鳥の鳴き声。</p>
    </div>
  </body>
</html>)", compound.toString())).value();

Every allocated passage target must appear in the XML. Writing consumes the XML and closes target allocation for that article. Finish the dictionary and product as in the first dictionary.

Reading a compound result still retrieves the whole article XML. Keep the full result target to locate its subsection.

Choose other target kinds

The target kind describes a location. The search scope describes the index used to find it. Allocating a target does not add keys or XML for you.

Target kind Use it for Usual search scope
Compound Kanwa jukugo Idiom
Idiom General-dictionary idioms and phrases Idiom
Example Examples or quotations Example
Sense Individual meanings Sense
Section Other article sections Usually reached through a link

For example, before writing an article, allocate an example target and put it on the example's element:

example = article.add_target(mkd.EntryTargetKind.EXAMPLE)
example_xml = f'<p id="{example}">朝、鳥の声で目を覚ます。</p>'
const auto example = article.addTarget(MKD::EntryTargetKind::Example).value();
auto exampleXml = std::format(
    R"(<p id="{}">朝、鳥の声で目を覚ます。</p>)", example.toString());

Insert that fragment into the article XML. Add a headline and Example search keys if the example should appear in search results.

InlineText builds escaped text and native links. Use an existing target, such as the compound above:

link = mkd.InlineText()
link.append(mkd.EntryLink(compound, "鳥語"))
link_xml = link.to_xml()
MKD::InlineText link;
link.append(MKD::EntryLink{compound, "鳥語"});
auto linkXml = link.toXhtml().value();

Insert the fragment into another article before writing it. Reserve entries and targets first when linking to articles you have not written yet. Links are checked when the dictionary is finished.