mrkeyoor.com_
Sun 25 Oct 23:11 UTC
npmCLI & Toolingupdated 25 Oct 2026

lunr-languages review

A multilingual Lunr index sends each word through every selected language's stemmer. That detail matters when you choose between one shared index and separate indexes for each locale. lunr-languages 1.23.0 supplies language plugins for Lunr, including stemming, stopword filtering and tokenization for supported languages. You load the relevant registration modules, then select a plugin inside the index builder. It extends an existing search engine rather than providing a command-line search application. The 1.23.0 release notes list Farsi language support. Use this guide for pipeline selection and loading order; the [Lunr guide](https://mrkeyoor.com/libs/lunr/) covers the parent engine's indexing and query model.

Verdict

Use lunr-languages when a Lunr integration needs explicit language processing and you can check its matching against your own content. Start with one known locale, then justify a combined pipeline with query examples before shipping it.

Answers from our run

lunr-languages or lunr: which should you use?

lunr: Use core Lunr alone when its default English processing meets your needs. Its registry describes browser full-text search; choose language plugins only when the corpus calls for them. Use lunr-languages when a Lunr integration needs explicit language processing and you can check its matching against your own content.

When should you not use lunr-languages?

You need translation or semantic answers across languages. These plugins process search terms; adding them does not supply a translation model or embeddings.

API stability3/5The published 1.23.0 manifest defines CommonJS and explicit language-module subpaths, so the registration entry points have an inspectable package contract. The multi-language implementation also shows that selecting a plugin resets pipelines. This earns a middle rating: there is concrete integration evidence, but this guide has no runtime compatibility tests or evidence of a future compatibility guarantee.
Docs4/5The version-pinned README gives CommonJS and import examples, a combined-language setup and the exact Spanish accent-folding recipe. It also states Chinese runtime requirements and the absence of a browser fallback. The combined-stemmer warning is easier to find in the implementation than in the README, so a reader still needs source inspection to understand an important matching tradeoff.
Maintenance3/5The exact 1.23.0 release page lists a Farsi contribution, and the matching registry record exposes declaration paths and module exports. That supports a released change and inspectable packaging. It does not establish issue response times, regression coverage or a release schedule. The middle score reflects the available release evidence without treating one release as a maintenance guarantee.
Ecosystem3/5The published README documents browser and Node use, CommonJS registration, import syntax and TypeScript declarations. These are useful integration options for an existing Lunr project. The Chinese tokenizer path varies by runtime, and this guide did not validate bundlers or downstream projects. The middle score reflects documented reach, with no adoption figure or universal compatibility claim.

Use it if

  • Your documentation already uses Lunr and needs a supported language's text processing instead of the default English pipeline.
  • You can select language modules explicitly and maintain the same registration setup wherever you build indexes.
  • You have mixed-language documents and can evaluate the combined pipeline against real queries before choosing it.
  • Your Spanish search needs the documented opt-in accent-folding step, and you can configure both indexing and search pipelines.
Skip it if

Setup reality

Install Lunr separately, then load stemmer support before the chosen language module. Registering a module and selecting its pipeline are separate steps: require('lunr-languages/lunr.de')(lunr) attaches the German plugin, while this.use(lunr.de) applies it to a builder. Call the plugin before adding documents. The package's 1.23.0 registry manifest declares CommonJS, subpath exports and TypeScript declaration paths. Those declarations are packaging evidence, not a compatibility test of your bundler.

For a combined index, load each non-English language module before calling lunr.multiLanguage. English is built in. The version-pinned implementation resets the indexing pipeline and, when present, the search pipeline. It installs all selected stemmers rather than detecting the language of each document. Its own warning says words with the same stemming root may fail to converge. If documents already have a locale, compare a shared index with separate locale indexes using the queries your readers actually type. That is a suggested evaluation, not a measured result.

Spanish accent folding is optional. The documented recipe inserts lunr.es.accentFold before the Spanish stemmer in both pipelines. Configuring just the indexing side leaves the recipe incomplete. Chinese has a different deployment concern: the documentation describes Intl.Segmenter plus CJK bigrams, with optional @node-rs/jieba use in Node. Do not assume the browser and optional Node tokenizer produce identical results.

We did not install or execute this package for this guide. The snippets below are documentation-based, unexecuted illustrations using the published 1.23.0 documentation and multi-language implementation. Later snippets identify the earlier setup they require. No latency, bundle-size or search-quality measurement is claimed.

Ratings use a documentation-based scale from 1 to 5: 1 means substantial unresolved concerns, 3 means a usable documented path with material caveats, and 5 would require unusually complete evidence for that dimension. API stability considers the published module contract and pipeline behavior. Documentation quality considers setup instructions and disclosed limits. Maintenance considers the release notes, not a response-time promise. Ecosystem considers integration choices, not downloads or proven adoption.

Patterns

Install the engine and language package install-language-plugins

npm install lunr@2.3.9 lunr-languages@1.23.0

Unexecuted setup command. The README imports Lunr separately; these pins identify the versions discussed, not a tested compatibility matrix.

Register German after stemmer support register-german

const lunr = require('lunr')
require('lunr-languages/lunr.stemmer.support')(lunr)
require('lunr-languages/lunr.de')(lunr)

Documentation-based illustration. Loading the module attaches lunr.de; choose it in the builder before adding documents.

Select German in the builder build-german-index

// Continue after the German registration example.
const germanIndex = lunr(function () {
  this.use(lunr.de)
  this.ref('id')
  this.field('title', { boost: 10 })
  this.field('body')
  this.add({
    id: 'de-1',
    title: 'Dokument',
    body: 'Beispieltext'
  })
})

Unexecuted adaptation of the published German example with an explicit document ID. The language plugin belongs before document insertion; no expected result count is asserted.

Use import syntax for registration import-registration-modules

import lunr from 'lunr'
import stemmerSupport from 'lunr-languages/lunr.stemmer.support'
import de from 'lunr-languages/lunr.de'

stemmerSupport(lunr)
de(lunr)

The 1.23.0 README documents these imports and the manifest maps the subpaths. This illustration was not executed in Node or a bundler. Registration still needs a builder's this.use(lunr.de).

Load modules before combining languages register-mixed-languages

const lunr = require('lunr')
require('lunr-languages/lunr.stemmer.support')(lunr)
require('lunr-languages/lunr.de')(lunr)
require('lunr-languages/lunr.multi')(lunr)
const englishAndGerman = lunr.multiLanguage('en', 'de')

Unexecuted illustration backed by lunr.multi.js 1.23.0. English is built in; the non-English language must already be registered when multiLanguage is called.

Apply the combined pipeline once build-mixed-index

// Continue after the mixed-language registration example.
const mixedIndex = lunr(function () {
  this.use(englishAndGerman)
  this.ref('id')
  this.field('body')
  this.add({ id: 'en-1', body: 'Search documentation' })
  this.add({ id: 'de-1', body: 'Dokumentation suchen' })
})

The plugin resets the indexing pipeline and the search pipeline when present. Every word passes through both selected stemmers. This is an unexecuted example, not evidence of matching quality or automatic language detection.

Prepare the Spanish plugin register-spanish

const lunr = require('lunr')
require('lunr-languages/lunr.stemmer.support')(lunr)
require('lunr-languages/lunr.es')(lunr)

The published accent-folding recipe begins with these registrations. Registration alone does not enable the optional accentFold function. This example was not executed.

Configure accent folding on both sides fold-spanish-accents

// Continue after the Spanish registration example.
const spanishIndex = lunr(function () {
  this.use(lunr.es)
  this.pipeline.before(lunr.es.stemmer, lunr.es.accentFold)
  this.searchPipeline.before(lunr.es.stemmer, lunr.es.accentFold)
  this.ref('id')
  this.field('body')
  this.add({ id: 'es-1', body: 'Respiración' })
})

Documentation-based, unexecuted adaptation of the 1.23.0 Lunr 2 recipe. Insert accentFold before the stemmer in both pipelines. The README describes omitted-accent matching; this guide does not report a local match test.

Alternatives

PackageRegistryPick it when
lunrnpmUse core Lunr alone when its default English processing meets your needs. Its registry describes browser full-text search; choose language plugins only when the corpus calls for them.
minisearchnpmEvaluate MiniSearch when you are still choosing the underlying engine rather than extending an existing Lunr installation. Its registry describes a full-text search engine for browser and Node; language-processing suitability needs a separate check.

More cli & tooling guides

commander · chalk · click · esbuild · typescript · yargs · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.