Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

ovos-lang-parser

Map spoken and written language names to standard IETF/BCP-47 language codes, and back, in many languages, offline, with a two-function API.

"Brazilian Portuguese"  ->  "pt-br"
"alemão" (Portuguese)   ->  "de"
"pt-br"  ->  "Português do Brasil"   (rendered in Portuguese)
"pt-br"  ->  "Brazilian Portuguese"  (rendered in English)

The library understands language names written in 21 languages (see Coverage). A user can say "French" in English, "français" in French, or "Französisch" in German, and each resolves to the code fr. This is the piece you need whenever a human names a language in free text and your code needs a canonical code to act on: routing to a translation/TTS/STT engine, tagging an entity, or normalizing a messy label.

It ships as part of OpenVoiceOS, but has no OVOS runtime dependency and is useful in any plain-Python project.

Install

pip install ovos-lang-parser
# or
uv add ovos-lang-parser

Runtime dependencies are small: langcodes for tag normalization and ovos-utils for the fuzzy matcher. There are no models and no network calls: the wordlists are bundled.

30-second quickstart

from ovos_lang_parser import extract_langcode, pronounce_lang

# name -> code (second arg is the language the text is written in)
print(extract_langcode("Brazilian Portuguese", "en"))          # -> ('pt-br', 1.0)
print(extract_langcode("translate this to German", "en"))      # -> ('de', 1.0)

# code -> name, rendered in a chosen language
print(pronounce_lang("de", "en"))   # -> German
print(pronounce_lang("de", "pt"))   # -> Alemão

That is the whole surface for most callers: extract_langcode reads a name out of text and returns (code, confidence). pronounce_lang turns a code back into a human name.

The API in one screen

Function Purpose Returns
extract_langcode(text, lang) Find the language named in text (written in lang) (langcode, confidence). Confidence is 0.0 to 1.0, and an exact name match is 1.0
pronounce_lang(langcode, lang) Human name of langcode, rendered in lang str (falls back to the base tag, then to langcode unchanged)
get_lang_data(lang) The full {name: code} table for lang dict[str, str]
LANGS Codes of the languages a name can be written in list[str]

In both functions lang is the language the names are written in, not the language being named. extract_langcode("français", "fr") and extract_langcode("French", "en") both give fr. See docs/api.md for full signatures, the confidence model, and edge behavior.

Use it outside OVOS

The same two functions cover a range of standalone jobs. Each example below is a runnable script under examples/: run pip install ovos-lang-parser, then run the script. No OVOS stack is required.

Entity extraction / NER: pull a language out of free text

You have a sentence and want to know which language it mentions.

from ovos_lang_parser import extract_langcode

for text in ["translate this to Brazilian Portuguese",
             "can you say it in Mandarin Chinese?",
             "I'd like the subtitles in Greek"]:
    code, conf = extract_langcode(text, "en")
    if conf >= 0.7:
        print(f"{text!r} -> {code} ({conf:.2f})")

Because matching is fuzzy, apply a confidence threshold to decide whether a language was really mentioned. Full script: examples/ner_language_mentions.py.

Routing: pick a translation / TTS / STT engine by name

A user names a target language. You resolve it to a code and hand that to whatever engine your pipeline drives.

from ovos_lang_parser import extract_langcode

def resolve_target(user_request, spoken_in="en"):
    code, conf = extract_langcode(user_request, spoken_in)
    return code if conf >= 0.7 else None

print(resolve_target("read it back to me in German"))   # -> de  (feed to your TTS)

Full script (with a mock engine table): examples/routing.py.

Normalization: canonicalize messy names and autonyms to one code

Aliases, autonyms, and localized spellings all collapse to a single canonical code, so you can deduplicate and standardize labels regardless of how they were written.

from ovos_lang_parser import extract_langcode

labels = [("Deutsch", "de"), ("alemão", "pt"), ("German", "en"), ("allemand", "fr")]
for name, written_in in labels:
    code, _ = extract_langcode(name, written_in)
    print(f"{name:>10} -> {code}")   # all -> de

Full script: examples/normalization.py.

In an OVOS skill vs. standalone

The API is identical. Only where you get text and lang differs.

# Standalone language-routing utility
code, conf = extract_langcode(user_input, "en")

# Inside an OVOS skill, the utterance and its language come from the session
class MySkill(OVOSSkill):
    def handle_translate(self, message):
        utterance = message.data["utterance"]
        code, conf = extract_langcode(utterance, self.lang)
        ...

Coverage

Names can be written in 21 languages. Each carries a table of a few hundred target languages keyed by ISO 639 code.

an Aragonese ar Arabic ast Asturian bg Bulgarian
ca Catalan da Danish de German en English
es Spanish eu Basque fr French fy Frisian
gl Galician hr Croatian it Italian kab Kabyle
nl Dutch oc Occitan pt Portuguese ro Romanian
sk Slovak

The live list is always ovos_lang_parser.LANGS. Adding a language means dropping in one JSON file. See docs/coverage.md and docs/extending.md.

Documentation

License

Apache 2.0. See LICENSE.

Metadata

Release files for ovos-lang-parser 0.8.0a2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ovos-lang-parser 0.8.0a2
File Size Uploaded
ovos_lang_parser-0.8.0a2.tar.gz 47.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ovos-lang-parser 0.8.0a2
File Interpreter ABI Platform
ovos_lang_parser-0.8.0a2-py3-none-any.whl Python 3 none any Details

Total release size: 93.2 kB

Release files / ovos_lang_parser-0.8.0a2.tar.gz

Download URL ovos_lang_parser-0.8.0a2.tar.gz
Size 47.1 kB
Tags Source
SHA-256 checksum
How to use checksums
f09c1ca24bc18a4d35bec4efe20db5807f96240d7a1e6fbd08d4cb6e266ae790
BLAKE2b-256 checksum
How to use checksums
bd58e84dc7714b8a2644e4dcff0b90485993a5be44532dd1679676226c60b542
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / ovos_lang_parser-0.8.0a2-py3-none-any.whl

Download URL ovos_lang_parser-0.8.0a2-py3-none-any.whl
Size 46.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d1a75167989adb811d7cf68abfd3ef5a9eb8e87d227606f9cfd20e26d14a5a6f
BLAKE2b-256 checksum
How to use checksums
9e2a7b61d46ec1b189d1c450eb39e2707bcd2b4286903ebe89f5026c9b54d729
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page