Language Detect

Green Node + Browser Text 1.73–8.1× faster

Language detection powered by whatlang. Paragraph-size Green, short-string Red by design.

Version
0.1.1

Install

pnpm add @amigo-labs/language-detect

Benchmarks

Trend (4 pts)

Benchmark

language-detect — tweet (50 B)

1.73× vs slowest
  • @amigo-labs/language-detect 12.14K hz · 1.73×
  • franc 7.02K hz

Benchmark

language-detect — paragraph (~300 B)

8.06× vs slowest
  • @amigo-labs/language-detect 8.84K hz · 8.06×
  • franc 1.10K hz

Benchmark

language-detect — article (~11 KB)

5.92× vs slowest
  • @amigo-labs/language-detect 4.95K hz · 5.92×
  • franc 836 hz
Performance trend for Language Detect
4 commits · last 2026-05-22

README

@amigo-labs/language-detect

Language detection via whatlang — ISO-639-3 codes out, franc-compatible shape.

Paragraph-sized Latin/Cyrillic/CJK detection is clear Green; short strings (<50 B) fall back to 'und' by design because no trigram detector is reliable there. See docs/perf-review/franc.md for the full shape analysis.

Install

pnpm add @amigo-labs/language-detect

Usage

import {
  detect,
  detectIfLong,
  detectAll,
  detectMany,
  languageExists,
} from '@amigo-labs/language-detect'

detect('The quick brown fox jumps over the lazy dog')
// 'eng'

detect('Der schnelle braune Fuchs springt über den faulen Hund')
// 'deu'

detect('hi')
// 'und' — below default minLength (10 bytes)

detectIfLong('hi')
// null — prefer this over 'und' in pipelines that branch on result

detectAll('Le chat dort sur le tapis rouge')
// [{ lang: 'fra', confidence: 0.92 }]

detectMany([
  'The quick brown fox…',
  'Der schnelle braune Fuchs…',
  'hi',
])
// ['eng', 'deu', 'und']

languageExists('eng') // true
languageExists('xyz') // false

Options

type DetectOptions = {
  minLength?: number  // default 10 bytes
  only?: string[]     // ISO-639-3 allow-list
  ignore?: string[]   // ISO-639-3 deny-list, applied after `only`
}

Install for the browser

The same import works in Angular, React, Vite, esbuild, and webpack ≥ 5 — the bundler picks the WASM build via the browser conditional export:

import { detect } from '@amigo-labs/language-detect'

Node consumers get the napi binary; browser consumers get the in-tarball wasm/pkg/ artifact. whatlang’s bundle is ~100 KB gzipped, well under the 500 KB browser budget.

Migration from franc

See MIGRATION.md — nearly drop-in on common cases; the confidence scale is [0, 1] instead of franc’s internal range, and rare franc-all languages return 'und' here (bundle-size trade-off).

License

MIT

Perf review

Perf-Review: @amigo-labs/language-detect

Status: 🟢 Green, bimodal (tweet bucket 🟡 Yellow) · Reviewed: 2026-07-02 · Version: 0.1.1

Verdict

1.73× (50 B tweet), 8.06× (~300 B paragraph), 5.92× (~11 KB article) vs. franc (bench 2026-05-22). The candidate review predicted overall Yellow — Green on paragraphs, Red on short strings. The measurement came in better on both ends: the paragraph bucket doubles the predicted 3–4×, and the tweet bucket lands at 1.73× (Yellow by the candidate’s own ≥1.5× threshold, not Red — the FFI floor did not eat the win). Trigram scoring over whatlang’s compile-time language profiles is exactly the compute-heavy, single-string-in / small-result-out shape NAPI likes.

Evidence

Measured speedup (docs/benchmarks/language-detect.json, 2026-05-22, commit b67b03d)

Scenario@amigo-labs/language-detectfrancSpeedup
tweet (50 B)12 137.51 Hz7 019.62 Hz1.73×
paragraph (~300 B)8 835.18 Hz1 096.13 Hz8.06×
article (~11 KB)4 946.72 Hz835.62 Hz5.92×
  • docs/packages.json speedup: "1.73–8.1× faster".
  • Install size: 27 KB vs franc’s 304 KB.

Benchmark gaps

  • The candidate gate’s tiny (10 B) and 200 B buckets were not benched; the 50 B and ~300 B measurements bracket them.

What shipped vs. the candidate prediction

  • 87 languages (whatlang’s set) vs. franc-all’s 414 — the mainstream-language 80/20 the candidate review scoped.
  • franc-compatible ISO-639-3 return codes ('eng', 'deu', 'und', …).
  • detectIfLong guard: inputs below the minimum length return 'und' instead of a noise guess.

Divergences

Confidence scores are not comparable to franc’s (different normalization); the detected-language code matches franc on the conformance corpus for supported languages. Languages outside whatlang’s 87 fall back to 'und'. See crates/language-detect/__conformance__/divergences.md.

Pre-port assessment: franc.md

References

  • Crate: crates/language-detect
  • Bench shard: docs/benchmarks/language-detect.json
  • docs/packages.json speedup: "1.73–8.1× faster"