Skip to content

Dictionary acquisition

On this page

ferrolex can acquire a reviewed pair of LibreOffice Hunspell files, but it does not bundle dictionary content and it never downloads a dictionary during normal checking, validation, compilation, tests, or CI.

This is source acquisition, not ferrolex dictionary distribution: the optional installer fetches raw upstream bytes only after an explicit user command and writes them into a caller-selected local cache. ferrolex does not operate a companion artifact repository or publish these dictionaries. A product that redistributes a resulting compiled artifact remains responsible for the locale-specific license evidence recorded in the catalog.

The optional ferrolex dictionary command is an installer, not an updater:

  • no cache directory is inferred; the caller supplies --cache;
  • only absolute https:// source URLs are accepted;
  • every .aff and .dic response is checked against a catalogued SHA-256 digest at an immutable upstream revision;
  • the bytes are verified before an atomic, non-replacing write to <cache>/<locale>/<file-name>;
  • cache files and their parent directory are synced before success is reported, and stale temporary siblings from interrupted writes are removed later;
  • filesystems without hard-link support use an OS-locked atomic rename followed by a digest re-check; the persistent hidden lock sidecar is reusable and a terminated installer releases its lock automatically;
  • a cache file with different bytes is preserved and causes an error;
  • a cache file whose bytes match the pinned digest is reused without a network request;
  • redirects are refused with a diagnostic that identifies the original URL and HTTP status; the command has no implicit retries, telemetry, or background updates.
  • requests time out after 10 seconds while connecting, 15 seconds while awaiting response headers, 60 seconds while receiving a response body, or 75 seconds end-to-end; timeout failures identify the URL and stage.

This separation ensures the spell-checking runtime remains deterministic and offline after installation. The command never follows a branch, learns a new digest, or replaces a cached file with different bytes. A catalog update is a normal reviewed ferrolex release change.

Initial LibreOffice catalog

ferrolex dictionary list exposes these reviewed sources:

LocalePinned upstream pathsReviewed SPDX expressionLocale-specific notice
en_USen/en_US.aff, en/en_US.dicGPL-2.0-onlyen/license.txt
de_DEde/de_DE_frami.aff, de/de_DE_frami.dicGPL-2.0-only OR GPL-3.0-onlyde/README_de_DE_frami.txt
hu_HUhu_HU/hu_HU.aff, hu_HU/hu_HU.dicMPL-2.0-or-later OR LGPL-3.0-or-laterhu_HU/README_hu_HU.txt
es_ESes/es_ES.aff, es/es_ES.dicGPL-3.0-or-later OR LGPL-3.0-or-later OR MPL-1.1es/LICENSE.md
fr_FRfr_FR/dictionaries/fr.aff, fr_FR/dictionaries/fr.dicMPL-2.0fr_FR/dictionaries/README_dict_fr.txt
it_ITit_IT/it_IT.aff, it_IT/it_IT.dicGPL-3.0-onlyit_IT/README_it_IT.txt
pt_BRpt_BR/pt_BR.aff, pt_BR/pt_BR.dicLGPL-3.0-only OR MPL-1.1pt_BR/README_pt_BR.txt
pt_PTpt_PT/pt_PT.aff, pt_PT/pt_PT.dicGPL-2.0-only OR LGPL-2.1-only OR MPL-1.1pt_PT/LICENSES.txt
nl_NLnl_NL/nl_NL.aff, nl_NL/nl_NL.dicBSD-3-Clause OR CC-BY-3.0nl_NL/LICENSE.txt
pl_PLpl_PL/pl_PL.aff, pl_PL/pl_PL.dicGPL-2.0-only OR LGPL-2.1-only OR MPL-1.1 OR Apache-2.0 OR CC-BY-4.0pl_PL/README_pl_PL.txt
ru_RUru_RU/ru_RU.aff, ru_RU/ru_RU.dicBSD-3-Clauseru_RU/README_ru_RU.txt
tr_TRtr_TR/tr_TR.aff, tr_TR/tr_TR.dicMPL-2.0tr_TR/LICENSE
arar/ar.aff, ar/ar.dicGPL-2.0-or-later OR LGPL-2.1-or-later OR MPL-1.1ar/COPYING.txt
uk_UAuk_UA/uk_UA.aff, uk_UA/uk_UA.dicMPL-1.1uk_UA/README_uk_UA.txt
sv_SEsv_SE/dictionaries/sv_SE.aff, sv_SE/dictionaries/sv_SE.dicLGPL-3.0-onlysv_SE/LICENSE_sv_SE.txt
id_IDid/id_ID.aff, id/id_ID.dicLGPL-3.0-onlyid/LICENSE-dict
hi_INhi_IN/hi_IN.aff, hi_IN/hi_IN.dicGPL-2.0-onlyhi_IN/COPYING
bn_BDbn_BD/bn_BD.aff, bn_BD/bn_BD.dicGPL-2.0-onlybn_BD/COPYING

All paths and file digests are pinned to LibreOffice/dictionaries commit f2ff99058268502bdcf4cad25c1ca2935ad8aa7d. Each reviewed SPDX expression is paired with its linked locale notice, rather than assigning one license to the entire LibreOffice collection. It is a source catalog, not legal advice or a claim that all dictionaries share one redistributable license. Consumers must review and accept the linked terms for every locale they distribute.

list also prints the source encoding. Installation preserves upstream bytes: de_DE is ISO-8859-1, pl_PL is ISO-8859-2, id_ID has an ISO-8859-1-compatible affix file with a UTF-8 word list, and hu_HU has a UTF-8-declared affix file with reviewed ISO-8859-2 fallback bytes plus a UTF-8 word list; the other initial entries are UTF-8. validate and install decode shared UTF-8, ISO-8859-1, and ISO-8859-2 pairs losslessly from their AFF SET declaration. install also supplies the reviewed per-file or fallback decoding policy needed by the mixed-encoding id_ID and hu_HU pairs. Arabic and Turkish are deliberately available for compatibility evaluation; recognition support remains dependent on the diagnostics from validate --strict. The locale compatibility matrix records this evidence separately for every catalog entry.

CJK locales are intentionally absent. They need a dedicated text-segmentation contract, rather than treating a dictionary fetch as complete language support. The pinned LibreOffice collection has no Urdu (ur) Hunspell pair, so Urdu is not silently substituted with another upstream source; adding it needs a separate provenance and license review.

Fetch workflow

First inspect the available immutable source and its notice:

ferrolex dictionary list

Install a reviewed locale into an explicit cache directory:

ferrolex dictionary fetch pl_PL \
  --cache "$HOME/.cache/ferrolex/dictionaries"

The command prints the fetched paths plus the reviewed SPDX expression and notice URL, then points to dictionary install for building the runtime cache with the pair's reviewed provenance and encoding policy. Validate the resulting files before using them:

ferrolex validate --strict \
  "$HOME/.cache/ferrolex/dictionaries/pl_PL/pl_PL.aff" \
  "$HOME/.cache/ferrolex/dictionaries/pl_PL/pl_PL.dic"

No dictionary data or network fixtures are committed in this repository. Only source paths, provenance notices, encodings, and SHA-256 values are stored. That preserves the engine's MIT OR Apache-2.0 licensing while making each consuming product responsible for the exact upstream terms it accepts.

Checked install workflow

For the normal workflow, install obtains the same checked source bytes (or reuses an already verified cache entry) and then runs the strict byte-oriented importer in one operation:

ferrolex dictionary install pl_PL \
  --cache "$HOME/.cache/ferrolex/dictionaries"

The importer decodes UTF-8, ISO-8859-1, and ISO-8859-2 in memory, without rewriting the cache bytes whose digest establishes provenance. It also handles the catalogued id_ID mixed encoding pair explicitly. An unsupported recognition directive makes install return exit status 1, while leaving the verified source cache available for diagnostic work. fetch remains useful when acquisition and validation need to be separate steps.

Library consumers using the umbrella crate should reuse the catalog's reviewed encoding policy instead of matching the mixed-encoding variants themselves:

let encodings = ferrolex::catalog_import_encodings(source.encoding());

Pass the returned value to import_bytes_with_encodings when it is Some. For None, use import_bytes, which discovers the shared encoding from the affix file's SET declaration.

After a successful strict import, install also writes a versioned, provenance-bound runtime cache beside the affix source. See Hunspell runtime cache for its validity and rebuild contract.

Use the installed dictionary offline with the affix path:

ferrolex check \
  --hunspell "$HOME/.cache/ferrolex/dictionaries/pl_PL/pl_PL.aff" \
  słowami

This loads the adjacent runtime cache only after verifying it against both source files. If no cache exists, --hunspell strictly imports an ordinary pair directly and prints a slower-path notice plus a compile/--compiled hint. Catalog pairs with reviewed per-file encoding overrides must go through dictionary install; a locale-shaped filename alone is not treated as catalog provenance. This makes compatible read-only system dictionary directories usable without writing beside their sources. Checking never downloads or silently writes a cache; importer errors and malformed or stale caches remain errors.