shallok 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +72 -2
- package/dist/index.js +52324 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -4
- package/skills/astro-localization-and-translation-i18n/SKILL.md +164 -0
- package/skills/astro-localization-and-translation-i18n/references/astro-i18n.md +40 -0
- package/skills/astro-localization-and-translation-i18n/references/extraction.md +29 -0
- package/skills/astro-localization-and-translation-i18n/references/translation.md +45 -0
- package/skills/astro-localization-and-translation-i18n/references/versioning.md +57 -0
- package/skills/expo-localization-and-translation-i18n/SKILL.md +169 -0
- package/skills/expo-localization-and-translation-i18n/references/expo-localization.md +46 -0
- package/skills/expo-localization-and-translation-i18n/references/extraction.md +29 -0
- package/skills/expo-localization-and-translation-i18n/references/translation.md +45 -0
- package/skills/expo-localization-and-translation-i18n/references/versioning.md +57 -0
- package/skills/localization-and-translation-i18n/SKILL.md +173 -0
- package/skills/localization-and-translation-i18n/references/extraction.md +29 -0
- package/skills/localization-and-translation-i18n/references/frameworks.md +40 -0
- package/skills/localization-and-translation-i18n/references/translation.md +45 -0
- package/skills/localization-and-translation-i18n/references/versioning.md +57 -0
- package/skills/localize-app/SKILL.md +80 -0
- package/skills/localize-app/references/extraction.md +29 -0
- package/skills/localize-app/references/frameworks.md +25 -0
- package/skills/localize-app/references/translation.md +45 -0
- package/skills/localize-app/references/versioning.md +57 -0
- package/skills/nextjs-localization-and-translation-i18n/SKILL.md +166 -0
- package/skills/nextjs-localization-and-translation-i18n/references/extraction.md +29 -0
- package/skills/nextjs-localization-and-translation-i18n/references/next-intl.md +63 -0
- package/skills/nextjs-localization-and-translation-i18n/references/translation.md +45 -0
- package/skills/nextjs-localization-and-translation-i18n/references/versioning.md +57 -0
- package/skills/react-localization-and-translation-i18n/SKILL.md +266 -0
- package/skills/react-localization-and-translation-i18n/references/extraction.md +29 -0
- package/skills/react-localization-and-translation-i18n/references/react-i18next.md +47 -0
- package/skills/react-localization-and-translation-i18n/references/translation.md +45 -0
- package/skills/react-localization-and-translation-i18n/references/versioning.md +57 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Per-Key Versioning & Context Reference
|
|
2
|
+
|
|
3
|
+
## Canonical Source Catalog (`localization_base/`)
|
|
4
|
+
The canonical catalog is the single source of truth for all active and obsolete keys, including their cryptographic content hashes and version counters.
|
|
5
|
+
|
|
6
|
+
### Structure of a Canonical Entry
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"checkout.pay_now": {
|
|
10
|
+
"key": "checkout.pay_now",
|
|
11
|
+
"content": "Pay now",
|
|
12
|
+
"context": "Primary action button on checkout screen to trigger payment modal",
|
|
13
|
+
"relative_file_path": "src/components/checkout.tsx",
|
|
14
|
+
"occurrences": [
|
|
15
|
+
{
|
|
16
|
+
"relative_file_path": "src/components/checkout.tsx",
|
|
17
|
+
"line": 42,
|
|
18
|
+
"column": 12
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"last_updated_at": "2026-10-19T10:00:00.000Z",
|
|
22
|
+
"key_version": 1,
|
|
23
|
+
"content_hash": "sha256:...",
|
|
24
|
+
"status": "active"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Context Enrichment by AI Agents
|
|
30
|
+
1. When strings are extracted via `localize extract`, the CLI provides baseline AST context (e.g. `JSX text in <button> (in App <button>)`).
|
|
31
|
+
2. The AI Agent analyzes the source code, component hierarchy, and user flow, and enriches the `context` with semantic clarity:
|
|
32
|
+
- CLI method: `localize context set <key> "<semantic_description>"`
|
|
33
|
+
- Direct edit: Update `"context"` in `localization_base/<source_locale>.json`.
|
|
34
|
+
3. **Preservation Guarantee**:
|
|
35
|
+
Shallok's reconciliation algorithm (`reconcileCanonicalCatalog`) checks if a key already has an enriched context. Unless the source code introduces an explicit inline comment (`{/* context: ... */}`), the AI agent's enriched context is **strictly preserved** across all future extractions and will not be overwritten by generic AST node descriptions.
|
|
36
|
+
|
|
37
|
+
## Reconciliation & Versioning Rules
|
|
38
|
+
1. **New Key**: Initialized at `key_version = 1`, `status = "active"`.
|
|
39
|
+
2. **Unchanged Content & Context**: `key_version` and `last_updated_at` remain unchanged.
|
|
40
|
+
3. **Modified Source Content**: `key_version` increments by 1; `last_updated_at` is updated.
|
|
41
|
+
4. **File Move / Occurrence Change**: Path and occurrence lines are updated; `key_version` does NOT increment.
|
|
42
|
+
5. **Key Removed from Source**: Marked `status = "obsolete"`; preserved in catalog for historical retention.
|
|
43
|
+
6. **Key Reintroduced**: Reactivated as `"active"`.
|
|
44
|
+
|
|
45
|
+
## Stale Detection in Locale Catalogs
|
|
46
|
+
In `messages/<locale>.json`, each entry records:
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"checkout.pay_now": {
|
|
50
|
+
"value": "ಈಗ ಪಾವತಿಸಿ",
|
|
51
|
+
"source_version": 1,
|
|
52
|
+
"translated_at": "2026-10-19T10:05:00.000Z",
|
|
53
|
+
"status": "translated"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
A translation is **stale** when `entry.source_version < canonicalEntry.key_version`. Stale entries retain their existing translated value for reference until the AI agent updates them.
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nextjs-localization-and-translation-i18n
|
|
3
|
+
description: Next.js-specific localization and translation workflow using next-intl and Shallok CLI (shallok). Covers App Router and Pages Router, Server and Client Components, routing middleware, context enrichment, direct agent translation without external API keys, runtime bundle compilation, and validation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Next.js Localization & Translation Skill (`next-intl`)
|
|
7
|
+
|
|
8
|
+
Use this skill when asked to add, configure, update, or audit localization in **Next.js applications** (Next.js 13, 14, 15+ App Router or Pages Router).
|
|
9
|
+
|
|
10
|
+
## Two Ways Developers Use Shallok
|
|
11
|
+
|
|
12
|
+
1. **Via CLI (`npx shallok init`)**: The developer runs `npx shallok init` in their project. Shallok initializes the catalogs, installs `shallok` into `devDependencies`, and adds this skill directly into `.agents/skills/` and `skills/`.
|
|
13
|
+
2. **Direct Skill Installation**: The developer installs or links this skill into their AI coding agent and directly asks: *"Add localization to this application"* or *"Translate into Kannada and Hindi"*.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Agent Step 0: Verify & Install Shallok CLI
|
|
18
|
+
|
|
19
|
+
**Before executing any localization commands, you (the AI Agent) MUST verify that `shallok` is available:**
|
|
20
|
+
|
|
21
|
+
1. Check `package.json` for `"shallok"` in `devDependencies` or run:
|
|
22
|
+
```bash
|
|
23
|
+
npx shallok --version
|
|
24
|
+
```
|
|
25
|
+
2. **If `shallok` is NOT installed, install it immediately** using the project's package manager:
|
|
26
|
+
- If `pnpm-lock.yaml` exists: `pnpm add -D shallok`
|
|
27
|
+
- If `yarn.lock` exists: `yarn add -D shallok`
|
|
28
|
+
- If `bun.lockb` / `bun.lock` exists: `bun add -d shallok`
|
|
29
|
+
- Otherwise: `npm install -D shallok`
|
|
30
|
+
*(Alternatively, run commands directly via `npx shallok <command>`)*
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Architecture & Agent Role
|
|
35
|
+
|
|
36
|
+
Shallok pairs a deterministic AST CLI (`shallok`) with **the AI Agent as the semantic translator and context enricher**:
|
|
37
|
+
|
|
38
|
+
1. **The CLI (`shallok`)** handles deterministic tasks:
|
|
39
|
+
- Scaffolds Next.js configuration files: `src/i18n/routing.ts` and `src/i18n/request.ts`.
|
|
40
|
+
- AST parses Next.js JSX/TSX components (`shallok extract`).
|
|
41
|
+
- Replaces user-facing strings with `{t('key')}` and imports `useTranslations` (`shallok extract --apply`).
|
|
42
|
+
- Maintains per-key versioning and SHA-256 content hashes in `localization_base/`.
|
|
43
|
+
- Compiles runtime message bundles to `messages/runtime/<locale>.json` (`shallok build`).
|
|
44
|
+
- Validates 0 missing keys, 0 stale versions, and 0 broken placeholders (`shallok validate`).
|
|
45
|
+
|
|
46
|
+
2. **The AI Agent (You)** provides semantic intelligence:
|
|
47
|
+
- **No external API keys required**: You generate natural, culturally authentic translations directly into target languages (e.g. Kannada, Hindi, Spanish, French, German).
|
|
48
|
+
- **Context Enrichment**: You inspect Next.js Server Components, Client Components, and layout hierarchies to provide rich, descriptive `context` in `localization_base/` for each key.
|
|
49
|
+
- **Integrity**: You preserve all interpolation tokens (`{userName}`, `{count}`, `{amount}`) exactly as they appear in the source text.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 6-Phase Agent Workflow for Next.js
|
|
54
|
+
|
|
55
|
+
### Phase A: Analyze
|
|
56
|
+
Inspect repository architecture without modifying files:
|
|
57
|
+
```bash
|
|
58
|
+
shallok analyze --json
|
|
59
|
+
```
|
|
60
|
+
- Verify framework is detected as `nextjs`.
|
|
61
|
+
- Check Next.js version in `package.json` (`dependencies.next`).
|
|
62
|
+
- Check router type:
|
|
63
|
+
- **App Router**: `app/` directory exists (with or without `src/`).
|
|
64
|
+
- **Pages Router**: `pages/` directory exists.
|
|
65
|
+
- Identify candidate page and component files (`app/**/*.tsx`, `src/**/*.tsx`).
|
|
66
|
+
- Note user-requested target locales (e.g. `kn`, `hi`, `fr`, `es`).
|
|
67
|
+
- **Never edit files during Phase A.**
|
|
68
|
+
|
|
69
|
+
### Phase B: Plan and Review
|
|
70
|
+
Present a concise plan to the developer:
|
|
71
|
+
1. **Framework & Library**: Next.js with `next-intl`.
|
|
72
|
+
2. **Locales**: Source locale (e.g. `en`) and target locales (e.g. `kn` Kannada, `hi` Hindi).
|
|
73
|
+
3. **Dependencies to Install**:
|
|
74
|
+
```bash
|
|
75
|
+
pnpm add next-intl
|
|
76
|
+
```
|
|
77
|
+
4. **Planned Scaffolding**:
|
|
78
|
+
- `localization.json` (Project manifest)
|
|
79
|
+
- `src/i18n/routing.ts` (Routing definition for `next-intl`)
|
|
80
|
+
- `src/i18n/request.ts` (Request configuration for server-side loading)
|
|
81
|
+
- `middleware.ts` (Locale detection and URL rewriting)
|
|
82
|
+
- `localization_base/<source_locale>.json` & `metadata.json` (Canonical catalog & versions)
|
|
83
|
+
- `messages/<locale>.json` (Authoritative target catalogs)
|
|
84
|
+
- `messages/runtime/<locale>.json` (Compiled runtime message bundles)
|
|
85
|
+
5. **App Structure Updates**:
|
|
86
|
+
- Nest routes under `app/[locale]/...`
|
|
87
|
+
- Setup `NextIntlClientProvider` in `app/[locale]/layout.tsx` for client components
|
|
88
|
+
6. Confirm with user before proceeding (or proceed if `--yes` / requested).
|
|
89
|
+
|
|
90
|
+
### Phase C: Initialize
|
|
91
|
+
Initialize configuration and Next.js scaffolding:
|
|
92
|
+
```bash
|
|
93
|
+
shallok init --source en --locales kn,hi --framework nextjs --yes
|
|
94
|
+
```
|
|
95
|
+
This automatically creates:
|
|
96
|
+
- `localization.json`
|
|
97
|
+
- `src/i18n/routing.ts`
|
|
98
|
+
- `src/i18n/request.ts`
|
|
99
|
+
- Initial catalogs in `localization_base/` and `messages/`
|
|
100
|
+
- Installs `shallok` in `devDependencies` and copies skills
|
|
101
|
+
|
|
102
|
+
Ensure dependencies are installed:
|
|
103
|
+
```bash
|
|
104
|
+
pnpm add next-intl
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Phase D: Extract & Enrich Context (AI-Driven)
|
|
108
|
+
1. **Preview proposed extraction**:
|
|
109
|
+
```bash
|
|
110
|
+
shallok extract --dry-run --json
|
|
111
|
+
```
|
|
112
|
+
2. **Extract strings to canonical catalog**:
|
|
113
|
+
```bash
|
|
114
|
+
shallok extract
|
|
115
|
+
```
|
|
116
|
+
This extracts text and JSX expressions to `localization_base/en.json`.
|
|
117
|
+
|
|
118
|
+
3. **Enrich Context (Performed by AI Agent)**:
|
|
119
|
+
- Review `localization_base/en.json`.
|
|
120
|
+
- Inspect the Next.js page or component where each key originates.
|
|
121
|
+
- Enrich `context` with semantic clarity (e.g. *"Dashboard banner heading welcoming returning user"*).
|
|
122
|
+
- Use the CLI:
|
|
123
|
+
```bash
|
|
124
|
+
shallok context set <key> "<semantic_description>"
|
|
125
|
+
```
|
|
126
|
+
Or edit `"context"` directly in `localization_base/en.json`.
|
|
127
|
+
- **Preservation Guarantee**: Shallok's reconciliation algorithm strictly preserves your enriched context across all future extractions.
|
|
128
|
+
|
|
129
|
+
### Phase E: Translate (AI-Driven)
|
|
130
|
+
**No external API keys or LLM provider subscriptions are required.**
|
|
131
|
+
You, as the AI coding agent, generate the translations directly:
|
|
132
|
+
|
|
133
|
+
1. **Check translation status**:
|
|
134
|
+
```bash
|
|
135
|
+
shallok status --json
|
|
136
|
+
```
|
|
137
|
+
Identify keys in `messages/<locale>.json` marked with `status: "missing"` or `status: "stale"`.
|
|
138
|
+
|
|
139
|
+
2. **Generate Natural Translations**:
|
|
140
|
+
- Translate each string into culturally authentic target language (e.g. Kannada, Hindi).
|
|
141
|
+
- Use the source `content` and your enriched `context` for accurate terminology.
|
|
142
|
+
- **Strict Rule**: Preserve all interpolation tokens (`{count}`, `{name}`, `{date}`) exactly as formatted in the source text.
|
|
143
|
+
|
|
144
|
+
3. **Update Target Locale Catalogs**:
|
|
145
|
+
Write directly into `messages/<locale>.json` or use:
|
|
146
|
+
```bash
|
|
147
|
+
shallok entry set <locale> <key> "<translated_text>"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Phase F: Apply, Build & Validate
|
|
151
|
+
1. **Transform Next.js source components**:
|
|
152
|
+
```bash
|
|
153
|
+
shallok extract --apply
|
|
154
|
+
```
|
|
155
|
+
2. **Verify Next.js Integration Files**:
|
|
156
|
+
- `middleware.ts` configured with `next-intl/middleware`.
|
|
157
|
+
- `next.config.mjs` with `createNextIntlPlugin`.
|
|
158
|
+
3. **Compile runtime message bundles**:
|
|
159
|
+
```bash
|
|
160
|
+
shallok build
|
|
161
|
+
```
|
|
162
|
+
4. **Validate catalog integrity**:
|
|
163
|
+
```bash
|
|
164
|
+
shallok validate
|
|
165
|
+
```
|
|
166
|
+
Verifies 0 missing translations, 0 stale versions, 0 dropped or mismatched placeholders.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# AST Extraction Reference
|
|
2
|
+
|
|
3
|
+
## Extraction Strategy
|
|
4
|
+
Shallok uses Babel AST parsing (`@babel/parser` and `@babel/traverse`) with full JSX and TypeScript support to safely inspect and transform source files without regular expressions.
|
|
5
|
+
|
|
6
|
+
## What is Extracted
|
|
7
|
+
1. **JSX Text Nodes**:
|
|
8
|
+
- `<h1>Welcome</h1>` → `{t('home.welcome')}`
|
|
9
|
+
- `<button>Pay now</button>` → `<button>{t('checkout.pay_now')}</button>`
|
|
10
|
+
2. **User-Facing Attributes**:
|
|
11
|
+
- `placeholder="Enter your email"`
|
|
12
|
+
- `aria-label="Submit login form"`
|
|
13
|
+
- `title="Cart summary"`
|
|
14
|
+
- `alt="Product thumbnail"`
|
|
15
|
+
- `label="Password"`
|
|
16
|
+
3. **Conditional UI Expressions**:
|
|
17
|
+
- `{isMember ? 'VIP Member' : 'Guest User'}`
|
|
18
|
+
4. **Template Literals with Variables**:
|
|
19
|
+
- `Hello, ${name}!` → `Hello, {name}!` with variable preservation.
|
|
20
|
+
|
|
21
|
+
## What is Explicitly Ignored
|
|
22
|
+
- Technical attributes: `className`, `id`, `name`, `key`, `ref`, `type`, `href`, `src`, `data-testid`, `role`.
|
|
23
|
+
- Console and logger calls: `console.log(...)`, `console.error(...)`, `logger.debug(...)`.
|
|
24
|
+
- URLs, file paths, hex colors, CSS units.
|
|
25
|
+
- Non-user-facing strings, code constants, and symbols.
|
|
26
|
+
- Already localized calls: `t(...)`, `i18n.t(...)`.
|
|
27
|
+
|
|
28
|
+
## Dry-Run Mode
|
|
29
|
+
Always use `localize extract --dry-run` to preview keys and occurrences before committing changes to source files.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Next.js & next-intl Technical Reference
|
|
2
|
+
|
|
3
|
+
## Configuration Pattern
|
|
4
|
+
|
|
5
|
+
### 1. `src/i18n/routing.ts`
|
|
6
|
+
```typescript
|
|
7
|
+
import { defineRouting } from 'next-intl/routing';
|
|
8
|
+
|
|
9
|
+
export const routing = defineRouting({
|
|
10
|
+
locales: ['en', 'kn', 'hi'],
|
|
11
|
+
defaultLocale: 'en',
|
|
12
|
+
});
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### 2. `src/i18n/request.ts`
|
|
16
|
+
```typescript
|
|
17
|
+
import { getRequestConfig } from 'next-intl/server';
|
|
18
|
+
import { routing } from './routing';
|
|
19
|
+
|
|
20
|
+
export default getRequestConfig(async ({ requestLocale }) => {
|
|
21
|
+
let locale = await requestLocale;
|
|
22
|
+
|
|
23
|
+
if (!locale || !routing.locales.includes(locale as any)) {
|
|
24
|
+
locale = routing.defaultLocale;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
locale,
|
|
29
|
+
messages: (await import(`../../messages/runtime/${locale}.json`)).default,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 3. `middleware.ts`
|
|
35
|
+
```typescript
|
|
36
|
+
import createMiddleware from 'next-intl/middleware';
|
|
37
|
+
import { routing } from './src/i18n/routing';
|
|
38
|
+
|
|
39
|
+
export default createMiddleware(routing);
|
|
40
|
+
|
|
41
|
+
export const config = {
|
|
42
|
+
matcher: ['/', '/(kn|hi|en)/:path*']
|
|
43
|
+
};
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Hook & Async Usage
|
|
47
|
+
- **Server Components**:
|
|
48
|
+
```typescript
|
|
49
|
+
import { getTranslations } from 'next-intl/server';
|
|
50
|
+
const t = await getTranslations();
|
|
51
|
+
```
|
|
52
|
+
- **Client Components**:
|
|
53
|
+
```typescript
|
|
54
|
+
'use client';
|
|
55
|
+
import { useTranslations } from 'next-intl';
|
|
56
|
+
const t = useTranslations();
|
|
57
|
+
```
|
|
58
|
+
- **Navigation**:
|
|
59
|
+
```typescript
|
|
60
|
+
import { createNavigation } from 'next-intl/navigation';
|
|
61
|
+
import { routing } from './routing';
|
|
62
|
+
export const { Link, redirect, usePathname, useRouter } = createNavigation(routing);
|
|
63
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Translation Engine & Agent-Native Translation Reference
|
|
2
|
+
|
|
3
|
+
## Agent-Native Translation (Primary Workflow)
|
|
4
|
+
When using Shallok via an AI coding agent (e.g., in Claude, Cursor, Copilot, Antigravity):
|
|
5
|
+
- **No external API keys or LLM provider subscriptions are needed.**
|
|
6
|
+
- The AI agent itself generates accurate, natural translations for each target locale.
|
|
7
|
+
- The AI agent inspects `messages/<locale>.json` or runs `localize status --json` to identify entries with `status: "missing"` or `status: "stale"`.
|
|
8
|
+
- The AI agent writes the translated strings into `messages/<locale>.json` (or uses `localize entry set <locale> <key> "<translated_text>"`).
|
|
9
|
+
|
|
10
|
+
### Translation Schema
|
|
11
|
+
Each entry in `messages/<locale>.json` maintains:
|
|
12
|
+
```json
|
|
13
|
+
{
|
|
14
|
+
"checkout.pay_now": {
|
|
15
|
+
"value": "ಈಗ ಪಾವತಿಸಿ",
|
|
16
|
+
"source_version": 1,
|
|
17
|
+
"translated_at": "2026-10-19T14:00:00.000Z",
|
|
18
|
+
"status": "translated"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Supported Statuses
|
|
24
|
+
- `missing`: Key exists in canonical catalog but has no translation.
|
|
25
|
+
- `stale`: Key source version was incremented; old translation preserved for reference.
|
|
26
|
+
- `translated`: Translated and matching the current canonical `source_version`.
|
|
27
|
+
- `review_required`: Flagged for human review.
|
|
28
|
+
- `approved`: Formally approved translation.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Placeholder Preservation Rules
|
|
33
|
+
The AI agent must strictly preserve all interpolation placeholders in target translations:
|
|
34
|
+
- Source: `"Welcome back, {userName}! You have {itemCount} items in your cart."`
|
|
35
|
+
- Kannada: `"ಮರಳಿ ಸ್ವಾಗತ, {userName}! ನಿಮ್ಮ ಕಾರ್ಟ್ನಲ್ಲಿ {itemCount} ಐಟಂಗಳು ಇವೆ."`
|
|
36
|
+
- Hindi: `"वापसी पर स्वागत है, {userName}! आपके कार्ट में {itemCount} आइटम हैं।"`
|
|
37
|
+
|
|
38
|
+
If a translation drops a placeholder or introduces an invalid placeholder, `localize validate` will fail with an error.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## CLI-Based Translation (Optional / Fallback)
|
|
43
|
+
For automated pipelines or scripts running outside an interactive AI agent:
|
|
44
|
+
1. **Mock Provider (`mock`)**: Default provider with built-in dictionary for local development and CI testing.
|
|
45
|
+
2. **LLM Provider (`llm`)**: Calls OpenAI, Gemini, or Anthropic HTTP APIs when `TRANSLATION_API_KEY` is provided.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Per-Key Versioning & Context Reference
|
|
2
|
+
|
|
3
|
+
## Canonical Source Catalog (`localization_base/`)
|
|
4
|
+
The canonical catalog is the single source of truth for all active and obsolete keys, including their cryptographic content hashes and version counters.
|
|
5
|
+
|
|
6
|
+
### Structure of a Canonical Entry
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"checkout.pay_now": {
|
|
10
|
+
"key": "checkout.pay_now",
|
|
11
|
+
"content": "Pay now",
|
|
12
|
+
"context": "Primary action button on checkout screen to trigger payment modal",
|
|
13
|
+
"relative_file_path": "src/components/checkout.tsx",
|
|
14
|
+
"occurrences": [
|
|
15
|
+
{
|
|
16
|
+
"relative_file_path": "src/components/checkout.tsx",
|
|
17
|
+
"line": 42,
|
|
18
|
+
"column": 12
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"last_updated_at": "2026-10-19T10:00:00.000Z",
|
|
22
|
+
"key_version": 1,
|
|
23
|
+
"content_hash": "sha256:...",
|
|
24
|
+
"status": "active"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Context Enrichment by AI Agents
|
|
30
|
+
1. When strings are extracted via `localize extract`, the CLI provides baseline AST context (e.g. `JSX text in <button> (in App <button>)`).
|
|
31
|
+
2. The AI Agent analyzes the source code, component hierarchy, and user flow, and enriches the `context` with semantic clarity:
|
|
32
|
+
- CLI method: `localize context set <key> "<semantic_description>"`
|
|
33
|
+
- Direct edit: Update `"context"` in `localization_base/<source_locale>.json`.
|
|
34
|
+
3. **Preservation Guarantee**:
|
|
35
|
+
Shallok's reconciliation algorithm (`reconcileCanonicalCatalog`) checks if a key already has an enriched context. Unless the source code introduces an explicit inline comment (`{/* context: ... */}`), the AI agent's enriched context is **strictly preserved** across all future extractions and will not be overwritten by generic AST node descriptions.
|
|
36
|
+
|
|
37
|
+
## Reconciliation & Versioning Rules
|
|
38
|
+
1. **New Key**: Initialized at `key_version = 1`, `status = "active"`.
|
|
39
|
+
2. **Unchanged Content & Context**: `key_version` and `last_updated_at` remain unchanged.
|
|
40
|
+
3. **Modified Source Content**: `key_version` increments by 1; `last_updated_at` is updated.
|
|
41
|
+
4. **File Move / Occurrence Change**: Path and occurrence lines are updated; `key_version` does NOT increment.
|
|
42
|
+
5. **Key Removed from Source**: Marked `status = "obsolete"`; preserved in catalog for historical retention.
|
|
43
|
+
6. **Key Reintroduced**: Reactivated as `"active"`.
|
|
44
|
+
|
|
45
|
+
## Stale Detection in Locale Catalogs
|
|
46
|
+
In `messages/<locale>.json`, each entry records:
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"checkout.pay_now": {
|
|
50
|
+
"value": "ಈಗ ಪಾವತಿಸಿ",
|
|
51
|
+
"source_version": 1,
|
|
52
|
+
"translated_at": "2026-10-19T10:05:00.000Z",
|
|
53
|
+
"status": "translated"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
A translation is **stale** when `entry.source_version < canonicalEntry.key_version`. Stale entries retain their existing translated value for reference until the AI agent updates them.
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: react-localization-and-translation-i18n
|
|
3
|
+
description: React-specific localization and translation workflow using react-i18next and Shallok CLI (shallok). Guides AI coding agents through AST extraction of React JSX/TSX components, context enrichment, direct agent translation without external API keys, runtime bundle compilation, and validation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# React Localization & Translation Skill (`react-i18next`)
|
|
7
|
+
|
|
8
|
+
Use this skill when asked to add, configure, update, or audit localization in **React applications** (Vite, Create React App, Webpack, SPAs).
|
|
9
|
+
|
|
10
|
+
## Two Ways Developers Use Shallok
|
|
11
|
+
|
|
12
|
+
1. **Via CLI (`npx shallok init`)**: The developer runs `npx shallok init` in their project. Shallok initializes the catalogs, installs `shallok` into `devDependencies`, and adds this skill directly into `.agents/skills/` and `skills/`.
|
|
13
|
+
2. **Direct Skill Installation**: The developer installs or links this skill into their AI coding agent and directly asks: *"Add localization to this application"* or *"Translate into Kannada and Hindi"*.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Agent Step 0: Verify & Install Shallok CLI
|
|
18
|
+
|
|
19
|
+
**Before executing any localization commands, you (the AI Agent) MUST verify that `shallok` is available:**
|
|
20
|
+
|
|
21
|
+
1. Check `package.json` for `"shallok"` in `devDependencies` or run:
|
|
22
|
+
```bash
|
|
23
|
+
npx shallok --version
|
|
24
|
+
```
|
|
25
|
+
2. **If `shallok` is NOT installed, install it immediately** using the project's package manager:
|
|
26
|
+
- If `pnpm-lock.yaml` exists: `pnpm add -D shallok`
|
|
27
|
+
- If `yarn.lock` exists: `yarn add -D shallok`
|
|
28
|
+
- If `bun.lockb` / `bun.lock` exists: `bun add -d shallok`
|
|
29
|
+
- Otherwise: `npm install -D shallok`
|
|
30
|
+
*(Alternatively, run commands directly via `npx shallok <command>`)*
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Architecture & Agent Role
|
|
35
|
+
|
|
36
|
+
Shallok pairs a deterministic AST CLI (`shallok`) with **the AI Agent as the semantic translator and context enricher**:
|
|
37
|
+
|
|
38
|
+
1. **The CLI (`shallok`)** handles deterministic tasks:
|
|
39
|
+
- Scaffolds `src/i18n.ts` configuring `react-i18next`.
|
|
40
|
+
- AST parses React JSX/TSX components (`shallok extract`).
|
|
41
|
+
- Replaces user-facing strings and JSX elements with `{t('key')}` and imports `useTranslation` (`shallok extract --apply`).
|
|
42
|
+
- Maintains per-key versioning and SHA-256 content hashes in `localization_base/`.
|
|
43
|
+
- Compiles runtime message bundles to `messages/runtime/<locale>.json` (`shallok build`).
|
|
44
|
+
- Validates 0 missing keys, 0 stale versions, and 0 broken placeholders (`shallok validate`).
|
|
45
|
+
|
|
46
|
+
2. **The AI Agent (You)** provides semantic intelligence:
|
|
47
|
+
- **No external API keys required**: You generate natural, culturally authentic translations directly into target languages (e.g. Kannada, Hindi, Spanish, French, German).
|
|
48
|
+
- **Context Enrichment**: You inspect React components, state flows, and screen layouts to provide rich, descriptive `context` in `localization_base/` for each key.
|
|
49
|
+
- **Integrity**: You preserve all interpolation tokens (`{userName}`, `{count}`, `{amount}`) exactly as they appear in the source text.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 6-Phase Agent Workflow for React
|
|
54
|
+
|
|
55
|
+
### Phase A: Analyze
|
|
56
|
+
Inspect repository architecture without modifying files:
|
|
57
|
+
```bash
|
|
58
|
+
shallok analyze --json
|
|
59
|
+
```
|
|
60
|
+
- Verify framework is detected as `react`.
|
|
61
|
+
- Check React version in `package.json` (`dependencies.react`).
|
|
62
|
+
- Identify source directory (typically `src/`) and entry file (`src/main.tsx`, `src/index.tsx`, or `src/App.tsx`).
|
|
63
|
+
- Identify candidate React component files (`src/**/*.tsx`, `src/**/*.jsx`).
|
|
64
|
+
- Note user-requested target locales (e.g. `kn`, `hi`, `fr`, `es`).
|
|
65
|
+
- **Never edit files during Phase A.**
|
|
66
|
+
|
|
67
|
+
### Phase B: Plan and Review
|
|
68
|
+
Present a concise plan to the developer:
|
|
69
|
+
1. **Framework & Library**: React with `react-i18next` and `i18next`.
|
|
70
|
+
2. **Locales**: Source locale (e.g. `en`) and target locales (e.g. `kn` Kannada, `hi` Hindi).
|
|
71
|
+
3. **Dependencies to Install**:
|
|
72
|
+
```bash
|
|
73
|
+
pnpm add i18next react-i18next
|
|
74
|
+
```
|
|
75
|
+
4. **Planned Scaffolding**:
|
|
76
|
+
- `localization.json` (Project manifest)
|
|
77
|
+
- `src/i18n.ts` (React-i18next configuration)
|
|
78
|
+
- `localization_base/<source_locale>.json` & `metadata.json` (Canonical catalog & versions)
|
|
79
|
+
- `messages/<locale>.json` (Target locale catalogs)
|
|
80
|
+
- `messages/runtime/<locale>.json` (Compiled runtime bundles)
|
|
81
|
+
5. **Entry Point Integration**: Adding `import './i18n';` in `src/main.tsx` (or `src/index.tsx`).
|
|
82
|
+
6. Confirm with user before proceeding (or proceed if `--yes` / requested).
|
|
83
|
+
|
|
84
|
+
### Phase C: Initialize
|
|
85
|
+
Initialize configuration and React scaffolding:
|
|
86
|
+
```bash
|
|
87
|
+
shallok init --source en --locales kn,hi --framework react --yes
|
|
88
|
+
```
|
|
89
|
+
This automatically creates:
|
|
90
|
+
- `localization.json`
|
|
91
|
+
- `src/i18n.ts`
|
|
92
|
+
- Initial catalogs in `localization_base/` and `messages/`
|
|
93
|
+
- Installs `shallok` in `devDependencies` and copies skills
|
|
94
|
+
|
|
95
|
+
Ensure React runtime dependencies are installed:
|
|
96
|
+
```bash
|
|
97
|
+
pnpm add i18next react-i18next
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Phase D: Extract & Enrich Context (AI-Driven)
|
|
101
|
+
1. **Preview proposed extraction**:
|
|
102
|
+
```bash
|
|
103
|
+
shallok extract --dry-run --json
|
|
104
|
+
```
|
|
105
|
+
2. **Extract strings to canonical catalog**:
|
|
106
|
+
```bash
|
|
107
|
+
shallok extract
|
|
108
|
+
```
|
|
109
|
+
This populates `localization_base/en.json` with extracted keys and initial AST locations.
|
|
110
|
+
|
|
111
|
+
3. **Enrich Context (Performed by AI Agent)**:
|
|
112
|
+
- Review `localization_base/en.json`.
|
|
113
|
+
- Inspect the React component code where each key is used.
|
|
114
|
+
- Enrich `context` with semantic clarity (e.g. *"Primary CTA button inside CheckoutModal component to submit credit card payment"*).
|
|
115
|
+
- Use the CLI:
|
|
116
|
+
```bash
|
|
117
|
+
shallok context set <key> "<semantic_description>"
|
|
118
|
+
```
|
|
119
|
+
Or edit `"context"` directly in `localization_base/en.json`.
|
|
120
|
+
- **Preservation Guarantee**: Shallok's reconciliation algorithm strictly preserves your enriched context across all future extractions.
|
|
121
|
+
|
|
122
|
+
### Phase E: Translate (AI-Driven)
|
|
123
|
+
**No external API keys or LLM provider subscriptions are required.**
|
|
124
|
+
You, as the AI coding agent, generate the translations directly:
|
|
125
|
+
|
|
126
|
+
1. **Check translation status**:
|
|
127
|
+
```bash
|
|
128
|
+
shallok status --json
|
|
129
|
+
```
|
|
130
|
+
Identify keys in `messages/<locale>.json` marked with `status: "missing"` or `status: "stale"`.
|
|
131
|
+
|
|
132
|
+
2. **Generate Natural Translations**:
|
|
133
|
+
- Translate each string into culturally authentic target language (e.g. Kannada, Hindi).
|
|
134
|
+
- Use the source `content` and your enriched `context` for accurate terminology.
|
|
135
|
+
- **Strict Rule**: Preserve all interpolation tokens (`{count}`, `{name}`, `{date}`) exactly as formatted in the source text.
|
|
136
|
+
|
|
137
|
+
3. **Update Target Locale Catalogs**:
|
|
138
|
+
Write directly into `messages/<locale>.json` or use:
|
|
139
|
+
```bash
|
|
140
|
+
shallok entry set <locale> <key> "<translated_text>"
|
|
141
|
+
```
|
|
142
|
+
Example catalog entry:
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"checkout.pay_now": {
|
|
146
|
+
"value": "ಈಗ ಪಾವತಿಸಿ",
|
|
147
|
+
"source_version": 1,
|
|
148
|
+
"translated_at": "2026-10-19T14:00:00.000Z",
|
|
149
|
+
"status": "translated"
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Phase F: Apply, Build & Validate
|
|
155
|
+
1. **Transform React source components**:
|
|
156
|
+
```bash
|
|
157
|
+
shallok extract --apply
|
|
158
|
+
```
|
|
159
|
+
This injects `const { t } = useTranslation();` and replaces hardcoded text with `{t('key')}`.
|
|
160
|
+
|
|
161
|
+
2. **Verify Entry Point Integration**:
|
|
162
|
+
Ensure `src/main.tsx` or `src/index.tsx` imports the i18n configuration:
|
|
163
|
+
```tsx
|
|
164
|
+
import React from 'react';
|
|
165
|
+
import ReactDOM from 'react-dom/client';
|
|
166
|
+
import App from './App';
|
|
167
|
+
import './i18n'; // <-- Must be imported before rendering
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
3. **Compile runtime message bundles**:
|
|
171
|
+
```bash
|
|
172
|
+
shallok build
|
|
173
|
+
```
|
|
174
|
+
Compiles clean dictionaries into `messages/runtime/<locale>.json`.
|
|
175
|
+
|
|
176
|
+
4. **Validate catalog integrity**:
|
|
177
|
+
```bash
|
|
178
|
+
shallok validate
|
|
179
|
+
```
|
|
180
|
+
Verifies:
|
|
181
|
+
- 0 missing translations.
|
|
182
|
+
- 0 stale versions.
|
|
183
|
+
- 0 dropped or mismatched placeholders.
|
|
184
|
+
|
|
185
|
+
5. **Summarize results**:
|
|
186
|
+
Present modified components, added locales, completeness, and verification state.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## React Code Patterns & Best Practices
|
|
191
|
+
|
|
192
|
+
### 1. Component Transformation
|
|
193
|
+
Before:
|
|
194
|
+
```tsx
|
|
195
|
+
export function Hero() {
|
|
196
|
+
return (
|
|
197
|
+
<div>
|
|
198
|
+
<h1>Welcome to our store</h1>
|
|
199
|
+
<input placeholder="Search products..." />
|
|
200
|
+
</div>
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
After (`shallok extract --apply`):
|
|
206
|
+
```tsx
|
|
207
|
+
import { useTranslation } from 'react-i18next';
|
|
208
|
+
|
|
209
|
+
export function Hero() {
|
|
210
|
+
const { t } = useTranslation();
|
|
211
|
+
return (
|
|
212
|
+
<div>
|
|
213
|
+
<h1>{t('hero.welcome_title')}</h1>
|
|
214
|
+
<input placeholder={t('hero.search_placeholder')} />
|
|
215
|
+
</div>
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### 2. Language Switcher Component
|
|
221
|
+
```tsx
|
|
222
|
+
import { useTranslation } from 'react-i18next';
|
|
223
|
+
|
|
224
|
+
export function LanguageSwitcher() {
|
|
225
|
+
const { i18n } = useTranslation();
|
|
226
|
+
|
|
227
|
+
const changeLanguage = (lng: string) => {
|
|
228
|
+
i18n.changeLanguage(lng);
|
|
229
|
+
document.documentElement.lang = lng;
|
|
230
|
+
document.documentElement.dir = ['ar', 'he', 'fa', 'ur'].includes(lng) ? 'rtl' : 'ltr';
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
return (
|
|
234
|
+
<div className="language-switcher">
|
|
235
|
+
<button onClick={() => changeLanguage('en')} disabled={i18n.language === 'en'}>
|
|
236
|
+
English
|
|
237
|
+
</button>
|
|
238
|
+
<button onClick={() => changeLanguage('kn')} disabled={i18n.language === 'kn'}>
|
|
239
|
+
ಕನ್ನಡ
|
|
240
|
+
</button>
|
|
241
|
+
<button onClick={() => changeLanguage('hi')} disabled={i18n.language === 'hi'}>
|
|
242
|
+
हिंदी
|
|
243
|
+
</button>
|
|
244
|
+
</div>
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Maintenance Workflows
|
|
252
|
+
|
|
253
|
+
- **Add a new language**:
|
|
254
|
+
```bash
|
|
255
|
+
shallok locale add es
|
|
256
|
+
```
|
|
257
|
+
Translate active keys into `messages/es.json`, then run `shallok build && shallok validate`.
|
|
258
|
+
|
|
259
|
+
- **Source wording changed in a React component**:
|
|
260
|
+
Run `shallok extract`. Modified strings automatically increment `key_version` and flag target translations as `stale`. Translate the changed string, then run `shallok build`.
|
|
261
|
+
|
|
262
|
+
- **Rename a key**:
|
|
263
|
+
```bash
|
|
264
|
+
shallok key rename old.key.name new.key.name
|
|
265
|
+
shallok build
|
|
266
|
+
```
|