shallok 0.1.1 → 0.1.2

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.
Files changed (36) hide show
  1. package/dist/index.js +0 -0
  2. package/package.json +9 -9
  3. package/skills/astro-localization-and-translation-i18n/SKILL.md +105 -32
  4. package/skills/astro-localization-and-translation-i18n/references/astro-i18n.md +15 -0
  5. package/skills/astro-localization-and-translation-i18n/references/extraction.md +6 -1
  6. package/skills/astro-localization-and-translation-i18n/references/frameworks.md +59 -0
  7. package/skills/astro-localization-and-translation-i18n/references/translation.md +30 -4
  8. package/skills/astro-localization-and-translation-i18n/references/versioning.md +22 -6
  9. package/skills/expo-localization-and-translation-i18n/SKILL.md +116 -35
  10. package/skills/expo-localization-and-translation-i18n/references/expo-localization.md +56 -11
  11. package/skills/expo-localization-and-translation-i18n/references/extraction.md +6 -1
  12. package/skills/expo-localization-and-translation-i18n/references/frameworks.md +59 -0
  13. package/skills/expo-localization-and-translation-i18n/references/translation.md +30 -4
  14. package/skills/expo-localization-and-translation-i18n/references/versioning.md +22 -6
  15. package/skills/localization-and-translation-i18n/SKILL.md +116 -28
  16. package/skills/localization-and-translation-i18n/references/extraction.md +6 -1
  17. package/skills/localization-and-translation-i18n/references/frameworks.md +26 -7
  18. package/skills/localization-and-translation-i18n/references/translation.md +30 -4
  19. package/skills/localization-and-translation-i18n/references/versioning.md +22 -6
  20. package/skills/nextjs-localization-and-translation-i18n/SKILL.md +107 -35
  21. package/skills/nextjs-localization-and-translation-i18n/references/extraction.md +6 -1
  22. package/skills/nextjs-localization-and-translation-i18n/references/frameworks.md +59 -0
  23. package/skills/nextjs-localization-and-translation-i18n/references/next-intl.md +14 -2
  24. package/skills/nextjs-localization-and-translation-i18n/references/translation.md +30 -4
  25. package/skills/nextjs-localization-and-translation-i18n/references/versioning.md +22 -6
  26. package/skills/react-localization-and-translation-i18n/SKILL.md +116 -35
  27. package/skills/react-localization-and-translation-i18n/references/extraction.md +6 -1
  28. package/skills/react-localization-and-translation-i18n/references/frameworks.md +59 -0
  29. package/skills/react-localization-and-translation-i18n/references/react-i18next.md +54 -8
  30. package/skills/react-localization-and-translation-i18n/references/translation.md +30 -4
  31. package/skills/react-localization-and-translation-i18n/references/versioning.md +22 -6
  32. package/skills/localize-app/SKILL.md +0 -80
  33. package/skills/localize-app/references/extraction.md +0 -29
  34. package/skills/localize-app/references/frameworks.md +0 -25
  35. package/skills/localize-app/references/translation.md +0 -45
  36. package/skills/localize-app/references/versioning.md +0 -57
@@ -3,6 +3,11 @@
3
3
  ## Extraction Strategy
4
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
5
 
6
+ ## Normalized Dot-Paths for Keys (Never Object-Based)
7
+ - **Always use normalized dot-separated key paths**: e.g., `"checkout.pay_now"`, `"auth.login.title"`, `"dashboard.metrics.active_users"`.
8
+ - **Never use object-based or nested object paths**: Catalogs must never store nested object trees.
9
+ - **If an existing project uses object-based keys**: Ask the user for confirmation to flatten them to normalized dot-path keys before running extraction or migrating catalogs.
10
+
6
11
  ## What is Extracted
7
12
  1. **JSX Text Nodes**:
8
13
  - `<h1>Welcome</h1>` → `{t('home.welcome')}`
@@ -26,4 +31,4 @@ Shallok uses Babel AST parsing (`@babel/parser` and `@babel/traverse`) with full
26
31
  - Already localized calls: `t(...)`, `i18n.t(...)`.
27
32
 
28
33
  ## Dry-Run Mode
29
- Always use `localize extract --dry-run` to preview keys and occurrences before committing changes to source files.
34
+ Always use `shallok extract --dry-run` to preview keys and occurrences before committing changes to source files.
@@ -0,0 +1,59 @@
1
+ # Framework Adapters Reference
2
+
3
+ ## Loading Strategies: Local vs. CDN
4
+
5
+ | Framework Type | Recommended Strategy | Primary Rationale | Configuration & ENV |
6
+ | :--- | :--- | :--- | :--- |
7
+ | **Astro** (`astro:i18n`) | **Local** (`messages/runtime/`) | Static builds (SSG) & SSR; zero network hops, zero build dependency on external services. | Bundled in `src/i18n/utils.ts` |
8
+ | **Next.js** (`next-intl`) | **Local** (`messages/runtime/`) | Server Components & SSR; instant First Contentful Paint, zero latency in Node/Edge. | Bundled in `src/i18n/request.ts` |
9
+ | **Expo / React Native** | **CDN-Backed** (+ Local Fallback) | Instant Over-The-Air (OTA) translation & typo fixes without waiting for App Store review. | `EXPO_PUBLIC_TRANSLATIONS_CDN_URL` + AsyncStorage caching + local fallback |
10
+ | **React SPA** (Vite / CRA) | **CDN-Backed** (+ Local Fallback) | Instant copy updates without rebuilding web bundle. | `VITE_TRANSLATIONS_CDN_URL` + localStorage caching + local fallback |
11
+
12
+ ---
13
+
14
+ ## Supported Frameworks & Adapters
15
+
16
+ ### 1. React (`react-i18next`)
17
+ - **Initialization**: Generates `src/i18n.ts` configuring `i18next` with `initReactI18next`.
18
+ - **Runtime Messages**: Generates clean key-value message files in `messages/runtime/<locale>.json`.
19
+ - **CDN Loading**: Suggest `VITE_TRANSLATIONS_CDN_URL` in `.env` with local `messages/runtime/` fallback and `scripts/upload-locales.mjs`.
20
+ - **Legacy Migration**: If `src/main.tsx` or `src/i18n.ts` imported `src/locales/en.json`, migrate to `messages/runtime/` or CDN loader.
21
+ - **AST Transformation**:
22
+ - Adds `import { useTranslation } from 'react-i18next';`
23
+ - Injects `const { t } = useTranslation();` in components
24
+ - Replaces text with `{t('key')}` using normalized dot-separated key paths.
25
+
26
+ ### 2. Next.js (`next-intl`)
27
+ - **App Router Support**:
28
+ - Generates `src/i18n/routing.ts` defining `locales` and `defaultLocale`.
29
+ - Generates `src/i18n/request.ts` using `getRequestConfig` loading local `messages/runtime/<locale>.json`.
30
+ - **Runtime Messages**: Generates runtime message files in `messages/runtime/<locale>.json`.
31
+ - **Loading Strategy**: Local loading recommended for Server Components and SSR.
32
+ - **Legacy Migration**: If `src/i18n/request.ts` or `middleware.ts` imported old locale JSONs, update imports to `messages/runtime/<locale>.json`.
33
+ - **AST Transformation**:
34
+ - Adds `import { useTranslations } from 'next-intl';`
35
+ - Injects `const t = useTranslations();` in components
36
+ - Replaces text with `{t('key')}` using normalized dot-separated key paths.
37
+
38
+ ### 3. Expo / React Native (`expo-localization` + `react-i18next`)
39
+ - **Initialization**: Generates `i18n.ts` using `getLocales` from `expo-localization` and `i18next`.
40
+ - **Runtime Messages**: Generates runtime message files in `messages/runtime/<locale>.json`.
41
+ - **CDN Loading**: Suggest `EXPO_PUBLIC_TRANSLATIONS_CDN_URL` in `.env` with `AsyncStorage` caching and local `messages/runtime/` fallback.
42
+ - **Legacy Migration**: If `app/_layout.tsx` or `src/i18n.ts` imported `src/locales/en.json`, migrate to `messages/runtime/` or CDN loader.
43
+ - **AST Transformation**:
44
+ - Adds `import { useTranslation } from 'react-i18next';`
45
+ - Injects `const { t } = useTranslation();` in mobile components
46
+ - Replaces text inside `<Text>` and attributes like `placeholder` with `{t('key')}` using normalized dot-separated key paths.
47
+
48
+ ### 4. Astro (`astro:i18n`)
49
+ - **Initialization**: Generates `src/i18n/utils.ts` defining `locales`, `defaultLocale`, and `useTranslations` loading local `messages/runtime/<locale>.json`.
50
+ - **Runtime Messages**: Generates runtime message files in `messages/runtime/<locale>.json`.
51
+ - **Loading Strategy**: Local loading recommended for fast static SSG and hybrid SSR.
52
+ - **Legacy Migration**: If `src/i18n/utils.ts` or `.astro` files imported old locale JSONs, update imports to `messages/runtime/<locale>.json`.
53
+ - **Component Usage**:
54
+ - In Astro components frontmatter: `const t = await useTranslations(locale);`
55
+ - Renders `{t('key')}` in templates and islands using normalized dot-separated key paths.
56
+
57
+ ### 5. Vue (`vue-i18n`)
58
+ - **Initialization**: Generates `src/i18n.ts` using `createI18n`.
59
+ - **Runtime Messages**: Generates runtime message files in `messages/runtime/<locale>.json`.
@@ -1,4 +1,16 @@
1
- # Next.js & next-intl Technical Reference
1
+ ## Loading Architecture: Local Bundled Loading for Server Components & SSR
2
+
3
+ For Next.js App Router and Pages Router, **always keep translations LOCAL** in `messages/runtime/<locale>.json`.
4
+ - **Zero Network Latency**: Server Components and Edge middleware resolve dictionaries directly from memory/disk without remote HTTP requests.
5
+ - **Resilient Builds**: Static site exports and SSR hydration never fail due to external CDN outages.
6
+
7
+ ### Legacy Base Locale Migration
8
+ If an existing Next.js app was importing from `src/locales/en.json` or `locales/en.json`:
9
+ 1. Reconcile keys into `localization_base/en.json`.
10
+ 2. Update the dynamic import in `src/i18n/request.ts` to target `../../messages/runtime/${locale}.json`.
11
+ 3. Deprecate and remove the old legacy locale folder.
12
+
13
+ ---
2
14
 
3
15
  ## Configuration Pattern
4
16
 
@@ -12,7 +24,7 @@ export const routing = defineRouting({
12
24
  });
13
25
  ```
14
26
 
15
- ### 2. `src/i18n/request.ts`
27
+ ### 2. `src/i18n/request.ts` (Loads Local `messages/runtime/`)
16
28
  ```typescript
17
29
  import { getRequestConfig } from 'next-intl/server';
18
30
  import { routing } from './routing';
@@ -1,11 +1,37 @@
1
1
  # Translation Engine & Agent-Native Translation Reference
2
2
 
3
3
  ## Agent-Native Translation (Primary Workflow)
4
- When using Shallok via an AI coding agent (e.g., in Claude, Cursor, Copilot, Antigravity):
4
+ When using Shallok via an AI coding agent (e.g., in Antigravity, Claude, Cursor, Copilot):
5
5
  - **No external API keys or LLM provider subscriptions are needed.**
6
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>"`).
7
+ - **Always verify context first**: Before translating any key, check that all keys in `localization_base/<source_locale>.json` have proper semantic context. If any key lacks context or has generic AST context, generate rich context before translating.
8
+ - **Always translate from `localization_base/<source_locale>.json` and its context**: Never translate raw isolated string fragments. Combine the canonical source `content` and its semantic `context` to generate culturally authentic, grammatically correct translations.
9
+ - Inspect `messages/<locale>.json` or run `shallok status --json` to identify entries with `status: "missing"` or `status: "stale"`.
10
+ - Write the translated strings into `messages/<locale>.json` (or use `shallok entry set <locale> <key> "<translated_text>"`).
11
+
12
+ ## Core Rules for Translations
13
+
14
+ ### 1. Pre-Flight Verification & Persistence
15
+ - Before making changes to a new or existing repo, verify `shallok` is installed and check that `localization.json` and `localization_base/` exist. If not, initialize with `shallok init`.
16
+ - **NEVER delete `localization.json` or `localization_base/`**. They hold the single source of truth, content hashes, version counters, and context.
17
+
18
+ ### 2. Normalized Dot-Paths for Keys
19
+ - All keys must use normalized dot notation (e.g., `"checkout.pay_now"`, `"auth.login.title"`).
20
+ - Never use nested object structures. If an existing codebase uses nested objects for keys, ask the user to convert/flatten them to normalized dot-path keys.
21
+
22
+ ### 3. Standardized `messages/` Folder
23
+ - All translations must reside in `messages/` (`messages/<locale>.json` and `messages/runtime/<locale>.json`).
24
+ - If an existing project uses another directory (such as `locales/`, `src/locales/`, `translations/`), ask the user to switch to `messages/` and migrate existing files.
25
+
26
+ ### 4. Context Verification Before Translation
27
+ - Check all keys in `localization_base/<source_locale>.json` have meaningful semantic context.
28
+ - If any key lacks context, generate clear context describing the screen, element, and user action before initiating translation.
29
+
30
+ ### 5. Always Translate from Source Locale Catalog + Context
31
+ - Read both `content` and `context` from `localization_base/<source_locale>.json`.
32
+ - Preserve all interpolation placeholders (`{name}`, `{count}`, `{amount}`) exactly as formatted.
33
+
34
+ ---
9
35
 
10
36
  ### Translation Schema
11
37
  Each entry in `messages/<locale>.json` maintains:
@@ -35,7 +61,7 @@ The AI agent must strictly preserve all interpolation placeholders in target tra
35
61
  - Kannada: `"ಮರಳಿ ಸ್ವಾಗತ, {userName}! ನಿಮ್ಮ ಕಾರ್ಟ್‌ನಲ್ಲಿ {itemCount} ಐಟಂಗಳು ಇವೆ."`
36
62
  - Hindi: `"वापसी पर स्वागत है, {userName}! आपके कार्ट में {itemCount} आइटम हैं।"`
37
63
 
38
- If a translation drops a placeholder or introduces an invalid placeholder, `localize validate` will fail with an error.
64
+ If a translation drops a placeholder or introduces an invalid placeholder, `shallok validate` will fail with an error.
39
65
 
40
66
  ---
41
67
 
@@ -1,8 +1,22 @@
1
1
  # Per-Key Versioning & Context Reference
2
2
 
3
+ ## Strict Catalog Persistence: NEVER Delete `localization.json` or `localization_base/`
4
+ > [!CAUTION]
5
+ > `localization.json` and `localization_base/` are the permanent foundation of the localization system:
6
+ > - `localization.json` stores project settings, locales, paths, and key strategies.
7
+ > - `localization_base/` stores canonical source strings, per-key version counters (`key_version`), cryptographic SHA-256 hashes (`content_hash`), occurrence positions, and enriched semantic `context`.
8
+ > - **Under NO circumstances should you EVER delete `localization.json` or `localization_base/`**. Deleting them resets version counters, destroys human- and AI-enriched context, breaks incremental translation, and corrupts catalog synchronization.
9
+
10
+ ---
11
+
3
12
  ## Canonical Source Catalog (`localization_base/`)
4
13
  The canonical catalog is the single source of truth for all active and obsolete keys, including their cryptographic content hashes and version counters.
5
14
 
15
+ ### Key Format: Normalized Dot-Separated Paths Only
16
+ - All keys must use normalized dot-separated string paths (e.g. `"checkout.pay_now"`, `"auth.login.title"`).
17
+ - **Never use nested object-based keys**.
18
+ - If an existing project uses object-based keys, ask the user to convert and flatten them to normalized dot-paths before modifying catalogs.
19
+
6
20
  ### Structure of a Canonical Entry
7
21
  ```json
8
22
  {
@@ -26,12 +40,14 @@ The canonical catalog is the single source of truth for all active and obsolete
26
40
  }
27
41
  ```
28
42
 
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>"`
43
+ ## Context Enrichment & Verification Before Translation
44
+ 1. When strings are extracted via `shallok extract`, the CLI provides baseline AST context (e.g. `JSX text in <button> (in App <button>)`).
45
+ 2. **Mandatory Check Before Translation**: Before generating any translations, check that all active keys in `localization_base/<source_locale>.json` have proper, high-quality semantic context.
46
+ 3. If any key lacks context or has only generic AST descriptions, analyze the source code, component hierarchy, and user flow, and enrich the `context` with semantic clarity:
47
+ - CLI method: `shallok context set <key> "<semantic_description>"`
33
48
  - Direct edit: Update `"context"` in `localization_base/<source_locale>.json`.
34
- 3. **Preservation Guarantee**:
49
+ 4. **Always Translate from Source Locale + Context**: Translations must be derived directly from `localization_base/<source_locale>.json` using BOTH `content` and `context`.
50
+ 5. **Preservation Guarantee**:
35
51
  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
52
 
37
53
  ## Reconciliation & Versioning Rules
@@ -54,4 +70,4 @@ In `messages/<locale>.json`, each entry records:
54
70
  }
55
71
  }
56
72
  ```
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.
73
+ 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 from `localization_base/<source_locale>.json` and its enriched `context`.
@@ -14,20 +14,91 @@ Use this skill when asked to add, configure, update, or audit localization in **
14
14
 
15
15
  ---
16
16
 
17
- ## Agent Step 0: Verify & Install Shallok CLI
17
+ ## Agent Step 0: Mandatory Pre-Flight Checklist (Run Before ANY Code or Config Changes)
18
18
 
19
- **Before executing any localization commands, you (the AI Agent) MUST verify that `shallok` is available:**
19
+ **Before making ANY changes to a new repo or an existing repo, you (the AI Agent) MUST execute the following checks in order:**
20
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>`)*
21
+ ### 1. Check if Shallok is Installed
22
+ - Inspect `package.json` for `"shallok"` or `"@shallok/cli"` in `devDependencies` (or `dependencies`), or run:
23
+ ```bash
24
+ npx shallok --version
25
+ ```
26
+ - **If `shallok` is NOT installed, install it immediately into `devDependencies`:**
27
+ - If `pnpm-lock.yaml` exists: `pnpm add -D shallok`
28
+ - If `yarn.lock` exists: `yarn add -D shallok`
29
+ - If `bun.lockb` / `bun.lock` exists: `bun add -d shallok`
30
+ - Otherwise: `npm install -D shallok`
31
+
32
+ ### 2. Check if `localization.json` and `localization_base/` Exist
33
+ - Verify that `localization.json` exists in the project root.
34
+ - Verify that the `localization_base/` directory exists with `<source_locale>.json` and `metadata.json`.
35
+ - **If either does NOT exist, create them using Shallok:**
36
+ ```bash
37
+ shallok init --source en --locales kn,hi --framework react --yes
38
+ ```
39
+
40
+ ### 3. NEVER Delete `localization.json` or `localization_base/`
41
+ > [!CAUTION]
42
+ > **CRITICAL PERSISTENCE RULE: NEVER DELETE `localization.json` OR `localization_base/`!**
43
+ > - `localization.json` is the single source-of-truth project manifest.
44
+ > - `localization_base/` contains the canonical catalog (`<source_locale>.json`) with per-key version numbers (`key_version`), cryptographic content hashes (`sha256:`), source code occurrences, and enriched semantic context, alongside `metadata.json`.
45
+ > - **Under NO circumstances should you EVER delete `localization.json` or `localization_base/`**. Deleting them destroys the versioning history, wipes out human- and AI-enriched context, resets version counters, breaks incremental translation, and corrupts catalog synchronization.
46
+
47
+ ---
48
+
49
+ ## Core Architectural & Formatting Rules
50
+
51
+ ### Rule 1: Always Use Normalized Paths for Keys (Never Object-Based Paths)
52
+ - **Always use normalized dot-separated key paths**: e.g., `"auth.login.title"`, `"checkout.pay_now"`, `"settings.profile.change_password"`.
53
+ - **Never use nested object-based paths**: Do not structure keys or catalogs as nested JSON objects (e.g., `{ "auth": { "login": { "title": "..." } } }`). All keys in `localization_base/<source_locale>.json`, `messages/<locale>.json`, and runtime bundles MUST be flat normalized string paths.
54
+ - **If an existing project is using object-based keys**:
55
+ - **STOP and ask the user** for confirmation to flatten them into normalized dot-separated key paths before proceeding with extraction or catalog edits.
56
+ - Explain that normalized dot-paths are required for deterministic AST extraction, per-key versioning, and collision-free reconciliation.
57
+ - Upon user approval, migrate and flatten all nested keys to normalized dot-paths.
58
+
59
+ ### Rule 2: Always Use the `messages/` Directory Structure (Ask User & Migrate If Different)
60
+ - **Standard translations folder**: Shallok strictly standardizes on `messages/` for authoritative locale catalogs (`messages/<locale>.json`) and compiled runtime bundles (`messages/runtime/<locale>.json`).
61
+ - **If the project uses any other folder structure** (e.g., `locales/`, `src/locales/`, `translations/`, `lang/`, `src/i18n/locales/`):
62
+ - **STOP and ask the user** for approval to switch to the standardized `messages/` directory structure.
63
+ - Upon user approval, **migrate** all existing translation files into `messages/`, update framework configuration and import paths, reconcile existing strings into `localization_base/`, and clean up the old directory.
64
+
65
+ ### Rule 3: Check Context for All Keys in `localization_base/{source_locale}` Before Translating
66
+ - **Before generating any translations for any target locale**:
67
+ - Inspect all active keys in `localization_base/<source_locale>.json` (e.g., `localization_base/en.json`).
68
+ - Verify that **every key has meaningful, accurate semantic `context`**.
69
+ - If any key lacks context, has an empty context (`""`), or contains only generic AST descriptions (e.g., `"JSX text in button"`), you MUST inspect the component/screen and **generate rich semantic context for all such keys BEFORE generating translations**.
70
+ - Enrich context via:
71
+ ```bash
72
+ shallok context set <key> "<semantic_description>"
73
+ ```
74
+ or directly edit the `"context"` field in `localization_base/<source_locale>.json`.
75
+
76
+ ### Rule 4: Always Generate Translations from `localization_base/{source_locale}` and Its Context
77
+ - **Never translate raw strings in isolation**:
78
+ - All translations MUST be generated directly from `localization_base/<source_locale>.json`, reading BOTH the source string (`content`) and its semantic `context`.
79
+ - The `context` provides critical disambiguation (grammatical gender, button vs label vs heading, formality, technical terminology).
80
+ - Strictly preserve all interpolation tokens (`{userName}`, `{count}`, `{amount}`) exactly as formatted in the source `content`.
81
+
82
+ ### Rule 5: Migrate Legacy Base Locale References to Specified Structure
83
+ - **If the React app already has an existing localization setup**:
84
+ - Check how the base/source locale (`source_locale`, e.g., `en`) is imported and loaded.
85
+ - If any file (e.g. `src/i18n.ts`, `src/main.tsx`, `src/App.tsx`) is importing a legacy file (such as `src/locales/en.json`, `locales/en.json`, or arbitrary JSON files):
86
+ 1. **Reconcile strings** into `localization_base/<source_locale>.json` and `messages/<source_locale>.json`.
87
+ 2. **Update all code imports** to point to the standardized compiled runtime bundle (`messages/runtime/<locale>.json`) or the CDN loader.
88
+ 3. Remove or deprecate the legacy base locale file so that Shallok does NOT extract it as source code (preventing false occurrences like `"relative_file_path": "src/locales/en.json"`).
89
+
90
+ ### Rule 6: React Client Architecture: CDN-Backed Dynamic Loading (OTA Updates)
91
+ - **Suggest loading translations from a CDN for React SPAs**:
92
+ - In modern client web applications (Vite, Webpack SPAs), fetching translations from a CDN allows continuous translation updates without rebuilding or redeploying the web frontend.
93
+ - Recommend hosting compiled `messages/runtime/<locale>.json` on a CDN or cloud storage bucket (e.g. Cloudflare R2, AWS S3/CloudFront, Supabase Storage, Vercel Blob).
94
+ - **Environment Variables & Configuration**:
95
+ - Define `VITE_TRANSLATIONS_CDN_URL=https://cdn.yourdomain.com/locales` (or `REACT_APP_TRANSLATIONS_CDN_URL`) in `.env` and `.env.example`.
96
+ - **Prompt and ask the user to configure/update `VITE_TRANSLATIONS_CDN_URL`** with their actual CDN endpoint.
97
+ - **Resilient Runtime Loader with Local Offline Fallback**:
98
+ - Configure `src/i18n.ts` using `i18next-http-backend` or custom fetch to load from `${VITE_TRANSLATIONS_CDN_URL}/${locale}.json` with `localStorage` caching.
99
+ - Always bundle `messages/runtime/<locale>.json` locally as fallback resources, ensuring the application renders immediately before network requests complete.
100
+ - **Upload Script**:
101
+ - Suggest / scaffold an upload script (e.g., `scripts/upload-locales.mjs`) to publish compiled `messages/runtime/` dictionaries to the CDN.
31
102
 
32
103
  ---
33
104
 
@@ -38,7 +109,7 @@ Shallok pairs a deterministic AST CLI (`shallok`) with **the AI Agent as the sem
38
109
  1. **The CLI (`shallok`)** handles deterministic tasks:
39
110
  - Scaffolds `src/i18n.ts` configuring `react-i18next`.
40
111
  - 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`).
112
+ - Replaces user-facing strings and JSX elements with `{t('key')}` using normalized dot-separated key paths and imports `useTranslation` (`shallok extract --apply`).
42
113
  - Maintains per-key versioning and SHA-256 content hashes in `localization_base/`.
43
114
  - Compiles runtime message bundles to `messages/runtime/<locale>.json` (`shallok build`).
44
115
  - Validates 0 missing keys, 0 stale versions, and 0 broken placeholders (`shallok validate`).
@@ -59,6 +130,9 @@ shallok analyze --json
59
130
  ```
60
131
  - Verify framework is detected as `react`.
61
132
  - Check React version in `package.json` (`dependencies.react`).
133
+ - Check existing translation catalogs and folders (`locales/`, `src/locales/`, `messages/`).
134
+ - Check if existing base locale is referencing legacy files (e.g., `src/locales/en.json`, `locales/en.json`).
135
+ - Check if existing keys use object-based nesting or normalized dot-paths.
62
136
  - Identify source directory (typically `src/`) and entry file (`src/main.tsx`, `src/index.tsx`, or `src/App.tsx`).
63
137
  - Identify candidate React component files (`src/**/*.tsx`, `src/**/*.jsx`).
64
138
  - Note user-requested target locales (e.g. `kn`, `hi`, `fr`, `es`).
@@ -68,29 +142,36 @@ shallok analyze --json
68
142
  Present a concise plan to the developer:
69
143
  1. **Framework & Library**: React with `react-i18next` and `i18next`.
70
144
  2. **Locales**: Source locale (e.g. `en`) and target locales (e.g. `kn` Kannada, `hi` Hindi).
71
- 3. **Dependencies to Install**:
145
+ 3. **Directory & Legacy File Migration**:
146
+ - If non-standard locale folders or legacy base locale files exist (e.g. `src/locales/en.json`): Propose migrating to `messages/` and updating all import references to `messages/runtime/<locale>.json`.
147
+ - If object-based keys exist: Explicitly propose flattening to normalized dot-path keys and request user confirmation.
148
+ 4. **Loading Strategy Recommendation**:
149
+ - Propose loading translations from a CDN via `VITE_TRANSLATIONS_CDN_URL` with local fallback for rapid copy updates without rebuilding web bundles.
150
+ - Ask the user to configure their CDN endpoint in `.env`.
151
+ 5. **Dependencies to Install**:
72
152
  ```bash
73
153
  pnpm add i18next react-i18next
74
154
  ```
75
- 4. **Planned Scaffolding**:
155
+ 6. **Planned Scaffolding**:
76
156
  - `localization.json` (Project manifest)
77
- - `src/i18n.ts` (React-i18next configuration)
78
- - `localization_base/<source_locale>.json` & `metadata.json` (Canonical catalog & versions)
157
+ - `src/i18n.ts` (React-i18next configuration with CDN loader & local fallback)
158
+ - `.env` / `.env.example` (Configured with `VITE_TRANSLATIONS_CDN_URL`)
159
+ - `scripts/upload-locales.mjs` (Script to sync `messages/runtime/` to CDN)
160
+ - `localization_base/<source_locale>.json` & `metadata.json` (Canonical catalog & versions — **never delete**)
79
161
  - `messages/<locale>.json` (Target locale catalogs)
80
162
  - `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).
163
+ 7. **Entry Point Integration**: Adding `import './i18n';` in `src/main.tsx` (or `src/index.tsx`).
164
+ 8. Confirm with user before proceeding (or proceed if `--yes` / requested).
83
165
 
84
166
  ### Phase C: Initialize
85
167
  Initialize configuration and React scaffolding:
86
168
  ```bash
87
169
  shallok init --source en --locales kn,hi --framework react --yes
88
170
  ```
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
171
+ 1. If migrating from an existing non-standard folder (e.g., `locales/` or `src/locales/`), copy/migrate existing translations into `messages/` and reconcile into `localization_base/`.
172
+ 2. **Update all code references**: Replace legacy imports like `import en from './locales/en.json'` with `messages/runtime/` or CDN loader.
173
+ 3. Configure `.env` and `.env.example` with `VITE_TRANSLATIONS_CDN_URL` and ask the user to update it with their CDN URL.
174
+ 4. Scaffold `scripts/upload-locales.mjs` if CDN loading is chosen.
94
175
 
95
176
  Ensure React runtime dependencies are installed:
96
177
  ```bash
@@ -108,33 +189,33 @@ pnpm add i18next react-i18next
108
189
  ```
109
190
  This populates `localization_base/en.json` with extracted keys and initial AST locations.
110
191
 
111
- 3. **Enrich Context (Performed by AI Agent)**:
192
+ 3. **Mandatory Context Check & Enrichment (Performed by AI Agent)**:
112
193
  - 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:
194
+ - **Verify that every key has proper semantic context**.
195
+ - If any key lacks context or has only generic AST descriptions, inspect the React component code and enrich `context` with semantic clarity BEFORE proceeding to translation:
116
196
  ```bash
117
197
  shallok context set <key> "<semantic_description>"
118
198
  ```
119
199
  Or edit `"context"` directly in `localization_base/en.json`.
120
200
  - **Preservation Guarantee**: Shallok's reconciliation algorithm strictly preserves your enriched context across all future extractions.
121
201
 
122
- ### Phase E: Translate (AI-Driven)
202
+ ### Phase E: Translate (AI-Driven from `localization_base/{source_locale}` + Context)
123
203
  **No external API keys or LLM provider subscriptions are required.**
124
204
  You, as the AI coding agent, generate the translations directly:
125
205
 
126
- 1. **Check translation status**:
206
+ 1. **Verify Context First**: Ensure all keys in `localization_base/<source_locale>.json` have proper semantic context.
207
+ 2. **Check translation status**:
127
208
  ```bash
128
209
  shallok status --json
129
210
  ```
130
211
  Identify keys in `messages/<locale>.json` marked with `status: "missing"` or `status: "stale"`.
131
212
 
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.
213
+ 3. **Generate Translations from `localization_base/{source_locale}` and Its Context**:
214
+ - Translate each string into culturally authentic target language (e.g. Kannada, Hindi) reading source `content` AND its semantic `context` from `localization_base/<source_locale>.json`.
215
+ - Use the source `content` and your enriched `context` for accurate terminology and grammatical tone.
135
216
  - **Strict Rule**: Preserve all interpolation tokens (`{count}`, `{name}`, `{date}`) exactly as formatted in the source text.
136
217
 
137
- 3. **Update Target Locale Catalogs**:
218
+ 4. **Update Target Locale Catalogs**:
138
219
  Write directly into `messages/<locale>.json` or use:
139
220
  ```bash
140
221
  shallok entry set <locale> <key> "<translated_text>"
@@ -156,7 +237,7 @@ You, as the AI coding agent, generate the translations directly:
156
237
  ```bash
157
238
  shallok extract --apply
158
239
  ```
159
- This injects `const { t } = useTranslation();` and replaces hardcoded text with `{t('key')}`.
240
+ This injects `const { t } = useTranslation();` and replaces hardcoded text with `{t('key')}` using normalized dot-separated key paths.
160
241
 
161
242
  2. **Verify Entry Point Integration**:
162
243
  Ensure `src/main.tsx` or `src/index.tsx` imports the i18n configuration:
@@ -3,6 +3,11 @@
3
3
  ## Extraction Strategy
4
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
5
 
6
+ ## Normalized Dot-Paths for Keys (Never Object-Based)
7
+ - **Always use normalized dot-separated key paths**: e.g., `"checkout.pay_now"`, `"auth.login.title"`, `"dashboard.metrics.active_users"`.
8
+ - **Never use object-based or nested object paths**: Catalogs must never store nested object trees.
9
+ - **If an existing project uses object-based keys**: Ask the user for confirmation to flatten them to normalized dot-path keys before running extraction or migrating catalogs.
10
+
6
11
  ## What is Extracted
7
12
  1. **JSX Text Nodes**:
8
13
  - `<h1>Welcome</h1>` → `{t('home.welcome')}`
@@ -26,4 +31,4 @@ Shallok uses Babel AST parsing (`@babel/parser` and `@babel/traverse`) with full
26
31
  - Already localized calls: `t(...)`, `i18n.t(...)`.
27
32
 
28
33
  ## Dry-Run Mode
29
- Always use `localize extract --dry-run` to preview keys and occurrences before committing changes to source files.
34
+ Always use `shallok extract --dry-run` to preview keys and occurrences before committing changes to source files.
@@ -0,0 +1,59 @@
1
+ # Framework Adapters Reference
2
+
3
+ ## Loading Strategies: Local vs. CDN
4
+
5
+ | Framework Type | Recommended Strategy | Primary Rationale | Configuration & ENV |
6
+ | :--- | :--- | :--- | :--- |
7
+ | **Astro** (`astro:i18n`) | **Local** (`messages/runtime/`) | Static builds (SSG) & SSR; zero network hops, zero build dependency on external services. | Bundled in `src/i18n/utils.ts` |
8
+ | **Next.js** (`next-intl`) | **Local** (`messages/runtime/`) | Server Components & SSR; instant First Contentful Paint, zero latency in Node/Edge. | Bundled in `src/i18n/request.ts` |
9
+ | **Expo / React Native** | **CDN-Backed** (+ Local Fallback) | Instant Over-The-Air (OTA) translation & typo fixes without waiting for App Store review. | `EXPO_PUBLIC_TRANSLATIONS_CDN_URL` + AsyncStorage caching + local fallback |
10
+ | **React SPA** (Vite / CRA) | **CDN-Backed** (+ Local Fallback) | Instant copy updates without rebuilding web bundle. | `VITE_TRANSLATIONS_CDN_URL` + localStorage caching + local fallback |
11
+
12
+ ---
13
+
14
+ ## Supported Frameworks & Adapters
15
+
16
+ ### 1. React (`react-i18next`)
17
+ - **Initialization**: Generates `src/i18n.ts` configuring `i18next` with `initReactI18next`.
18
+ - **Runtime Messages**: Generates clean key-value message files in `messages/runtime/<locale>.json`.
19
+ - **CDN Loading**: Suggest `VITE_TRANSLATIONS_CDN_URL` in `.env` with local `messages/runtime/` fallback and `scripts/upload-locales.mjs`.
20
+ - **Legacy Migration**: If `src/main.tsx` or `src/i18n.ts` imported `src/locales/en.json`, migrate to `messages/runtime/` or CDN loader.
21
+ - **AST Transformation**:
22
+ - Adds `import { useTranslation } from 'react-i18next';`
23
+ - Injects `const { t } = useTranslation();` in components
24
+ - Replaces text with `{t('key')}` using normalized dot-separated key paths.
25
+
26
+ ### 2. Next.js (`next-intl`)
27
+ - **App Router Support**:
28
+ - Generates `src/i18n/routing.ts` defining `locales` and `defaultLocale`.
29
+ - Generates `src/i18n/request.ts` using `getRequestConfig` loading local `messages/runtime/<locale>.json`.
30
+ - **Runtime Messages**: Generates runtime message files in `messages/runtime/<locale>.json`.
31
+ - **Loading Strategy**: Local loading recommended for Server Components and SSR.
32
+ - **Legacy Migration**: If `src/i18n/request.ts` or `middleware.ts` imported old locale JSONs, update imports to `messages/runtime/<locale>.json`.
33
+ - **AST Transformation**:
34
+ - Adds `import { useTranslations } from 'next-intl';`
35
+ - Injects `const t = useTranslations();` in components
36
+ - Replaces text with `{t('key')}` using normalized dot-separated key paths.
37
+
38
+ ### 3. Expo / React Native (`expo-localization` + `react-i18next`)
39
+ - **Initialization**: Generates `i18n.ts` using `getLocales` from `expo-localization` and `i18next`.
40
+ - **Runtime Messages**: Generates runtime message files in `messages/runtime/<locale>.json`.
41
+ - **CDN Loading**: Suggest `EXPO_PUBLIC_TRANSLATIONS_CDN_URL` in `.env` with `AsyncStorage` caching and local `messages/runtime/` fallback.
42
+ - **Legacy Migration**: If `app/_layout.tsx` or `src/i18n.ts` imported `src/locales/en.json`, migrate to `messages/runtime/` or CDN loader.
43
+ - **AST Transformation**:
44
+ - Adds `import { useTranslation } from 'react-i18next';`
45
+ - Injects `const { t } = useTranslation();` in mobile components
46
+ - Replaces text inside `<Text>` and attributes like `placeholder` with `{t('key')}` using normalized dot-separated key paths.
47
+
48
+ ### 4. Astro (`astro:i18n`)
49
+ - **Initialization**: Generates `src/i18n/utils.ts` defining `locales`, `defaultLocale`, and `useTranslations` loading local `messages/runtime/<locale>.json`.
50
+ - **Runtime Messages**: Generates runtime message files in `messages/runtime/<locale>.json`.
51
+ - **Loading Strategy**: Local loading recommended for fast static SSG and hybrid SSR.
52
+ - **Legacy Migration**: If `src/i18n/utils.ts` or `.astro` files imported old locale JSONs, update imports to `messages/runtime/<locale>.json`.
53
+ - **Component Usage**:
54
+ - In Astro components frontmatter: `const t = await useTranslations(locale);`
55
+ - Renders `{t('key')}` in templates and islands using normalized dot-separated key paths.
56
+
57
+ ### 5. Vue (`vue-i18n`)
58
+ - **Initialization**: Generates `src/i18n.ts` using `createI18n`.
59
+ - **Runtime Messages**: Generates runtime message files in `messages/runtime/<locale>.json`.
@@ -1,22 +1,46 @@
1
1
  # React & react-i18next Technical Reference
2
2
 
3
- ## Configuration Pattern (`src/i18n.ts`)
4
- Shallok sets up a deterministic configuration importing compiled runtime message bundles from `messages/runtime/`:
3
+ ## Deployment Architecture: CDN-Backed Loading vs. Local Bundling
5
4
 
5
+ For React SPAs (Vite, Webpack), loading translations from a CDN allows continuous translation updates without redeploying the web frontend.
6
+
7
+ ### 1. CDN Dynamic Loading Pattern (Recommended for Web SPAs)
8
+
9
+ Configure `.env`:
10
+ ```env
11
+ VITE_TRANSLATIONS_CDN_URL=https://cdn.yourdomain.com/locales
12
+ ```
13
+
14
+ `src/i18n.ts`:
6
15
  ```typescript
7
16
  import i18n from 'i18next';
8
17
  import { initReactI18next } from 'react-i18next';
9
18
 
10
- import enMessages from '../messages/runtime/en.json';
11
- import knMessages from '../messages/runtime/kn.json';
12
- import hiMessages from '../messages/runtime/hi.json';
19
+ // Local bundled fallbacks (from our specified structure)
20
+ import enFallback from '../messages/runtime/en.json';
21
+ import knFallback from '../messages/runtime/kn.json';
22
+
23
+ const CDN_URL = import.meta.env.VITE_TRANSLATIONS_CDN_URL;
13
24
 
14
25
  const resources = {
15
- en: { translation: enMessages },
16
- kn: { translation: knMessages },
17
- hi: { translation: hiMessages },
26
+ en: { translation: enFallback },
27
+ kn: { translation: knFallback },
18
28
  };
19
29
 
30
+ export async function fetchRemoteTranslations(locale: string) {
31
+ if (!CDN_URL) return;
32
+ try {
33
+ const res = await fetch(`${CDN_URL}/${locale}.json`);
34
+ if (res.ok) {
35
+ const messages = await res.json();
36
+ i18n.addResourceBundle(locale, 'translation', messages, true, true);
37
+ localStorage.setItem(`translations_${locale}`, JSON.stringify(messages));
38
+ }
39
+ } catch (err) {
40
+ // Falls back seamlessly to bundled local messages
41
+ }
42
+ }
43
+
20
44
  i18n
21
45
  .use(initReactI18next)
22
46
  .init({
@@ -31,6 +55,28 @@ i18n
31
55
  export default i18n;
32
56
  ```
33
57
 
58
+ ### 2. Upload Script (`scripts/upload-locales.mjs`)
59
+ Suggest creating an upload script to sync `messages/runtime/` to CDN/bucket:
60
+ ```javascript
61
+ import fs from 'node:fs';
62
+ import path from 'node:path';
63
+
64
+ // Upload all JSON files in messages/runtime/ to Cloudflare R2 / S3 / Supabase Storage
65
+ const runtimeDir = path.resolve('messages/runtime');
66
+ const files = fs.readdirSync(runtimeDir);
67
+ for (const file of files) {
68
+ console.log(`Uploading ${file} to CDN...`);
69
+ }
70
+ ```
71
+
72
+ ### 3. Legacy Base Locale Migration
73
+ If existing code imported `src/locales/en.json`:
74
+ - Reconcile keys into `localization_base/en.json`.
75
+ - Update imports in `src/i18n.ts` and `src/main.tsx` to point to `../messages/runtime/en.json` (or CDN loader).
76
+ - Deprecate or remove `src/locales/en.json`.
77
+
78
+ ---
79
+
34
80
  ## Hook Usage (`useTranslation`)
35
81
  - Import: `import { useTranslation } from 'react-i18next';`
36
82
  - Call inside functional component: `const { t, i18n } = useTranslation();`