Dictionary Formats#

Plover supports multiple proprietary steno dictionary formats, as well as some open formats widely used by the Open Steno community. At a high level, there are two main types of dictionaries: static and programmatic.

Static Dictionaries#

Static dictionaries consist of entries mapping steno outlines to translations. This is the simplest type of dictionary, and most Plover dictionaries will be of this form.

JSON#

The most common format for steno dictionaries in Plover is the JavaScript Object Notation (JSON) format. This consists of a series of key-value pairs separated by commas and surrounded by curly brackets {}:

{
  "KAT": "cat",
  "KAT/HROG": "catalog",
  "KA/TA/HROG": "catalog",
  "-S": "{^s}"
}

In each key-value pair, the key is the canonical steno notation of the outline, with the strokes separated by slashes, and the value is the translation for that outline in Plover’s translation language. This format is used for dictionaries because it matches Plover’s internal storage format almost exactly.

RTF/CRE#

Another common dictionary format, which is also supported by most proprietary steno software, is the Rich Text Format with Court Reporting Extensions (RTF/CRE) format. It was designed as an interchange format between steno systems, so Plover supports some of the features implemented into the format.

{\rtf1\ansi\cxrev100\cxdict
{\*\cxs KAT}cat
{\*\cxs KAT/HROG}catalog
{\*\cxs KA/TA/HROG}catalog
{\*\cxs -S}\cxds s{\*\cxcomment -s suffix}
}

In RTF dictionaries, while the steno outline is also written in the same notation, the translation isn’t written in Plover’s translation language; instead it uses RTF-specific formatting controls that translate to different commands for each steno system that supports it. RTF also supports some entry-level metadata, such as comments and historical usage data, but these can’t be read by Plover.

It’s generally not recommended to maintain RTF dictionaries, since they can be slow to parse and the format isn’t especially well defined, but this is often an option if, for example, professional stenographers would also like to use their personal dictionaries with Plover.

Proprietary Formats#

Plover also supports some proprietary software’s native dictionary formats, with the help of some plugins:

Programmatic Dictionaries#

Programmatic dictionaries, instead of containing a list of entries, calculate translations on the fly, the moment Plover requests them. This is most useful for heavily regular dictionaries like a symbol system or a syllabic theory.

The plover-python-dictionary plugin adds support for programmatic dictionaries written in Python, which can be used in Plover just like static ones.

Programmatic dictionaries primarily expose a lookup function, which calculates a translation for a given steno outline. Some dictionaries may also provide a reverse-lookup function, which calculates all the possible outlines that translate to a particular text.

LONGEST_KEY#

The maximum number of strokes that this dictionary can translate. Plover uses this value to optimize dictionary lookups by only using this dictionary when looking up outlines this length or shorter.

This attribute is required.

lookup(outline: Tuple[str]) str

Given an outline which is a tuple of steno strokes, returns the translation for this outline, or raises a KeyError when no translation is available. The translation should be in Plover’s translation language.

This function is required.

reverse_lookup(translation: str) List[Tuple[str]]

Given a translation in Plover’s translation language, returns the list of possible outlines that translate to it. The list may be empty if there are no possible outlines in this dictionary.

This function is optional; the dictionary still works without implementing it, but it will not support searching in the Lookup tool.

Here is an example of a very basic programmatic dictionary which just translates KP-PL to example:

LONGEST_KEY = 1


def lookup(outline):
  assert len(outline) == 1

  stroke = outline[0]
  if stroke == "KP-PL":
    return "example"
  else:
    raise KeyError


def reverse_lookup(translation):
  if translation == "example":
    return [("KP-PL",)]
  else:
    return []