@lingo.dev/cli 1.0.0
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/dist/bin.js +108 -0
- package/dist/flush-telemetry.js +38 -0
- package/dist/index.js +3 -0
- package/dist/renderer-DvB06WWF.js +1533 -0
- package/dist/server-BxEBM9NU.js +847 -0
- package/dist/update-C-JdpZwG.js +816 -0
- package/guides/api.md +54 -0
- package/guides/index.md +10 -0
- package/guides/migrate.md +34 -0
- package/guides/setup.md +111 -0
- package/package.json +55 -0
- package/skills/lingo/SKILL.md +11 -0
package/guides/api.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# API Reference – @lingo.dev/react
|
|
2
|
+
|
|
3
|
+
## Hooks
|
|
4
|
+
- `useLingo()` → returns Lingo with translation + formatting helpers.
|
|
5
|
+
|
|
6
|
+
## Translation helpers (context required)
|
|
7
|
+
```tsx
|
|
8
|
+
l.text(source, { context, values? })
|
|
9
|
+
l.jsx(source, { context, tags?, values? })
|
|
10
|
+
l.plural(count, { one, other, zero?, two?, few?, many? }, { context })
|
|
11
|
+
l.select(value, { ...forms, other }, { context })
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Examples:
|
|
15
|
+
```tsx
|
|
16
|
+
l.text("Save", { context: "Form submit button" })
|
|
17
|
+
l.text("Hello, {name}!", { context: "Dashboard welcome", values: { name } })
|
|
18
|
+
l.jsx("Read <link>docs</link>", { context: "Footer link", tags: { link: c => <a href="/docs">{c}</a> } })
|
|
19
|
+
l.plural(items, { one: "# item", other: "# items" }, { context: "Cart count" })
|
|
20
|
+
l.select(role, { admin: "Admin", user: "User", other: "Guest" }, { context: "Nav label" })
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Context rules:
|
|
24
|
+
1) Always required on text/jsx/plural/select.
|
|
25
|
+
2) Describes where/how the string is used ("Checkout CTA", "Toast error").
|
|
26
|
+
3) Same source + different context = different translation key.
|
|
27
|
+
|
|
28
|
+
## Formatting helpers (no context needed)
|
|
29
|
+
```tsx
|
|
30
|
+
l.num(1234567) // "1,234,567"
|
|
31
|
+
l.currency(29.99, "USD") // "$29.99"
|
|
32
|
+
l.percent(0.156) // "16%"
|
|
33
|
+
l.date(new Date()) // locale date
|
|
34
|
+
l.time(new Date()) // locale time
|
|
35
|
+
l.relative(-1, "day") // "yesterday"
|
|
36
|
+
l.list(["A","B","C"]) // "A, B, and C"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Components / HOCs (Next.js Pages Router)
|
|
40
|
+
- `withLingoApp(App)` → wraps _app.tsx; sets dir for RTL; warns if page missing withLingoProps.
|
|
41
|
+
- `withLingoProps({ route, handler? })` → load route-specific messages in getStaticProps/SSR.
|
|
42
|
+
- `withLingoPaths(handler)` → expands getStaticPaths across locales (fallback: "blocking").
|
|
43
|
+
- `useLocaleSwitch()` → sets NEXT_LOCALE cookie + router.push with locale.
|
|
44
|
+
- `LingoHead` → hreflang SEO tags.
|
|
45
|
+
|
|
46
|
+
## Files generated by CLI
|
|
47
|
+
- `locales/<locale>.jsonc` – source/translated messages with @context + @src metadata.
|
|
48
|
+
- `lingo.d.ts` – TypeScript augmentation with exact context unions and required values.
|
|
49
|
+
|
|
50
|
+
## Required patterns
|
|
51
|
+
- Every page using translations must export withLingoProps({ route }).
|
|
52
|
+
- Every translation call must include context.
|
|
53
|
+
- Always run `npx @lingo.dev/cli check` before finishing.
|
|
54
|
+
```
|
package/guides/index.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Lingo Guides
|
|
2
|
+
|
|
3
|
+
Use `npx @lingo.dev/cli guide <name>` to view a guide.
|
|
4
|
+
|
|
5
|
+
Available guides:
|
|
6
|
+
- `setup` – first-time setup for @lingo.dev/react (Next.js Pages Router focus, works for React too)
|
|
7
|
+
- `api` – API reference for `l.text`, `l.jsx`, `l.plural`, `l.select`, formatting helpers
|
|
8
|
+
- `migrate` – migrate from next-intl, react-intl, i18next, lingui to @lingo.dev/react
|
|
9
|
+
|
|
10
|
+
Always finish workflows with `npx @lingo.dev/cli check` (or `pnpm lingo check`) and expect 0 issues.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Migration Guide – to @lingo.dev/react
|
|
2
|
+
|
|
3
|
+
## Key differences
|
|
4
|
+
- No manual keys. Use source text + required context: `l.text("Save", { context: "Form button" })`.
|
|
5
|
+
- Automatic hash keys; per-route splitting via withLingoProps({ route }).
|
|
6
|
+
- TypeScript enforces context and required values after `lingo extract`.
|
|
7
|
+
|
|
8
|
+
## API mapping
|
|
9
|
+
| Pattern | next-intl | react-intl | i18next | @lingo.dev/react |
|
|
10
|
+
|------------------|----------------------------|---------------------------------|---------------------------|------------------------------------------------------|
|
|
11
|
+
| Plain text | `t("key")` | `formatMessage({ id })` | `t("key")` | `l.text("source", { context: "..." })` |
|
|
12
|
+
| With values | `t("key", { name })` | `formatMessage({ id }, { name })`| `t("key", { name })` | `l.text("Hello, {name}", { context: "...", values: { name } })` |
|
|
13
|
+
| Rich text | `t.rich("key", { link })`| `<FormattedMessage components>` | `<Trans components>` | `l.jsx("Click <link>here</link>", { context: "...", tags: { link } })` |
|
|
14
|
+
| Plurals | ICU in JSON | `<FormattedPlural>` | ICU in JSON | `l.plural(count, { one: "# item", other: "# items" }, { context: "..." })` |
|
|
15
|
+
| Provider | `NextIntlProvider` | `IntlProvider` | `I18nextProvider` | `withLingoApp` (wraps LingoProvider) |
|
|
16
|
+
| Hook | `useTranslations()` | `useIntl()` | `useTranslation()` | `useLingo()` |
|
|
17
|
+
|
|
18
|
+
## Steps
|
|
19
|
+
1) Install @lingo.dev/react (and @lingo.dev/react-next for Next.js). Keep old lib temporarily.
|
|
20
|
+
2) Wrap root with withLingoApp (and keep old provider during migration if needed).
|
|
21
|
+
3) Per file:
|
|
22
|
+
- Replace old hook with `useLingo()`.
|
|
23
|
+
- Replace calls using mapping above.
|
|
24
|
+
- Add `withLingoProps({ route })` to every page using translations.
|
|
25
|
+
4) Run `npx @lingo.dev/cli extract`.
|
|
26
|
+
5) Run `npx @lingo.dev/cli localize --target-locale <locale>`.
|
|
27
|
+
6) Run `npx @lingo.dev/cli check` (expect 0 issues).
|
|
28
|
+
7) Remove old provider, message files, and dependencies once all pages migrated.
|
|
29
|
+
|
|
30
|
+
## Gotchas
|
|
31
|
+
- Old JSON translation files can’t be reused directly (keys differ). Re-translate via `localize`.
|
|
32
|
+
- Keep contexts specific (e.g., "Toolbar Save", "Form Save").
|
|
33
|
+
- Dynamic routes still need withLingoPaths for locale expansion.
|
|
34
|
+
```
|
package/guides/setup.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Setup Guide – @lingo.dev/react (Next.js Pages Router)
|
|
2
|
+
|
|
3
|
+
Philosophy: the agent writes i18n code; context is required on every call; route is required on every page loader. Finish with `npx @lingo.dev/cli check`.
|
|
4
|
+
|
|
5
|
+
## 1) Install packages
|
|
6
|
+
Detect package manager from lockfile. Example (pnpm):
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @lingo.dev/react @lingo.dev/react-next
|
|
9
|
+
pnpm add -D @lingo.dev/cli
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## 2) Configure Next.js i18n
|
|
13
|
+
`next.config.ts`
|
|
14
|
+
```ts
|
|
15
|
+
import type { NextConfig } from "next";
|
|
16
|
+
|
|
17
|
+
const nextConfig: NextConfig = {
|
|
18
|
+
i18n: {
|
|
19
|
+
locales: ["en", "es"],
|
|
20
|
+
defaultLocale: "en",
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default nextConfig;
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 3) Wrap _app.tsx
|
|
28
|
+
```tsx
|
|
29
|
+
// pages/_app.tsx
|
|
30
|
+
import type { AppProps } from "next/app";
|
|
31
|
+
import { withLingoApp, LingoHead } from "@lingo.dev/react-next/pages/client";
|
|
32
|
+
|
|
33
|
+
export default withLingoApp(function App({ Component, pageProps }: AppProps) {
|
|
34
|
+
return (
|
|
35
|
+
<>
|
|
36
|
+
<LingoHead />
|
|
37
|
+
<Component {...pageProps} />
|
|
38
|
+
</>
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
- withLingoApp wires LingoProvider, sets dir for RTL, warns if a page lacks withLingoProps.
|
|
43
|
+
- LingoHead adds hreflang tags.
|
|
44
|
+
|
|
45
|
+
## 4) Add withLingoProps to every page
|
|
46
|
+
Route = file path without extension (relative to repo root).
|
|
47
|
+
```tsx
|
|
48
|
+
import { withLingoProps } from "@lingo.dev/react-next/pages/server";
|
|
49
|
+
export const getStaticProps = withLingoProps({ route: "src/pages/index" });
|
|
50
|
+
```
|
|
51
|
+
Dynamic routes also add withLingoPaths:
|
|
52
|
+
```tsx
|
|
53
|
+
import { withLingoPaths } from "@lingo.dev/react-next/pages/server";
|
|
54
|
+
export const getStaticPaths = withLingoPaths(async () =>
|
|
55
|
+
getPosts().then((posts) => posts.map((p) => ({ params: { slug: p.slug } })))
|
|
56
|
+
);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 5) Wrap strings with useLingo
|
|
60
|
+
```tsx
|
|
61
|
+
import { useLingo } from "@lingo.dev/react";
|
|
62
|
+
|
|
63
|
+
const l = useLingo();
|
|
64
|
+
<h1>{l.text("Welcome to Acme", { context: "Hero heading" })}</h1>
|
|
65
|
+
<p>{l.text("The best tool for teams.", { context: "Hero subheading" })}</p>
|
|
66
|
+
<button>{l.text("Get started", { context: "Hero CTA" })}</button>
|
|
67
|
+
```
|
|
68
|
+
Context is REQUIRED on l.text/l.jsx/l.plural/l.select.
|
|
69
|
+
|
|
70
|
+
### API cheatsheet
|
|
71
|
+
- `l.text(source, { context, values? })`
|
|
72
|
+
- `l.jsx(source, { context, tags?, values? })`
|
|
73
|
+
- `l.plural(count, forms, { context })`
|
|
74
|
+
- `l.select(value, forms, { context })`
|
|
75
|
+
- Formatting: `l.num`, `l.currency`, `l.percent`, `l.date`, `l.time`, `l.relative`, `l.list`
|
|
76
|
+
|
|
77
|
+
## 6) Locale switcher
|
|
78
|
+
```tsx
|
|
79
|
+
import { useLocaleSwitch } from "@lingo.dev/react-next/pages/client";
|
|
80
|
+
import { useRouter } from "next/router";
|
|
81
|
+
|
|
82
|
+
const switchLocale = useLocaleSwitch();
|
|
83
|
+
const { locale, locales } = useRouter();
|
|
84
|
+
<select value={locale} onChange={(e) => switchLocale(e.target.value)}>
|
|
85
|
+
{locales?.map((loc) => <option key={loc}>{loc}</option>)}
|
|
86
|
+
</select>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## 7) Extract
|
|
90
|
+
```bash
|
|
91
|
+
npx @lingo.dev/cli extract # or pnpm lingo extract
|
|
92
|
+
```
|
|
93
|
+
Generates `locales/en.jsonc` + `lingo.d.ts`. After this, TS enforces context + values.
|
|
94
|
+
|
|
95
|
+
## 8) Translate
|
|
96
|
+
```bash
|
|
97
|
+
npx @lingo.dev/cli localize --target-locale es
|
|
98
|
+
```
|
|
99
|
+
Writes `locales/es.jsonc`.
|
|
100
|
+
|
|
101
|
+
## 9) Verify
|
|
102
|
+
```bash
|
|
103
|
+
npx @lingo.dev/cli check
|
|
104
|
+
```
|
|
105
|
+
0 issues = done.
|
|
106
|
+
|
|
107
|
+
## Rules to remember
|
|
108
|
+
- Context required on every translation call.
|
|
109
|
+
- Route required on every withLingoProps.
|
|
110
|
+
- Always finish with `npx @lingo.dev/cli check`.
|
|
111
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lingo.dev/cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"lingo": "./dist/bin.js"
|
|
7
|
+
},
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"skills",
|
|
15
|
+
"guides"
|
|
16
|
+
],
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.76",
|
|
19
|
+
"@babel/parser": "^7.29.0",
|
|
20
|
+
"@babel/traverse": "^7.29.0",
|
|
21
|
+
"@clack/prompts": "^0.11.0",
|
|
22
|
+
"@effect/cli": "^0.73.0",
|
|
23
|
+
"@effect/platform": "^0.94.1",
|
|
24
|
+
"@effect/platform-node": "^0.104.0",
|
|
25
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
26
|
+
"@supabase/supabase-js": "^2.99.1",
|
|
27
|
+
"cfonts": "^3.3.1",
|
|
28
|
+
"ci-info": "^4.4.0",
|
|
29
|
+
"effect": "^3.19.0",
|
|
30
|
+
"jsonc-parser": "^3.3.1",
|
|
31
|
+
"log-update": "^7.2.0",
|
|
32
|
+
"picocolors": "^1.1.1",
|
|
33
|
+
"posthog-node": "^5.28.2",
|
|
34
|
+
"semver": "^7.7.4",
|
|
35
|
+
"zod": "^4.0.0",
|
|
36
|
+
"@lingo.dev/spec": "1.0.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@babel/types": "^7.29.0",
|
|
40
|
+
"@types/babel__traverse": "^7.28.0",
|
|
41
|
+
"@types/node": "^25.5.0",
|
|
42
|
+
"@types/semver": "^7.7.1",
|
|
43
|
+
"tsdown": "^0.12.5",
|
|
44
|
+
"tsx": "^4.19.0",
|
|
45
|
+
"typescript": "^5.8.2",
|
|
46
|
+
"vitest": "^4.0.18"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsdown",
|
|
50
|
+
"typecheck": "tsc --noEmit",
|
|
51
|
+
"test": "vitest run",
|
|
52
|
+
"cli": "node --import tsx/esm src/bin.ts",
|
|
53
|
+
"dev": "tsdown && node dist/bin.js"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lingo
|
|
3
|
+
description: >
|
|
4
|
+
Set up, migrate, or maintain internationalization using @lingo.dev/react.
|
|
5
|
+
Use when the user asks about i18n, localization, translations, multi-language support,
|
|
6
|
+
adding a new locale, translating strings, or migrating from another i18n library.
|
|
7
|
+
user-invocable: true
|
|
8
|
+
argument-hint: "[add <locale>, migrate from <library>, or blank]"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
Run `npx @lingo.dev/cli guide` to read the guides (setup, api, migrate).
|