Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bhasha · भाषा

A shared vernacular layer for civic data dashboards — drop-in, zero-backend, client-side. One small script gives any dashboard a language switcher across Indian languages without ever translating the data.

Built to close the single biggest gap in a portfolio of India public-goods dashboards: they were English- and GIS-literate only. bhasha is the reusable fix — add it once per app instead of rebuilding i18n every time.

Live demo: ashwask.github.io/bhasha — switch to हिन्दी / ಕನ್ನಡ (bundled, offline) or தமிழ் / తెలుగు / मराठी / বাংলা (machine fallback). Or open standalone.html locally — it's fully self-contained (no server).


The one rule: faithful data

bhasha translates UI chrome and explanatory prose — labels, headings, guidance. It never touches authoritative data: place names, numbers, units, sources. Those are shown exactly as published.

This is deliberate. Translating "Bengaluru → ಬೆಂಗಳೂರು" or a sourced figure would breach faithful presentation — the value the whole civic-data project rests on. bhasha enforces the line in code: nothing is translated unless you opt it in, and protected elements are skipped no matter what.

  • Translate this: wrap it in data-bhasha<span data-bhasha>Air Quality</span>
  • Never translate this: wrap it in bhasha-keep / data-bhasha-keep<span class="bhasha-keep">182 µg/m³</span>

Integrate (single-file dashboard)

<script src="bhasha.js"></script>
<script>
  Bhasha.init({
    dict: {                       // your bundled, offline dictionary
      hi: { "Air Quality": "वायु गुणवत्ता", /* … */ },
      kn: { "Air Quality": "ವಾಯು ಗುಣಮಟ್ಟ", /* … */ }
    }
  });
</script>

Then tag your UI strings with data-bhasha and your data cells with class="bhasha-keep". That's the whole integration.

Framework apps (Svelte / React / Astro)

Call Bhasha.init(...) after mount, pointing root at your app node. Re-run _collect() semantics by re-initialising after route changes, or use mode:'opt-out' (below) so you don't have to tag every string.


Two modes

Mode What gets translated Use when
opt-in (default) only [data-bhasha] elements safest — data is protected unless you forget to tag it
opt-out all text under root except keepSelector fastest to adopt on an existing page; you protect data instead of tagging prose

In opt-out, protect data with class="bhasha-keep", [data-value], <code>, etc. (configurable via keepSelector).


Translation sources (in priority order)

  1. Bundled dictionary (dict) — hand-authored, high quality, works fully offline. Recommended for your core UI strings and your priority languages.
  2. translate(text, lang) hook — optional async fallback for the long tail. Results are cached in localStorage (each string leaves the browser at most once) and marked with a dotted underline so machine output is honest. Ships with a keyless MyMemory adapter; omit it for a fully-offline build.
  3. English — if neither has it, the string stays in English. No garbling, ever.

Conversational access (optional)

Set an ai(question, lang, contextText) hook to add an "Ask in your language" panel — the PDGI "humans-in-the-loop" pattern. The user asks in any language; the model answers in that language, grounded only in the page's canonical data (it explains the values, it doesn't restate or translate them). A Claude adapter is included.

Security: never ship an API key in client-side code. Point the adapter at a thin serverless proxy (Cloudflare Worker / Pages Function) that holds the key. The demo leaves it unset, so the panel is inert until you wire a proxy.


API

Bhasha.init({
  languages,      // [{code, native}]  — defaults to en/hi/kn/ta/te/mr/bn
  dict,           // { lang: { "English source": "translated" } }
  translate,      // async (text, lang) => string | null   (optional)
  ai,             // async (q, lang, contextText) => string (optional)
  mode,           // 'opt-in' (default) | 'opt-out'
  root,           // default document.body
  selector,       // opt-in target, default '[data-bhasha]'
  keepSelector,   // never-translate, default protects data cells/code
  position,       // 'bottom-right' (default) | 'bottom-left' | 'top-…'
  defaultLang,    // 'en'
  note            // faithful-data disclosure shown in the panel
});
Bhasha.setLang('hi');   // programmatic switch; persists to localStorage

Mark the region the AI should read as context with data-bhasha-context.


Adopting across the portfolio

Each single-file dashboard (Bhoomi, rtpv-agropv-explorer, india-energy-story, oaq-health-burden, urban-thesis-tracker …) needs three things:

  1. <script src="bhasha.js"> + a small dict for its ~20–40 UI strings,
  2. data-bhasha on those strings,
  3. bhasha-keep on the data cells.

Framework apps (village-espresso, IndiaTemperatureMap) use mode:'opt-out' and protect the map/data layers.

Adoptions in the wild

Dashboard Type Scope Status
Bhoomi environmental map + climate-risk full UI (labels, controls, guidance) ✅ merged — English / हिन्दी / ಕನ್ನಡ
india-energy-story data narrative nav + section structure (body prose stays English — data-dense) ✅ merged — English / हिन्दी / ಕನ್ನಡ

What the two show: dashboards translate almost fully; data-dense narratives translate their chrome + structure, and the body is better served by the conversational "ask in your language" layer than by translating figure-laden prose. Either way, no number, place name or source is ever altered.

Before shipping to users: bundled dictionaries are only as good as their authoring. The Hindi/Kannada strings in these adoptions are authored + machine-verified but not yet native-speaker reviewed — do that review before a dashboard's vernacular mode is called "done".


PDGI

bhasha is itself built to the principles it helps others meet: client-side (privacy — no data leaves the browser by default), open format, no lock-in, MIT. It moves the "grassroots and reaching the divide-affected" row from ⛳ toward ✅ — conversational and vernacular access without touching the authoritative data. Framework: pdgi.org.

MIT © 2026 Ashwin S Kulkarni

About

A shared, drop-in, zero-backend vernacular layer for India civic dashboards — translate the UI into Indian languages without ever translating the data.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages