shallok 0.1.2 → 0.1.3
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 +132 -24
- package/dist/index.js +13 -13
- package/dist/index.js.map +1 -1
- package/package.json +5 -6
package/README.md
CHANGED
|
@@ -2,72 +2,180 @@
|
|
|
2
2
|
|
|
3
3
|
> AI-Powered, Versioned Localization Tool for Developers & AI Coding Agents.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/shallok)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
**Shallok** is a developer tool and AI agent skill system that enables developers and AI coding agents (Antigravity, Cursor, Claude Code, GitHub Copilot) to add, configure, extract, translate, and maintain localization across existing codebases with **AST-based transformations**, **deterministic per-key versioning**, and **agent-native incremental translations**.
|
|
9
|
+
|
|
10
|
+
---
|
|
6
11
|
|
|
7
12
|
## Features
|
|
8
13
|
|
|
9
|
-
- **AST-Based Extraction**: Deterministic AST parsing (Babel) safely extracts user-facing text and attributes into stable semantic keys.
|
|
10
14
|
- **Agent-Native Translation**: **Zero external API keys required**. AI coding agents translate missing and stale keys directly with natural cultural fluency.
|
|
11
|
-
- **
|
|
12
|
-
- **Per-Key Versioning & Content Hashing**:
|
|
13
|
-
- **
|
|
15
|
+
- **AST-Based Code Transformations**: Parses TSX/JSX and TypeScript safely with Babel; replaces hardcoded strings with framework hook/function calls without fragile regexes.
|
|
16
|
+
- **Per-Key Versioning & SHA-256 Content Hashing**: Granular content hashing detects source modifications; changing one string increments only its version while preserving all other translations.
|
|
17
|
+
- **AI-Enriched Semantic Context**: Context notes are enriched by AI agents and developers, strictly preserved across extractions.
|
|
18
|
+
- **Framework Adapters**: First-class support for:
|
|
14
19
|
- **React**: `react-i18next` with `src/i18n.ts`
|
|
15
|
-
- **Next.js**: `next-intl` (App Router `routing.ts`, `request.ts`, `middleware.ts`)
|
|
20
|
+
- **Next.js**: `next-intl` (App Router `routing.ts`, `request.ts`, `middleware.ts` & Pages Router)
|
|
16
21
|
- **Expo / React Native**: `expo-localization` + `i18next` with native device locale detection
|
|
17
|
-
- **Astro**: `astro:i18n` with dynamic message compilation
|
|
22
|
+
- **Astro**: `astro:i18n` with dynamic message compilation and UI island support
|
|
23
|
+
- **Vue**: `vue-i18n` with Vue composition API setup
|
|
18
24
|
- **Placeholder & Integrity Validation**: Validates 0 missing keys, 0 stale versions, and 0 corrupted placeholder tokens (`{count}`, `{name}`).
|
|
25
|
+
- **Interactive Ink Terminal UI**: Beautiful interactive console screens with automatic non-TTY and `--json` fallback for AI agent orchestration.
|
|
26
|
+
- **5 Pre-Packaged Agent Skills**: Tailored skills for general i18n, React, Next.js, Expo, and Astro.
|
|
19
27
|
|
|
20
28
|
---
|
|
21
29
|
|
|
22
|
-
##
|
|
30
|
+
## Two Ways to Use Shallok
|
|
31
|
+
|
|
32
|
+
### 1. Developer CLI Quickstart (`npx shallok init`)
|
|
23
33
|
|
|
24
|
-
|
|
25
|
-
Run in any React, Next.js, Expo, or Astro project:
|
|
34
|
+
Run in any React, Next.js, Expo, Astro, or Vue project:
|
|
26
35
|
```bash
|
|
27
36
|
npx shallok init
|
|
28
37
|
```
|
|
29
38
|
This command automatically:
|
|
30
39
|
1. Analyzes project architecture, detected framework, and router.
|
|
31
|
-
2. Scaffolds `localization.json`, `localization_base/`, `messages/`, and framework files.
|
|
32
|
-
3. Installs `shallok` into `devDependencies` using your
|
|
33
|
-
4. Installs AI agent skills directly into `.agents/skills/` and `skills
|
|
40
|
+
2. Scaffolds `localization.json`, `localization_base/`, `messages/`, and framework runtime files.
|
|
41
|
+
3. Installs `shallok` into `devDependencies` using your detected package manager (pnpm, npm, yarn, or bun).
|
|
42
|
+
4. Installs AI agent skills directly into `.agents/skills/` and `skills/` so AI coding agents immediately recognize them.
|
|
34
43
|
|
|
35
44
|
### 2. Direct AI Agent Skill Usage
|
|
36
|
-
|
|
45
|
+
|
|
46
|
+
Alternatively, install or copy any of the skills from `skills/` into your AI coding agent (e.g. `.agents/skills/` or Claude/Cursor/Copilot), then tell your agent:
|
|
37
47
|
> *"Add localization to this application with Kannada and Hindi"*
|
|
38
48
|
|
|
39
|
-
The agent
|
|
49
|
+
The AI agent will:
|
|
50
|
+
1. Check if `shallok` CLI is present in the project.
|
|
51
|
+
2. If not present, install `shallok` into `devDependencies` automatically.
|
|
52
|
+
3. Execute the 6-phase staged workflow (**Analyze → Plan → Init → Extract & Enrich Context → Translate → Build & Validate**) with **0 external API keys required**.
|
|
40
53
|
|
|
41
54
|
---
|
|
42
55
|
|
|
43
|
-
## CLI Commands
|
|
56
|
+
## CLI Commands Reference
|
|
57
|
+
|
|
58
|
+
> Run via your package runner (`npx shallok`, `pnpm shallok`) or global install (`npm i -g shallok`).
|
|
44
59
|
|
|
60
|
+
### Project Setup & Analysis
|
|
45
61
|
```bash
|
|
46
|
-
# Analyze
|
|
62
|
+
# Analyze repository architecture without modifying files
|
|
63
|
+
shallok analyze
|
|
47
64
|
shallok analyze --json
|
|
48
65
|
|
|
49
66
|
# Initialize configuration and framework files
|
|
67
|
+
shallok init
|
|
50
68
|
shallok init --source en --locales kn,hi,fr --framework react --yes
|
|
69
|
+
```
|
|
51
70
|
|
|
52
|
-
|
|
71
|
+
### Extraction & Code Transformation
|
|
72
|
+
```bash
|
|
73
|
+
# Preview proposed keys and transformations without modifying files
|
|
53
74
|
shallok extract --dry-run
|
|
75
|
+
|
|
76
|
+
# Reconcile canonical catalog without modifying source code
|
|
54
77
|
shallok extract
|
|
55
78
|
|
|
56
|
-
# Apply AST transformations to source code
|
|
79
|
+
# Apply AST transformations to source code (replaces hardcoded strings with t(...) calls)
|
|
57
80
|
shallok extract --apply
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Translation & Context
|
|
84
|
+
```bash
|
|
85
|
+
# Generate missing or stale translations
|
|
86
|
+
shallok translate
|
|
87
|
+
shallok translate --locale kn
|
|
88
|
+
shallok translate --force
|
|
58
89
|
|
|
59
|
-
#
|
|
90
|
+
# Update semantic context for a key in canonical catalog (preserved across future extractions)
|
|
91
|
+
shallok context set app.pay_now "Primary CTA button in checkout flow to trigger payment modal"
|
|
92
|
+
|
|
93
|
+
# Directly update a translated entry in a locale catalog
|
|
94
|
+
shallok entry set kn app.pay_now "ಈಗ ಪಾವತಿಸಿ"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Health, Validation & Build
|
|
98
|
+
```bash
|
|
99
|
+
# Check localization status & translation completeness
|
|
60
100
|
shallok status
|
|
101
|
+
shallok status --json
|
|
61
102
|
|
|
62
|
-
#
|
|
63
|
-
shallok
|
|
103
|
+
# Produce a full localization health report
|
|
104
|
+
shallok report
|
|
105
|
+
shallok report --json
|
|
64
106
|
|
|
65
|
-
# Validate placeholder and catalog integrity
|
|
107
|
+
# Validate placeholder parity ({name}) and catalog integrity
|
|
66
108
|
shallok validate
|
|
109
|
+
|
|
110
|
+
# Compile runtime-compatible message bundles
|
|
111
|
+
shallok build
|
|
112
|
+
shallok build --format nested
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Management & Automation
|
|
116
|
+
```bash
|
|
117
|
+
# Add or remove target locales
|
|
118
|
+
shallok locale add de
|
|
119
|
+
shallok locale remove fr
|
|
120
|
+
|
|
121
|
+
# Rename a key across canonical catalog, locale catalogs, and source references
|
|
122
|
+
shallok key rename old.key auth.login
|
|
123
|
+
|
|
124
|
+
# Full end-to-end sync pipeline (extract, translate, build, and validate)
|
|
125
|
+
shallok sync --dry-run
|
|
126
|
+
shallok sync --yes
|
|
67
127
|
```
|
|
68
128
|
|
|
69
129
|
---
|
|
70
130
|
|
|
131
|
+
## Manifest Schema: `localization.json`
|
|
132
|
+
|
|
133
|
+
Located at the root of the target project:
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"schema_version": 1,
|
|
137
|
+
"localization_version": 1,
|
|
138
|
+
"source_locale": "en",
|
|
139
|
+
"supported_locales": ["en", "kn", "hi", "fr", "de"],
|
|
140
|
+
"framework": {
|
|
141
|
+
"name": "nextjs",
|
|
142
|
+
"router": "app",
|
|
143
|
+
"localization_library": "next-intl",
|
|
144
|
+
"library_version": null
|
|
145
|
+
},
|
|
146
|
+
"paths": {
|
|
147
|
+
"source_directories": ["src"],
|
|
148
|
+
"base_directory": "localization_base",
|
|
149
|
+
"translations_directory": "messages"
|
|
150
|
+
},
|
|
151
|
+
"key_strategy": "semantic",
|
|
152
|
+
"translation": {
|
|
153
|
+
"provider": "mock",
|
|
154
|
+
"model": null,
|
|
155
|
+
"batch_size": 25
|
|
156
|
+
},
|
|
157
|
+
"options": {
|
|
158
|
+
"include_accessibility_text": true,
|
|
159
|
+
"preserve_obsolete_keys": true,
|
|
160
|
+
"require_review_for_ambiguous_strings": true,
|
|
161
|
+
"require_review_for_stale_translations": true
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Agent Skills Included
|
|
169
|
+
|
|
170
|
+
Shallok ships with 5 tailored skills for AI coding agents:
|
|
171
|
+
- `skills/localization-and-translation-i18n/`: Framework-independent core workflow
|
|
172
|
+
- `skills/react-localization-and-translation-i18n/`: React (`react-i18next`)
|
|
173
|
+
- `skills/nextjs-localization-and-translation-i18n/`: Next.js (`next-intl`)
|
|
174
|
+
- `skills/expo-localization-and-translation-i18n/`: Expo & React Native (`expo-localization` + `i18next`)
|
|
175
|
+
- `skills/astro-localization-and-translation-i18n/`: Astro (`astro:i18n`)
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
71
179
|
## License
|
|
72
180
|
|
|
73
|
-
MIT © Shallok Contributors
|
|
181
|
+
MIT © [Shallok Contributors](https://github.com/Hypermona/Shallok)
|
package/dist/index.js
CHANGED
|
@@ -51189,7 +51189,7 @@ async function extractCommand(options) {
|
|
|
51189
51189
|
const storage = new CatalogStorage(cwd);
|
|
51190
51190
|
const manifest = await storage.readManifest();
|
|
51191
51191
|
if (!manifest) {
|
|
51192
|
-
printer.error('No localization.json found. Run "
|
|
51192
|
+
printer.error('No localization.json found. Run "shallok init" first.');
|
|
51193
51193
|
process.exit(1);
|
|
51194
51194
|
}
|
|
51195
51195
|
const isDryRun = options.dryRun ?? false;
|
|
@@ -51647,7 +51647,7 @@ async function translateCommand(options) {
|
|
|
51647
51647
|
const storage = new CatalogStorage(cwd);
|
|
51648
51648
|
const manifest = await storage.readManifest();
|
|
51649
51649
|
if (!manifest) {
|
|
51650
|
-
printer.error('No localization.json found. Run "
|
|
51650
|
+
printer.error('No localization.json found. Run "shallok init" first.');
|
|
51651
51651
|
process.exit(1);
|
|
51652
51652
|
}
|
|
51653
51653
|
const canonical = await storage.readCanonicalCatalog(
|
|
@@ -51772,7 +51772,7 @@ async function statusCommand(options) {
|
|
|
51772
51772
|
const storage = new CatalogStorage(cwd);
|
|
51773
51773
|
const manifest = await storage.readManifest();
|
|
51774
51774
|
if (!manifest) {
|
|
51775
|
-
printer.error('No localization.json found. Run "
|
|
51775
|
+
printer.error('No localization.json found. Run "shallok init" first.');
|
|
51776
51776
|
process.exit(1);
|
|
51777
51777
|
}
|
|
51778
51778
|
const canonical = await storage.readCanonicalCatalog(
|
|
@@ -51816,7 +51816,7 @@ async function validateCommand(options) {
|
|
|
51816
51816
|
const storage = new CatalogStorage(cwd);
|
|
51817
51817
|
const manifest = await storage.readManifest();
|
|
51818
51818
|
if (!manifest) {
|
|
51819
|
-
printer.error('No localization.json found. Run "
|
|
51819
|
+
printer.error('No localization.json found. Run "shallok init" first.');
|
|
51820
51820
|
process.exit(1);
|
|
51821
51821
|
}
|
|
51822
51822
|
const canonical = await storage.readCanonicalCatalog(
|
|
@@ -51864,7 +51864,7 @@ async function buildCommand(options) {
|
|
|
51864
51864
|
const storage = new CatalogStorage(cwd);
|
|
51865
51865
|
const manifest = await storage.readManifest();
|
|
51866
51866
|
if (!manifest) {
|
|
51867
|
-
printer.error('No localization.json found. Run "
|
|
51867
|
+
printer.error('No localization.json found. Run "shallok init" first.');
|
|
51868
51868
|
process.exit(1);
|
|
51869
51869
|
}
|
|
51870
51870
|
const canonical = await storage.readCanonicalCatalog(
|
|
@@ -51908,7 +51908,7 @@ async function reportCommand(options) {
|
|
|
51908
51908
|
const storage = new CatalogStorage(cwd);
|
|
51909
51909
|
const manifest = await storage.readManifest();
|
|
51910
51910
|
if (!manifest) {
|
|
51911
|
-
printer.error('No localization.json found. Run "
|
|
51911
|
+
printer.error('No localization.json found. Run "shallok init" first.');
|
|
51912
51912
|
process.exit(1);
|
|
51913
51913
|
}
|
|
51914
51914
|
const canonical = await storage.readCanonicalCatalog(
|
|
@@ -51968,7 +51968,7 @@ async function localeAddCommand(locale, options) {
|
|
|
51968
51968
|
const storage = new CatalogStorage(cwd);
|
|
51969
51969
|
const manifest = await storage.readManifest();
|
|
51970
51970
|
if (!manifest) {
|
|
51971
|
-
printer.error('No localization.json found. Run "
|
|
51971
|
+
printer.error('No localization.json found. Run "shallok init" first.');
|
|
51972
51972
|
process.exit(1);
|
|
51973
51973
|
}
|
|
51974
51974
|
const cleanLocale = locale.trim().toLowerCase();
|
|
@@ -51997,7 +51997,7 @@ async function localeAddCommand(locale, options) {
|
|
|
51997
51997
|
return;
|
|
51998
51998
|
}
|
|
51999
51999
|
printer.success(`Added locale "${cleanLocale}" to supported_locales.`);
|
|
52000
|
-
printer.info(`Run "
|
|
52000
|
+
printer.info(`Run "shallok translate --locale ${cleanLocale}" to generate translations for this locale.`);
|
|
52001
52001
|
}
|
|
52002
52002
|
async function localeRemoveCommand(locale, options) {
|
|
52003
52003
|
const cwd = process.cwd();
|
|
@@ -52005,7 +52005,7 @@ async function localeRemoveCommand(locale, options) {
|
|
|
52005
52005
|
const storage = new CatalogStorage(cwd);
|
|
52006
52006
|
const manifest = await storage.readManifest();
|
|
52007
52007
|
if (!manifest) {
|
|
52008
|
-
printer.error('No localization.json found. Run "
|
|
52008
|
+
printer.error('No localization.json found. Run "shallok init" first.');
|
|
52009
52009
|
process.exit(1);
|
|
52010
52010
|
}
|
|
52011
52011
|
const cleanLocale = locale.trim().toLowerCase();
|
|
@@ -52060,7 +52060,7 @@ async function renameCommand(oldKey, newKey, options) {
|
|
|
52060
52060
|
const storage = new CatalogStorage(cwd);
|
|
52061
52061
|
const manifest = await storage.readManifest();
|
|
52062
52062
|
if (!manifest) {
|
|
52063
|
-
printer.error('No localization.json found. Run "
|
|
52063
|
+
printer.error('No localization.json found. Run "shallok init" first.');
|
|
52064
52064
|
process.exit(1);
|
|
52065
52065
|
}
|
|
52066
52066
|
const canonical = await storage.readCanonicalCatalog(
|
|
@@ -52120,7 +52120,7 @@ async function contextSetCommand(key, newContext, options) {
|
|
|
52120
52120
|
const storage = new CatalogStorage(cwd);
|
|
52121
52121
|
const manifest = await storage.readManifest();
|
|
52122
52122
|
if (!manifest) {
|
|
52123
|
-
printer.error('No localization.json found. Run "
|
|
52123
|
+
printer.error('No localization.json found. Run "shallok init" first.');
|
|
52124
52124
|
process.exit(1);
|
|
52125
52125
|
}
|
|
52126
52126
|
const canonical = await storage.readCanonicalCatalog(
|
|
@@ -52162,7 +52162,7 @@ async function entrySetCommand(locale, key, translatedValue, options) {
|
|
|
52162
52162
|
const storage = new CatalogStorage(cwd);
|
|
52163
52163
|
const manifest = await storage.readManifest();
|
|
52164
52164
|
if (!manifest) {
|
|
52165
|
-
printer.error('No localization.json found. Run "
|
|
52165
|
+
printer.error('No localization.json found. Run "shallok init" first.');
|
|
52166
52166
|
process.exit(1);
|
|
52167
52167
|
}
|
|
52168
52168
|
const cleanLocale = locale.trim().toLowerCase();
|
|
@@ -52208,7 +52208,7 @@ async function entrySetCommand(locale, key, translatedValue, options) {
|
|
|
52208
52208
|
|
|
52209
52209
|
// src/index.ts
|
|
52210
52210
|
var program = new Command();
|
|
52211
|
-
program.name("shallok").description("Shallok: AI-Powered, Versioned Localization Tool").version("0.1.
|
|
52211
|
+
program.name("shallok").description("Shallok: AI-Powered, Versioned Localization Tool").version("0.1.3").option("--json", "Output machine-readable JSON for AI agent orchestration");
|
|
52212
52212
|
program.command("analyze").description("Analyze the repository without modifying it").option("--json", "Output machine-readable JSON").action(async (options) => {
|
|
52213
52213
|
const isJson = options.json || program.opts().json;
|
|
52214
52214
|
await analyzeCommand({ json: isJson });
|