Language Detection and Translation Plugins¶
In a nutshell
These add-ons give OVOS two related abilities. They work out what language some text is in, and they rewrite text from one language into another. They power features like Bidirectional Translation, so your assistant can understand and reply across languages. Some run entirely offline on your device. Others call an online service. You pick which ones to use in the configuration file. See the Glossary for terms.
Tip
Just want translation to work? See Bidirectional Translation. This page covers the plugin internals.
Language detection and translation plugins let OVOS identify the language of a piece of text and translate it between languages. They are the building blocks used by features like Bidirectional Translation, and they can also be called directly from your own code.
New here? Two separate jobs are involved:
- Detection decides what language a string is in (e.g.
"Hola"→es). - Translation rewrites a string into another language (e.g.
"Hola"→"Hello").
A single package may ship one or both. In mycroft.conf you select them under the "language" section with "detection_module" (a detect plugin) and "translation_module" (a translate plugin).
Recommended: NLLB + fastText (offline)
For offline translation, the recommended default is ovos-translate-plugin-nllb (NLLB-200)
paired with ovos-lang-detector-fasttext-plugin for offline detection. Both run fully
on-device once their models are downloaded. Use ovos-google-translate-plugin or
ovos-translate-plugin-server when translation coverage or quality matters more than
keeping text off the network. They are also a good choice when the device lacks the
compute budget to run NLLB locally.
Available Language Plugins¶
| Plugin (entry-point name) | Detect | Translate | Type | License | Notes | Maturity |
|---|---|---|---|---|---|---|
ovos-translate-plugin-server (repo) |
yes | yes | API (self/community hosted) | Apache-2.0 | Client for ovos-translate-server. Ships a built-in public-server list with failover. Detection is a separate entry-point, ovos-lang-detector-plugin-server. |
Stable |
ovos-translate-plugin-nllb (repo) |
no | yes | FOSS (Offline) | Apache-2.0 | NLLB-200 via CTranslate2. Downloads a model the first time. | Stable |
ovos-lang-detector-fasttext-plugin (repo) |
yes | no | FOSS (Offline) | Apache-2.0 | fastText language identification. | Stable |
ovos-lang-detector-plugin-voter (repo) |
yes | no | FOSS (Offline) | no license file | A voter that averages classic detectors. By default it uses cld2, langdetect and fastlang. Package name is ovos-lang-detector-classics-plugin; ovos-lang-detector-plugin-cld3 is also available as a separate sub-plugin from the same package. |
Stable |
ovos-translate-plugin-linguonnx (repo) |
no | yes | FOSS (Offline) | Apache-2.0 | ONNX routing over a graph of translation models, no torch. Reaches 593 languages. See linguonnx Language Plugins. | Alpha |
ovos-lang-detect-plugin-linguonnx (repo) |
yes | no | FOSS (Offline) | Apache-2.0 | GlotLID on ONNX. Same package as ovos-translate-plugin-linguonnx. See linguonnx Language Plugins. |
Alpha |
ovos-google-translate-plugin (repo) |
yes | yes | API (free) | Apache-2.0 (cloud service, separate Google terms) | Translate (ovos-google-translate-plugin) and detect (ovos-google-lang-detector-plugin) are separate entry-points. |
Stable |
Maturity reflects repository health (age, activity, open issues/PRs, in-repo docs), not version. See the Maturity Scale.
License and Maturity are independent axes
The License column reports what the repository itself declares. "No license file" just means no SPDX license was found, not that the code is unmature. The Maturity column reports repository health (age, activity, issues/PRs, docs). A plugin can be Mature and still ship no license file. A plugin can be Stable with a permissive license but thin docs. Do not read one column as implying the other.
Heads up: the package repo name, the pip name, and the entry-point name you put in config are not always the same. Configure plugins by their entry-point name (for example
ovos-translate-plugin-server, not the repoovos-translate-server-plugin). The names in the table above are entry-point names.
Configuring ovos-translate-plugin-server¶
If you don't set anything, the client shuffles through its built-in public-server list. It fails over to the next server whenever one errors or times out. To point it at your own ovos-translate-server instance(s), set host. Use a single URL, or a list of URLs for failover:
{
"language": {
"translation_module": "ovos-translate-plugin-server",
"detection_module": "ovos-lang-detector-plugin-server",
"ovos-translate-plugin-server": {
"host": ["https://my-nllb.example", "https://backup-nllb.example"],
"timeout": 5,
"skip_detection": false
}
}
}
-
host: a URL string or a list of URLs. When a list, the client tries each in order on failure. Omit it to use the built-in public servers (tried in random order to spread load). -
timeout: per-request timeout in seconds (default5). -
skip_detection(translator only): whentrue, the plugin skips the pre-translate/detect/{text}round-trip. The server then infers the source language directly from the/translate/{target}/{text}endpoint. This halves the request count when the server can self-detect. Defaults tofalse.
Choosing a translation / language-ID model¶
- NLLB-200 (
ovos-translate-plugin-nllb): the offline quality pick, from Meta's "No Language Left Behind" program (200 languages, mined low-resource data). Large; the trade-off is RAM and download size. - linguonnx (TigreGotico/linguonnx): torch-free ONNX routing across Marian, M2M100, NLLB, and MADLAD models, reaching 593 languages by pivoting; broadest coverage, alpha maturity, and a routing graph to reason about. Its detection side runs GlotLID, a language identifier purpose-built for low-resource languages (1,665 languages).
- fastText detection (
ovos-lang-detector-fasttext-plugin): the classic fast CPU language ID, built on fastText. Cheap and quick, weaker at separating closely related languages than GlotLID. - Cloud plugins (Google, translate-server): best quality-per-effort when text may leave the device; nothing to download, nothing authoritative to cite beyond the service.
Technical Explanation¶
OVOS provides two base classes for language processing, both in ovos_plugin_manager.templates.language: LanguageDetector and LanguageTranslator. Each is constructed with a config dict (the plugin's section from mycroft.conf), exposed as self.config.
Language Detector Interface¶
from ovos_plugin_manager.templates.language import LanguageDetector
class LanguageDetector:
def detect(self, text: str) -> str:
"""Return the single best language code (e.g. 'en')."""
def detect_probs(self, text: str) -> Dict[str, float]:
"""Return a {language_code: probability} dict."""
Language Translator Interface¶
from ovos_plugin_manager.templates.language import LanguageTranslator
class LanguageTranslator:
def translate(self, text: str, target: Optional[str] = None,
source: Optional[str] = None) -> str:
"""Abstract. Every backend implements this. Translate `text` to
`target`; if `source` is None the plugin detects it."""
@classproperty
def available_languages(cls) -> Set[str]:
"""Languages this backend supports (may be empty if unknown/dynamic)."""
Gotcha (advanced):
available_languagesis aclassproperty. Several real plugins return an empty set when the backend's language list is dynamic or unknown (for exampleovos-translate-plugin-serverandovos-google-translate-plugin). Don't assume it is populated.
Creating Your Own Plugin¶
1. Implementation Template (Translator)¶
from ovos_plugin_manager.templates.language import LanguageTranslator
class MyTranslator(LanguageTranslator):
def translate(self, text, target=None, source=None):
target = target or self.config.get("lang")
# Implement your translation logic here
return self.api.translate(text, target, source)
@property
def available_languages(self):
return {"en", "es", "fr", "de"}
2. Registration¶
Register your plugin in pyproject.toml under the correct entry-point groups. Translators use opm.lang.translate. Detectors use opm.lang.detect:
[project.entry-points."opm.lang.translate"]
my-translator = "my_package.module:MyTranslator"
[project.entry-points."opm.lang.detect"]
my-detector = "my_package.module:MyDetector"
The legacy Neon groups
neon.plugin.lang.translate/neon.plugin.lang.detectare still honoured as aliases byovos-plugin-manager(this is why a plugin likeovos-lang-detector-fasttext-pluginkeeps working), but new plugins should register under theopm.lang.*groups.
Standalone Usage¶
from ovos_plugin_manager.language import find_tx_plugins, find_lang_detect_plugins
# Translation
tx_plugins = find_tx_plugins()
translator = tx_plugins["ovos-google-translate-plugin"]()
print(translator.translate("Hello", target="es"))
# Detection
detect_plugins = find_lang_detect_plugins()
detector = detect_plugins["ovos-lang-detector-fasttext-plugin"]()
print(detector.detect("Hola, como estas?"))
Read next: Reference Overview Related: Bidirectional Translation · Contributing Translations · OpenAI-compatible LLM Backend