@dabalabs/lang 0.0.1-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +146 -0
- package/dist/dabalang.cjs +1348 -0
- package/dist/dabalang.cjs.map +1 -0
- package/dist/dabalang.d.cts +145 -0
- package/dist/dabalang.d.ts +145 -0
- package/dist/dabalang.js +1345 -0
- package/dist/dabalang.js.map +1 -0
- package/dist/dabalang.min.js +338 -0
- package/dist/dabalang.min.js.map +1 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# @dabalabs/lang
|
|
2
|
+
|
|
3
|
+
Embeddable i18n/translation widget for [dabalabs](https://dabalabs.com) projects. Drop it into any site and it detects the page's own text, translates it into whichever languages you configured from the dashboard, and shows a simple language-switcher pill row for visitors.
|
|
4
|
+
|
|
5
|
+
While you're developing locally, double-click any translated sentence to correct it in place — the correction is saved immediately and becomes the live translation for every visitor from then on. This editing UI only ever appears on a dev-looking hostname (`localhost`, `127.0.0.1`, `*.local`, `*.test`) — there's no way to trigger it once your site is deployed.
|
|
6
|
+
|
|
7
|
+
Works natively in **Plain HTML**, **React**, **Next.js**, **Vue**, **Nuxt**, **Svelte**, **SvelteKit**, **Astro**, and any modern JavaScript stack.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @dabalabs/lang
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
### Script tag (no build step)
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<div data-dabalang data-project-id="YOUR_PROJECT_ID" data-api-key="YOUR_API_KEY"></div>
|
|
21
|
+
<script src="https://unpkg.com/@dabalabs/lang/dist/dabalang.min.js"></script>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The `<div>` is where the language-switcher pills render; the rest of the page's text is what gets crawled and translated.
|
|
25
|
+
|
|
26
|
+
### npm / bundler
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { DabaLang } from "@dabalabs/lang";
|
|
30
|
+
|
|
31
|
+
new DabaLang({
|
|
32
|
+
container: "#language-switcher",
|
|
33
|
+
projectId: "YOUR_PROJECT_ID",
|
|
34
|
+
apiKey: "YOUR_API_KEY",
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Get your Project ID and API key
|
|
39
|
+
|
|
40
|
+
1. Go to your [dabalabs dashboard](https://dabalabs.com/dashboard/developer) → **Translate widgets**.
|
|
41
|
+
2. Create a translate project: pick a source language and the target languages you want to offer.
|
|
42
|
+
3. Create an API key for your domain, with `product` set to `dabalang`.
|
|
43
|
+
4. Copy the generated embed snippet.
|
|
44
|
+
|
|
45
|
+
## Options
|
|
46
|
+
|
|
47
|
+
| Option | Type | Required | Description |
|
|
48
|
+
| --- | --- | --- | --- |
|
|
49
|
+
| `container` | `string \| HTMLElement` | Yes | CSS selector or element where the language pills render. |
|
|
50
|
+
| `projectId` | `string` | Yes | Your translate project's ID. |
|
|
51
|
+
| `apiKey` | `string` | Yes | A publishable key with `product: "dabalang"`. Safe to ship in frontend source — the same trust model as Stripe.js: scoped server-side to your allowed origins. |
|
|
52
|
+
| `gatewayUrl` | `string` | No | Defaults to `https://api.dabalabs.com`. |
|
|
53
|
+
| `view` | `"modal" \| "dropdown"` | No | How the switcher presents languages: the flag-grid modal (default) or a compact dropdown anchored to the trigger. Script-tag installs can pass `data-view="dropdown"`. |
|
|
54
|
+
| `onLanguageChange` | `(langCode: string) => void` | No | Fires after a visitor switches language (the source language's own code when they pick "Original"). |
|
|
55
|
+
| `onError` | `(error: DabaLangError) => void` | No | Fires on a failed metadata fetch or translate call. Defaults to `console.error`. |
|
|
56
|
+
|
|
57
|
+
## What gets translated
|
|
58
|
+
|
|
59
|
+
Every visible text node in `<body>` is crawled by default — that's what "detect the content inside the website" means in practice; an opt-in scheme would make the widget translate nothing out of the box. To exclude a section (a code sample, a price ticker you don't want touched, anything with its own i18n already), mark it:
|
|
60
|
+
|
|
61
|
+
```html
|
|
62
|
+
<div data-dabalang-ignore>
|
|
63
|
+
This text is never crawled or translated.
|
|
64
|
+
</div>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Password fields, hidden inputs, and credit-card-autocomplete fields are always excluded, with no attribute needed.
|
|
68
|
+
|
|
69
|
+
Translation is **lazy**: a language is only translated the first time a visitor selects it, not pre-fetched for every configured language on every page load. The very first visitor to translate a given page into a given language pays the (small) live-translation latency; every subsequent visitor gets an instant cache hit.
|
|
70
|
+
|
|
71
|
+
## Correcting a translation (development only)
|
|
72
|
+
|
|
73
|
+
On `localhost` (or `127.0.0.1`, a `.local`/`.test` hostname), while a non-original language is selected, double-click any translated sentence to open a small editor next to it. Save, and:
|
|
74
|
+
|
|
75
|
+
- The correction applies immediately on your screen.
|
|
76
|
+
- It's stored against that exact source sentence for that language.
|
|
77
|
+
- Every visitor — in development or production — gets your corrected version from then on, since the point of this workflow is fixing a bad machine translation once, not maintaining a personal dev-only override.
|
|
78
|
+
|
|
79
|
+
There is no way to open this editor on a real (non-dev-looking) domain — it's a workflow safety rail for your own QA pass, not a security boundary. Manage or revert past corrections from the project's **Corrections** tab in the dashboard.
|
|
80
|
+
|
|
81
|
+
## Pre-translated languages
|
|
82
|
+
|
|
83
|
+
By default the platform translates for you. If the translation already exists, configure the language as **pre-translated** in the dashboard — it is then never machine-translated. Two shapes:
|
|
84
|
+
|
|
85
|
+
- **Your site already serves that language** (a CMS with localized pages, a localized build): give the language a path prefix and enable path routing. Pages under that prefix (`/ar/...`) are treated as already translated — the widget doesn't touch their content or spend a single translation call; it only sets `lang`/`dir`, marks the switcher, and navigates between prefixes.
|
|
86
|
+
- **You have the strings but one set of pages**: upload a map of source text → translated text. Uploaded strings are swapped in directly — no machine translation, no per-string cost — and any string your upload doesn't cover falls back to the normal pipeline, so a partial catalogue never breaks a page.
|
|
87
|
+
|
|
88
|
+
No widget change is needed either way.
|
|
89
|
+
|
|
90
|
+
## URL path routing
|
|
91
|
+
|
|
92
|
+
Optionally, languages can live under URL path prefixes — `example.com/ar/pricing` for Arabic, `example.com/pricing` for the original — configured per language from the dashboard (**Languages** tab → path prefix, plus the project-level toggle).
|
|
93
|
+
|
|
94
|
+
With it enabled, the widget:
|
|
95
|
+
|
|
96
|
+
- **Detects on load**: visiting a path under a configured prefix (`/ar/...`) applies that language immediately — no pill click needed. Un-prefixed paths serve the language marked *default* (or the original if none is).
|
|
97
|
+
- **Navigates on switch**: picking a language that has a prefix navigates to the same page under that prefix (query string and hash preserved); picking the original strips it. Languages without a prefix keep translating in place.
|
|
98
|
+
- **Never redirects on its own**: the widget only reacts to the URL it finds itself on. If you want `/` to redirect to `/ar` for Arabic-locale visitors, do that on your server/CDN — the widget will pick the language up from the path it lands on.
|
|
99
|
+
|
|
100
|
+
Your server must serve the same page under the prefixed paths (a catch-all/rewrite works fine — the widget re-translates from the path). SPAs and static hosts can map `/ar/*` to the same bundle.
|
|
101
|
+
|
|
102
|
+
## Limitations (v1)
|
|
103
|
+
|
|
104
|
+
- **Client-side only.** There's an unavoidable flash of the original-language content before JavaScript crawls and swaps in a translation — the same tradeoff every client-side-only i18n widget (Weglot, GTranslate's free tier, etc.) makes. A server-side-rendered/SEO-safe tier is not built.
|
|
105
|
+
- **No browser-language guessing.** The widget never infers a visitor's language from browser settings. Without path routing it always starts on "Original"; with path routing the URL decides.
|
|
106
|
+
- **One crawl per page load.** If your page injects new content after load (an SPA route change, infinite scroll), the newly-added text won't be picked up until you construct a fresh `DabaLang` instance or reload.
|
|
107
|
+
|
|
108
|
+
## License
|
|
109
|
+
|
|
110
|
+
MIT
|
|
111
|
+
|
|
112
|
+
## Environments
|
|
113
|
+
|
|
114
|
+
By default the widget talks to Dabalabs production. Point it at staging
|
|
115
|
+
with `env`:
|
|
116
|
+
|
|
117
|
+
```html
|
|
118
|
+
<div data-dabalang
|
|
119
|
+
data-project-id="YOUR_PROJECT_ID"
|
|
120
|
+
data-api-key="YOUR_API_KEY"
|
|
121
|
+
data-dabalang-env="staging"
|
|
122
|
+
></div>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
new DabaLang({
|
|
127
|
+
// ...
|
|
128
|
+
env: "staging",
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
| `env` | Gateway |
|
|
133
|
+
|---|---|
|
|
134
|
+
| omitted | `https://api.dabalabs.com` |
|
|
135
|
+
| `"production"` | `https://api.dabalabs.com` |
|
|
136
|
+
| `"staging"` | `https://api-staging.dabalabs.com` |
|
|
137
|
+
|
|
138
|
+
Production is the default in every direction — an embed that says nothing
|
|
139
|
+
about its environment is a live site, so staging has to be asked for by
|
|
140
|
+
name. An unrecognised value warns in the console and falls back to
|
|
141
|
+
production rather than throwing, so a typo cannot take a customer's page
|
|
142
|
+
down.
|
|
143
|
+
|
|
144
|
+
`gatewayUrl` still overrides `env` when both are given: it is the only
|
|
145
|
+
option that can name a host neither tier covers (a self-hosted
|
|
146
|
+
deployment, a local gateway).
|