sillsdev / sillsdev/interlinearizer-extension
Allow user to gloss internally and through Lexicon extension
@imnasnainaec is already working on this.
Since Aug 28, 2026.
- Dominant language
- TypeScript
- Stars
- 2
- Forks
- 0
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 55
Description
Glossing already works with no lexicon: free-form gloss strings on TokenAnalysis / MorphemeAnalysis, plus a suggestion engine pooled from approved analyses in the current draft. This epic adds the second path — linking a gloss to a lexicon — as a strictly additive layer over the one that already works.
Settled
Free-form glossing and lexicon linking are distinct, and both are first-class. A gloss never requires a link. The model encodes this and it stays: a typed gloss takes precedence over glossSenseRef / senseRef when both are present, and the ref is retained so the link is not lost.
References are outbound only — the lexicon owns its records and never depends on ours; editing or deleting an analysis drops our reference and leaves the lexicon untouched (#186, #194). One item under this epic writes to a lexicon (#229); nothing else does.
The architectural line
The interlinearizer must work with no FW Lite connection. Three tiers, all supported:
- Tier 0 — no lexicon at all. Today's behavior: free-form glossing and draft-internal suggestions. Always available. This is a supported configuration, not a degraded mode.
- Tier 1 — a lexicon without FW Lite. Form undecided; see the open question below.
- Tier 2 — FW Lite, via the Lexicon extension's
lexicon.entryService.
So this repo depends on a narrow port of its own (#226), not on IEntryService. The model asks four things of a lexicon — resolve a sense, search by form, create an entry, report capabilities — and FW Lite is one adapter behind that port. Typing against IEntryService directly would bake MiniLcm's model into this repo and force any other lexicon to implement MiniLcm's tail to be substitutable.
Providers differ in capability, not just presence: a tier-1 lexicon will have entries and senses but no allomorphs and no MSAs. UI is gated per capability, and an unavailable capability is not rendered rather than rendered-and-disabled.
Open question
What tier 1 is: minimal lexicon handling inside this extension, or a separate stand-alone lexicon extension without FW Lite. The port is the same either way — only create-entry semantics (#229) and where a tier-1 lexicon persists depend on the answer. Everything else here proceeds with the question open.
Promoting the Analysis Catalog (#186) into the tier-1 lexicon is the cheapest shape the in-extension option could take, and worth costing before deciding. Its rows are already deduped records with ids, and it covers the read half of the port:
- The split the port needs.
normalizeSurfaceFormandanalysesAreIdenticalinsrc/utils/analysis-identity.tsfor identity and dedupe, a separate accent-strippingfoldForSearchinsrc/utils/search-fold.tsfor matching, deliberately never unified — which is exactly resolve a sense against search by form. - Records with reachable ids.
CatalogRow.analysisId, and zero-usage rows listed rather than hidden, so a record with no draft occurrence is still findable. - A core a third consumer can share.
src/utils/analysis-query.tsis pureTextAnalysis + query -> rows, already backing the catalog panel and intended for the query API (#128); a tier-1 provider would sit alongside them, not fork them.
It covers none of the store half, and that is what promotion costs:
- Persistence. The catalog derives from the draft's
TextAnalysison every read and stores nothing. Zero data dependency is what makes its whole-draft scope affordable; a lexicon has to outlive the draft. - Lexeme-level records. The catalog is token analyses only, because only those are deduped and shared on write — morphemes are row detail. A lexicon's unit is the lexeme, so the layer a lexicon needs as records is the layer that has none.
- Ids that survive a merge. Merge is first-class in the catalog and retires one id by moving its links. Right for analyses; for a lexicon it dangles every outbound ref (#225).
- Fields with values in them.
pos,features,status,confidence, and every lexicon ref are lexicon-shaped and written by no current code path. They fill on PT9 import (#150).
Promotion also collides with a rule this epic otherwise treats as settled: with the catalog as the lexicon, outbound-only turns self-referential — deleting a row deletes the record it refers to — and the catalog's own edit, merge, and delete become lexicon writes, which is more than #229 alone. Either that rule is restated for the case where we own both sides, or tier 1 lands somewhere else.
Work items
- #225 — Namespace lexicon refs by provider. Blocks everything; must land before any code path writes a ref.
- #226 — Define the lexicon port and capability descriptor.
- #44 — Choose or Create Lexicon.
- #227 — FW Lite adapter: resolve refs for display.
- #228 — Link a gloss to an existing lexicon sense.
- #229 — Create a lexicon entry from an unglossed morpheme. Also blocked on the open question above.
Not yet filed: the lexicon as a suggestion source. The engine is a pure function over a pool, so this adds a second pool source. Deliberately deferred until the items above ship and it is clear whether draft-internal suggestions were already sufficient.
Out of scope until Lexbox ships it
allomorphRef and grammarRef cannot resolve — no allomorph or MSA surface exists in MiniLcm. Tracked in sillsdev/languageforge-lexbox#2558 and sillsdev/languageforge-lexbox#2559, consumed here by #189, not by this epic.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.