OVOS Localize: The zero-maintenance translation platform on GitHub
Claude (Anthropic) (Lead Author)
OVOS Contributor
Co-authors:
JarbasAl
Translating a voice assistant is a different job than translating an app. For instance, an app string like "Save" becomes "Speichern" in German, and you're done. A voice assistant line like turn {brightness} the {light_name} is a training sentence for an intent classifier. Get it wrong and the skill stops recognizing your language at all. OVOS Localize is a translation platform built for that harder job: instead of guessing at bare strings, translators see the code that uses each line and what it means. It runs on GitHub Pages and GitHub Actions, so we operate no infrastructure of our own. A GitHub account is all a translator needs to sign in.
Why voice assistant strings are harder to translate
Take that light-switching intent again:
turn {brightness} the {light_name}
To recognise German speakers saying this, you need roughly ten natural variations, and every one must preserve {brightness} and {light_name} exactly, because those are runtime slots mapped to real values.
Or a dialog line:
It is {temp} degrees {condition} in {location}
That's what the assistant says out loud. You need at least two variants, so it doesn't sound like a broken record, and the translation has to work grammatically for every value {condition} can take: "sunny", "overcast", "raining".
OVOS previously used GitLocalize, which showed translators files line by line with no context: no explanation of what triggered each line or what the slots meant. The result was translations that were grammatically fine but functionally broken: missing variables that crash skill responses, intent files with a single sentence that barely trains a classifier, dialog files that repeat because they only have one variant. It was also a hosted third-party dependency: community translation data living on someone else's platform.
Built entirely on GitHub
OVOS Localize skips custom infrastructure and uses what GitHub already provides:
| What we need | GitHub equivalent |
|---|---|
| Web server / CDN | GitHub Pages (free, global) |
| Database | Git-tracked JSON files |
| Authentication | GitHub App tokens (scoped, ephemeral) |
| Background jobs | GitHub Actions |
| Form submission API | GitHub Issues with machine-readable bodies |
| Bot identity | GitHub App (ovos-localize[bot]) |
| Audit log | Pull request history |
The result is a static single-page app on GitHub Pages, reading JSON committed to the same repo. Six GitHub Actions workflows run it:
add_skillregisters a new skill repoenable_new_languageopens a language for translationsubmit_translationturns a contribution into a pull requestfix_lang_coderepairs non-canonical locale directory namespoll_merged_fixeswatches for merged fixes and keeps the dashboard honestupdate_datarebuilds all editor and dataset files daily
No Docker, no server to patch, no cloud bill.
Submitting a translation opens a GitHub Issue. submit_translation reads a machine-readable block in the issue body, mints a short-lived token scoped only to the target skill repo, creates a branch, commits the translation, opens a PR, and closes the issue. The skill maintainer reviews the PR from there. You need nothing but a GitHub account.
How it works
The dashboard is a heatmap: every registered OVOS skill against dozens of languages, colour-coded by translation coverage. Dark means complete; light means someone needs to help.
The editor is a three-panel view: source on the left, your translation in the middle, and a context card on the right. That context card is the key idea: it shows the Python handler that uses the file, the method source, the slots it expects, and what the skill says when it speaks these lines. You always see the context, not just the isolated line.
Those context cards come from Python AST (Abstract Syntax Tree) analysis, a structural parse of the code rather than a text search. When the data pipeline sees self.speak_dialog("query_weather") in a skill method, it connects that dialog file to that handler and stores the source, so every file has provenance and every slot has a meaning.
Validation runs before you submit. OVOS Localize ships a dedicated parser and validator for each of the six locale file types it understands, .intent, .voc, .dialog, .entity, .rx and .value:
.intentfiles need at least 10 sentences after alternative-syntax expansion, must preserve every source{slot}, and must clear a lexical diversity score of 0.25 (the ratio of unique three-word phrases to all three-word phrases across the training lines), so ten near-identical lines don't pass as ten examples..dialogfiles need at least 2 variants and must preserve{variable}substitutions exactly. Extra or missing variables are hard errors..entityfiles need at least 5 examples for reliable slot filling..vocfiles are keyword lists: non-empty, with entries flagged if they look like whole sentences..rxregexes must compile and keep their named groups;.valuefiles must stay validdisplay,valueCSV with the system value preserved.
If a translation trips any of these rules, you see it before you submit, not after a skill breaks in production.
The Issues view
Scanning every registered skill surfaces problems beyond missing translations, in two buckets:
- Bare language code warnings: skills with locale directories named
euordainstead of the canonicaleu-ESorda-DK. These are unambiguous in OVOS context (Basque is alwayseu-ES, Danish alwaysda-DK), but they break coverage stats and confuse tooling. Since the fix is mechanical, we automated it: the "Request Auto-Fix" button opens an issue with aFIX_LANG_CODE_METAblock,fix_lang_codereads it, renames the directories using a scoped token, and opens a PR on the skill. - Validation rule violations: intent files with too few or too-similar training examples, dialog files missing required variables, entity files below the example threshold. These need a human, so the "Report" button opens a pre-filled issue in the skill's own repository with a markdown table of exactly which files and lines are affected.
Your translations become open data
Every translation contributed through OVOS Localize also feeds an open ML dataset. The same daily pipeline that builds the editor data generates six dataset formats:
- Intent classification: (utterance, skill, intent) triples for training classifiers
- Parallel translation: English to target-language pairs for translation model fine-tuning
- Slot filling: templates, slot names and entity values for Named Entity Recognition (NER) training
- Response pairs: (utterance, response) pairs for dialogue model training
- TTS corpus: deduplicated dialog sentences for speech synthesis training
- Skill metadata: multilingual skill names and descriptions for discovery
These rebuild daily, split at 100 MB for GitHub compatibility, and are written to data/datasets/ in the repo in HuggingFace Datasets layout. The format is ready; no hosted dataset has been published from it yet. The more languages get translated, the richer this open corpus becomes.
Get started
- Translate skills at openvoiceos.github.io/ovos-localize. Filter by your language on the dashboard, pick a skill with low coverage, and contribute.
- Check the Issues view for your language. Low-diversity intent files and missing dialog variants are easy fixes for a native speaker.
- Add your skill by opening a PR to add your
org/repotoskills.txt. The pipeline picks it up on the next daily run. - Request a new language via the "Can't find your language?" link in the language selector.
- Fork it. The platform is a repository: clone it, point it at your own skill list, and run your own instance.
For the technical architecture (GitHub App token handling, the AST context extraction, the full validation rule set) see the OVOS Localize whitepaper. Bugs and questions go to the issue tracker.
Transparency note: This blog post was written by Claude (claude-sonnet-4-6, Anthropic), the same AI that built the majority of OVOS Localize. Casimiro (jarbas) directed the project, set the requirements, reviewed all code, and is responsible for the human judgement calls throughout. The platform itself (parsers, validators, AST analysis, GitHub workflows, the SPA) was developed in close collaboration between Miro and Claude over many sessions. We think it's worth being upfront about that.
This work is part of the OpenVoiceOS From Beta to Breakthrough milestone, funded through the NGI0 Commons Fund, a fund established by NLnet with financial support from the European Commission's Next Generation Internet programme, under the aegis of DG Communications Networks, Content and Technology under grant agreement No 101135429. Additional funding is made available by the Swiss State Secretariat for Education, Research and Innovation (SERI).
Help us build voice for everyone
OpenVoiceOS is a mission as much as it is software. If you believe voice assistants should be open, inclusive, and user-controlled:
- 💸 Donate: help fund development, infrastructure, and legal protection.
- 📣 Contribute open data: share voice samples and transcriptions under open licenses.
- 🌍 Translate: help make OVOS accessible in every language.
We're building this for people, not for profit. Support the project here