melaka 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +347 -0
- package/LICENSE +21 -0
- package/README.md +57 -0
- package/docs/AI_PROVIDERS.md +343 -0
- package/docs/ARCHITECTURE.md +512 -0
- package/docs/CLI.md +438 -0
- package/docs/CONFIGURATION.md +453 -0
- package/docs/INTEGRATION.md +477 -0
- package/docs/ROADMAP.md +248 -0
- package/package.json +46 -0
- package/packages/ai/README.md +43 -0
- package/packages/ai/package.json +42 -0
- package/packages/ai/src/facade.ts +120 -0
- package/packages/ai/src/index.ts +34 -0
- package/packages/ai/src/prompt.ts +117 -0
- package/packages/ai/src/providers/gemini.ts +185 -0
- package/packages/ai/src/providers/index.ts +9 -0
- package/packages/ai/src/types.ts +134 -0
- package/packages/ai/tsconfig.json +19 -0
- package/packages/cli/README.md +70 -0
- package/packages/cli/package.json +44 -0
- package/packages/cli/src/cli.ts +30 -0
- package/packages/cli/src/commands/deploy.ts +115 -0
- package/packages/cli/src/commands/index.ts +9 -0
- package/packages/cli/src/commands/init.ts +107 -0
- package/packages/cli/src/commands/status.ts +73 -0
- package/packages/cli/src/commands/translate.ts +92 -0
- package/packages/cli/src/commands/validate.ts +69 -0
- package/packages/cli/tsconfig.json +19 -0
- package/packages/core/README.md +46 -0
- package/packages/core/package.json +50 -0
- package/packages/core/src/config.ts +241 -0
- package/packages/core/src/index.ts +111 -0
- package/packages/core/src/schema-generator.ts +263 -0
- package/packages/core/src/schemas.ts +126 -0
- package/packages/core/src/types.ts +481 -0
- package/packages/core/src/utils.ts +343 -0
- package/packages/core/tsconfig.json +19 -0
- package/packages/firestore/README.md +60 -0
- package/packages/firestore/package.json +48 -0
- package/packages/firestore/src/generator.ts +270 -0
- package/packages/firestore/src/i18n.ts +262 -0
- package/packages/firestore/src/index.ts +54 -0
- package/packages/firestore/src/processor.ts +245 -0
- package/packages/firestore/src/queue.ts +202 -0
- package/packages/firestore/src/task-handler.ts +164 -0
- package/packages/firestore/tsconfig.json +19 -0
- package/pnpm-workspace.yaml +2 -0
- package/turbo.json +31 -0
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
# Integration Guide
|
|
2
|
+
|
|
3
|
+
This guide walks you through integrating Melaka into your Firebase project.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Firebase project with Firestore enabled
|
|
8
|
+
- Firebase CLI installed (`npm install -g firebase-tools`)
|
|
9
|
+
- Cloud Functions enabled (requires Blaze plan for external API calls)
|
|
10
|
+
- Node.js 18+
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
|
|
14
|
+
### 1. Install Melaka CLI
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g melaka
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### 2. Initialize in Your Project
|
|
21
|
+
|
|
22
|
+
Navigate to your Firebase project root (where `firebase.json` lives):
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
cd my-firebase-project
|
|
26
|
+
melaka init
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
This creates `melaka.config.ts`:
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { defineConfig } from 'melaka';
|
|
33
|
+
|
|
34
|
+
export default defineConfig({
|
|
35
|
+
languages: ['ms-MY', 'zh-CN'],
|
|
36
|
+
|
|
37
|
+
ai: {
|
|
38
|
+
provider: 'gemini',
|
|
39
|
+
model: 'gemini-2.5-flash',
|
|
40
|
+
apiKeySecret: 'GEMINI_API_KEY',
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
collections: [
|
|
44
|
+
{
|
|
45
|
+
path: 'articles',
|
|
46
|
+
fields: ['title', 'content'],
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 3. Configure Your Collections
|
|
53
|
+
|
|
54
|
+
Edit `melaka.config.ts` to match your Firestore structure:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { defineConfig } from 'melaka';
|
|
58
|
+
|
|
59
|
+
export default defineConfig({
|
|
60
|
+
languages: ['ms-MY', 'zh-CN', 'ja-JP'],
|
|
61
|
+
|
|
62
|
+
ai: {
|
|
63
|
+
provider: 'gemini',
|
|
64
|
+
model: 'gemini-2.5-flash',
|
|
65
|
+
apiKeySecret: 'GEMINI_API_KEY',
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
region: 'asia-southeast1', // Match your Firestore region
|
|
69
|
+
|
|
70
|
+
collections: [
|
|
71
|
+
{
|
|
72
|
+
path: 'products',
|
|
73
|
+
fields: ['name', 'description', 'features'],
|
|
74
|
+
prompt: 'E-commerce product descriptions. Keep brand names unchanged.',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
path: 'articles',
|
|
78
|
+
fields: ['title', 'content', 'summary'],
|
|
79
|
+
prompt: 'Blog articles. Maintain markdown formatting.',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
path: 'categories',
|
|
83
|
+
fields: ['name', 'description'],
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
|
|
87
|
+
glossary: {
|
|
88
|
+
'Acme Store': 'Acme Store', // Don't translate brand
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 4. Set Up AI Provider API Key
|
|
94
|
+
|
|
95
|
+
Store your API key as a Firebase secret:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# For Gemini (recommended)
|
|
99
|
+
firebase functions:secrets:set GEMINI_API_KEY
|
|
100
|
+
|
|
101
|
+
# Or for OpenAI
|
|
102
|
+
firebase functions:secrets:set OPENAI_API_KEY
|
|
103
|
+
|
|
104
|
+
# Or for Claude
|
|
105
|
+
firebase functions:secrets:set ANTHROPIC_API_KEY
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### 5. Deploy
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
melaka deploy
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
This command:
|
|
115
|
+
1. Reads your `melaka.config.ts`
|
|
116
|
+
2. Generates Cloud Functions code in your `functions/` directory
|
|
117
|
+
3. Deploys the functions to Firebase
|
|
118
|
+
|
|
119
|
+
### 6. Done!
|
|
120
|
+
|
|
121
|
+
Your translations will now happen automatically when documents are created or updated.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## What Gets Deployed
|
|
126
|
+
|
|
127
|
+
After `melaka deploy`, your `functions/` folder will have:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
functions/
|
|
131
|
+
├── src/
|
|
132
|
+
│ ├── index.ts # Your existing code (unchanged)
|
|
133
|
+
│ └── melaka/ # Generated by Melaka
|
|
134
|
+
│ ├── triggers.ts # Firestore triggers for each collection
|
|
135
|
+
│ ├── task-handler.ts # Cloud Task processor
|
|
136
|
+
│ └── index.ts # Exports all Melaka functions
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Generated Functions
|
|
140
|
+
|
|
141
|
+
For each collection in your config, Melaka generates:
|
|
142
|
+
|
|
143
|
+
| Function | Type | Purpose |
|
|
144
|
+
|----------|------|---------|
|
|
145
|
+
| `melakaTranslate{Collection}` | `onDocumentWritten` | Triggered when doc changes, enqueues translation |
|
|
146
|
+
| `melakaTranslateTask` | `onTaskDispatched` | Processes translation tasks asynchronously |
|
|
147
|
+
|
|
148
|
+
### Example: Generated Trigger
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// Auto-generated: melaka/triggers.ts
|
|
152
|
+
import { onDocumentWritten } from 'firebase-functions/v2/firestore';
|
|
153
|
+
|
|
154
|
+
export const melakaTranslateProducts = onDocumentWritten(
|
|
155
|
+
{ document: 'products/{docId}', region: 'asia-southeast1' },
|
|
156
|
+
async (event) => {
|
|
157
|
+
if (!event.data?.after.exists) return; // Skip deletes
|
|
158
|
+
|
|
159
|
+
await enqueueTranslation({
|
|
160
|
+
collection: 'products',
|
|
161
|
+
documentId: event.params.docId,
|
|
162
|
+
languages: ['ms-MY', 'zh-CN', 'ja-JP'],
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
);
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## How Cloud Tasks Work
|
|
171
|
+
|
|
172
|
+
Melaka uses Firebase Cloud Tasks for reliable, async translation processing.
|
|
173
|
+
|
|
174
|
+
### Why Cloud Tasks?
|
|
175
|
+
|
|
176
|
+
- **No timeout issues** — Triggers return immediately, translation happens async
|
|
177
|
+
- **Automatic retries** — Failed translations retry with exponential backoff
|
|
178
|
+
- **Rate limiting** — Prevents overwhelming the AI API
|
|
179
|
+
- **Reliable delivery** — Tasks persist even if functions restart
|
|
180
|
+
|
|
181
|
+
### Automatic Setup
|
|
182
|
+
|
|
183
|
+
**You don't need to configure Cloud Tasks manually.** Firebase Functions v2's `onTaskDispatched` automatically:
|
|
184
|
+
|
|
185
|
+
1. Creates the task queue when deployed
|
|
186
|
+
2. Configures HTTP targets and authentication
|
|
187
|
+
3. Handles IAM permissions
|
|
188
|
+
|
|
189
|
+
### Task Flow
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
193
|
+
│ Document │ │ Firestore │ │ Cloud Task │
|
|
194
|
+
│ Updated │────▶│ Trigger │────▶│ Enqueued │
|
|
195
|
+
└─────────────────┘ └─────────────────┘ └────────┬────────┘
|
|
196
|
+
│
|
|
197
|
+
┌─────────────────┐ │
|
|
198
|
+
│ i18n Subcolls │ │
|
|
199
|
+
│ Updated │◀─────────────┤
|
|
200
|
+
└─────────────────┘ │
|
|
201
|
+
▼
|
|
202
|
+
┌─────────────────┐ ┌─────────────────┐
|
|
203
|
+
│ AI │ │ Task Handler │
|
|
204
|
+
│ Translation │◀────│ Processes │
|
|
205
|
+
└─────────────────┘ └─────────────────┘
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Task Configuration
|
|
209
|
+
|
|
210
|
+
Default settings (configurable in `melaka.config.ts`):
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
{
|
|
214
|
+
retryConfig: {
|
|
215
|
+
maxAttempts: 3,
|
|
216
|
+
minBackoffSeconds: 60,
|
|
217
|
+
maxBackoffSeconds: 300,
|
|
218
|
+
},
|
|
219
|
+
rateLimits: {
|
|
220
|
+
maxConcurrentDispatches: 10,
|
|
221
|
+
},
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Translation Storage
|
|
228
|
+
|
|
229
|
+
Translations are stored as subcollections under each document:
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
/products/product-123 ← Source document
|
|
233
|
+
/products/product-123/i18n/ms-MY ← Malay translation
|
|
234
|
+
/products/product-123/i18n/zh-CN ← Chinese translation
|
|
235
|
+
/products/product-123/i18n/ja-JP ← Japanese translation
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Translation Document Structure
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
// /products/product-123/i18n/ms-MY
|
|
242
|
+
{
|
|
243
|
+
// Translated fields
|
|
244
|
+
name: "Telefon Pintar XYZ",
|
|
245
|
+
description: "Telefon pintar terbaru dengan...",
|
|
246
|
+
features: ["Kamera 48MP", "Bateri 5000mAh"],
|
|
247
|
+
|
|
248
|
+
// Non-translatable fields (copied from source)
|
|
249
|
+
price: 999,
|
|
250
|
+
sku: "XYZ-001",
|
|
251
|
+
category_ref: "/categories/electronics",
|
|
252
|
+
|
|
253
|
+
// Melaka metadata
|
|
254
|
+
_melaka: {
|
|
255
|
+
source_hash: "a1b2c3d4...",
|
|
256
|
+
translated_at: Timestamp,
|
|
257
|
+
model: "gemini-2.5-flash",
|
|
258
|
+
status: "completed",
|
|
259
|
+
reviewed: false,
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Reading Translations in Your App
|
|
267
|
+
|
|
268
|
+
### Web/Mobile Client
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
import { doc, getDoc } from 'firebase/firestore';
|
|
272
|
+
|
|
273
|
+
async function getProduct(productId: string, locale: string) {
|
|
274
|
+
// Get translated version
|
|
275
|
+
const i18nRef = doc(db, 'products', productId, 'i18n', locale);
|
|
276
|
+
const i18nSnap = await getDoc(i18nRef);
|
|
277
|
+
|
|
278
|
+
if (i18nSnap.exists()) {
|
|
279
|
+
return i18nSnap.data();
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Fallback to source document
|
|
283
|
+
const sourceRef = doc(db, 'products', productId);
|
|
284
|
+
const sourceSnap = await getDoc(sourceRef);
|
|
285
|
+
return sourceSnap.data();
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### With Fallback Helper
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
async function getLocalizedDoc(
|
|
293
|
+
collection: string,
|
|
294
|
+
docId: string,
|
|
295
|
+
locale: string,
|
|
296
|
+
fallbackLocale = 'en'
|
|
297
|
+
) {
|
|
298
|
+
// Try requested locale
|
|
299
|
+
const i18nSnap = await getDoc(
|
|
300
|
+
doc(db, collection, docId, 'i18n', locale)
|
|
301
|
+
);
|
|
302
|
+
if (i18nSnap.exists()) return i18nSnap.data();
|
|
303
|
+
|
|
304
|
+
// Try fallback locale
|
|
305
|
+
if (locale !== fallbackLocale) {
|
|
306
|
+
const fallbackSnap = await getDoc(
|
|
307
|
+
doc(db, collection, docId, 'i18n', fallbackLocale)
|
|
308
|
+
);
|
|
309
|
+
if (fallbackSnap.exists()) return fallbackSnap.data();
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Return source document
|
|
313
|
+
const sourceSnap = await getDoc(doc(db, collection, docId));
|
|
314
|
+
return sourceSnap.data();
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## Firestore Security Rules
|
|
321
|
+
|
|
322
|
+
Add rules to protect i18n subcollections:
|
|
323
|
+
|
|
324
|
+
```javascript
|
|
325
|
+
rules_version = '2';
|
|
326
|
+
service cloud.firestore {
|
|
327
|
+
match /databases/{database}/documents {
|
|
328
|
+
|
|
329
|
+
// Your existing rules for main collections
|
|
330
|
+
match /products/{productId} {
|
|
331
|
+
allow read: if true;
|
|
332
|
+
allow write: if request.auth != null;
|
|
333
|
+
|
|
334
|
+
// i18n subcollection: read-only for clients
|
|
335
|
+
match /i18n/{locale} {
|
|
336
|
+
allow read: if true;
|
|
337
|
+
allow write: if false; // Only Cloud Functions can write
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
match /articles/{articleId} {
|
|
342
|
+
allow read: if true;
|
|
343
|
+
allow write: if request.auth != null;
|
|
344
|
+
|
|
345
|
+
match /i18n/{locale} {
|
|
346
|
+
allow read: if true;
|
|
347
|
+
allow write: if false;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## Manual Translation
|
|
357
|
+
|
|
358
|
+
For existing documents or re-translation:
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
# Translate all documents in a collection
|
|
362
|
+
melaka translate --collection products
|
|
363
|
+
|
|
364
|
+
# Translate specific language only
|
|
365
|
+
melaka translate --collection products --language ms-MY
|
|
366
|
+
|
|
367
|
+
# Force re-translate (ignore content hash)
|
|
368
|
+
melaka translate --collection products --force
|
|
369
|
+
|
|
370
|
+
# Dry run (show what would be translated)
|
|
371
|
+
melaka translate --collection products --dry-run
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Monitoring
|
|
377
|
+
|
|
378
|
+
### Check Translation Status
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
melaka status
|
|
382
|
+
|
|
383
|
+
# Output:
|
|
384
|
+
# products
|
|
385
|
+
# ms-MY: 142/150 (94.7%) ✓ 142 ✗ 3 ⏳ 5
|
|
386
|
+
# zh-CN: 150/150 (100%) ✓ 150 ✗ 0 ⏳ 0
|
|
387
|
+
# ja-JP: 148/150 (98.7%) ✓ 148 ✗ 2 ⏳ 0
|
|
388
|
+
#
|
|
389
|
+
# articles
|
|
390
|
+
# ms-MY: 45/50 (90%) ✓ 45 ✗ 0 ⏳ 5
|
|
391
|
+
# ...
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Retry Failed Translations
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
# Retry all failed
|
|
398
|
+
melaka retry
|
|
399
|
+
|
|
400
|
+
# Retry specific collection/language
|
|
401
|
+
melaka retry --collection products --language ms-MY
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
## Project Structure Example
|
|
407
|
+
|
|
408
|
+
After integration, your project looks like:
|
|
409
|
+
|
|
410
|
+
```
|
|
411
|
+
my-firebase-project/
|
|
412
|
+
├── firebase.json
|
|
413
|
+
├── firestore.rules
|
|
414
|
+
├── melaka.config.ts # Your Melaka configuration
|
|
415
|
+
├── functions/
|
|
416
|
+
│ ├── package.json
|
|
417
|
+
│ ├── src/
|
|
418
|
+
│ │ ├── index.ts # Your existing functions
|
|
419
|
+
│ │ └── melaka/ # Generated by Melaka
|
|
420
|
+
│ │ ├── index.ts
|
|
421
|
+
│ │ ├── triggers.ts
|
|
422
|
+
│ │ └── task-handler.ts
|
|
423
|
+
│ └── tsconfig.json
|
|
424
|
+
└── ...
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## Updating Configuration
|
|
430
|
+
|
|
431
|
+
When you change `melaka.config.ts`:
|
|
432
|
+
|
|
433
|
+
```bash
|
|
434
|
+
# Re-deploy with new config
|
|
435
|
+
melaka deploy
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
This regenerates the Cloud Functions and redeploys.
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
## Troubleshooting
|
|
443
|
+
|
|
444
|
+
### "Function deployment failed"
|
|
445
|
+
|
|
446
|
+
- Ensure you're on Blaze plan (required for external API calls)
|
|
447
|
+
- Check that your Firebase CLI is logged in: `firebase login`
|
|
448
|
+
- Verify region matches your Firestore region
|
|
449
|
+
|
|
450
|
+
### "API key not found"
|
|
451
|
+
|
|
452
|
+
- Set the secret: `firebase functions:secrets:set GEMINI_API_KEY`
|
|
453
|
+
- Ensure `apiKeySecret` in config matches the secret name
|
|
454
|
+
|
|
455
|
+
### "Translations not appearing"
|
|
456
|
+
|
|
457
|
+
- Check Cloud Functions logs: `firebase functions:log`
|
|
458
|
+
- Verify the collection path matches your Firestore structure
|
|
459
|
+
- Run `melaka status` to see pending/failed translations
|
|
460
|
+
|
|
461
|
+
### "Rate limit exceeded"
|
|
462
|
+
|
|
463
|
+
- Reduce `maxConcurrency` in config:
|
|
464
|
+
```typescript
|
|
465
|
+
defaults: {
|
|
466
|
+
maxConcurrency: 5, // Lower from default 10
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## Next Steps
|
|
473
|
+
|
|
474
|
+
- [Configuration Reference](./CONFIGURATION.md) — All config options
|
|
475
|
+
- [CLI Reference](./CLI.md) — Available commands
|
|
476
|
+
- [AI Providers](./AI_PROVIDERS.md) — Provider-specific setup
|
|
477
|
+
- [Architecture](./ARCHITECTURE.md) — System design details
|
package/docs/ROADMAP.md
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
This document outlines the planned development phases for Melaka.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Current Status: 🚧 Planning
|
|
8
|
+
|
|
9
|
+
We're in the architecture and planning phase. No code has been written yet.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Phase 1: MVP (v0.1.0)
|
|
14
|
+
|
|
15
|
+
**Goal:** Minimal viable product that can translate Firestore documents.
|
|
16
|
+
|
|
17
|
+
### Core Features
|
|
18
|
+
|
|
19
|
+
- [ ] **@melaka/core**
|
|
20
|
+
- [ ] Config file parsing (`melaka.config.ts`)
|
|
21
|
+
- [ ] TypeScript types and interfaces
|
|
22
|
+
- [ ] Zod schema generation from field types
|
|
23
|
+
- [ ] Content hashing for change detection
|
|
24
|
+
- [ ] Glossary handling
|
|
25
|
+
|
|
26
|
+
- [ ] **@melaka/ai**
|
|
27
|
+
- [ ] Gemini adapter (primary)
|
|
28
|
+
- [ ] Translation facade with structured output
|
|
29
|
+
- [ ] Prompt construction with glossary
|
|
30
|
+
|
|
31
|
+
- [ ] **@melaka/firestore**
|
|
32
|
+
- [ ] i18n subcollection read/write
|
|
33
|
+
- [ ] Cloud Task handler for translations
|
|
34
|
+
- [ ] Trigger generator for `onDocumentWritten`
|
|
35
|
+
- [ ] Batch processing with rate limiting
|
|
36
|
+
|
|
37
|
+
- [ ] **@melaka/cli**
|
|
38
|
+
- [ ] `melaka init` — Create config file
|
|
39
|
+
- [ ] `melaka deploy` — Deploy triggers
|
|
40
|
+
- [ ] `melaka translate` — Manual translation
|
|
41
|
+
- [ ] `melaka status` — Check progress
|
|
42
|
+
|
|
43
|
+
### Documentation
|
|
44
|
+
|
|
45
|
+
- [ ] README with quick start
|
|
46
|
+
- [ ] Architecture documentation
|
|
47
|
+
- [ ] Configuration reference
|
|
48
|
+
- [ ] Basic examples
|
|
49
|
+
|
|
50
|
+
### Milestone
|
|
51
|
+
|
|
52
|
+
✅ MVP is complete when you can:
|
|
53
|
+
1. Run `melaka init` in a Firebase project
|
|
54
|
+
2. Configure collections in `melaka.config.ts`
|
|
55
|
+
3. Run `melaka deploy` to deploy triggers
|
|
56
|
+
4. See automatic translations in `i18n` subcollections
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Phase 2: Production Ready (v0.2.0)
|
|
61
|
+
|
|
62
|
+
**Goal:** Ready for production use with reliability features.
|
|
63
|
+
|
|
64
|
+
### Features
|
|
65
|
+
|
|
66
|
+
- [ ] **Additional AI Providers**
|
|
67
|
+
- [ ] OpenAI adapter
|
|
68
|
+
- [ ] Claude adapter
|
|
69
|
+
|
|
70
|
+
- [ ] **Reliability**
|
|
71
|
+
- [ ] Retry logic with exponential backoff
|
|
72
|
+
- [ ] Error recording and status tracking
|
|
73
|
+
- [ ] `melaka retry` command
|
|
74
|
+
|
|
75
|
+
- [ ] **Monitoring**
|
|
76
|
+
- [ ] Detailed status output
|
|
77
|
+
- [ ] Progress tracking
|
|
78
|
+
- [ ] JSON output for CI/CD
|
|
79
|
+
|
|
80
|
+
- [ ] **CLI Improvements**
|
|
81
|
+
- [ ] `melaka validate` — Config validation
|
|
82
|
+
- [ ] `melaka cleanup` — Remove old translations
|
|
83
|
+
- [ ] `--dry-run` flag for all commands
|
|
84
|
+
- [ ] Verbose and quiet modes
|
|
85
|
+
|
|
86
|
+
### Documentation
|
|
87
|
+
|
|
88
|
+
- [ ] AI provider comparison and setup
|
|
89
|
+
- [ ] Troubleshooting guide
|
|
90
|
+
- [ ] CI/CD integration guide
|
|
91
|
+
|
|
92
|
+
### Milestone
|
|
93
|
+
|
|
94
|
+
✅ Phase 2 is complete when Melaka can be used in production with confidence.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Phase 3: Developer Experience (v0.3.0)
|
|
99
|
+
|
|
100
|
+
**Goal:** Great developer experience and tooling.
|
|
101
|
+
|
|
102
|
+
### Features
|
|
103
|
+
|
|
104
|
+
- [ ] **Collection Groups**
|
|
105
|
+
- [ ] Support for `isCollectionGroup: true`
|
|
106
|
+
- [ ] Subcollection translation
|
|
107
|
+
|
|
108
|
+
- [ ] **Export/Import**
|
|
109
|
+
- [ ] `melaka export` — Export translations to JSON/CSV
|
|
110
|
+
- [ ] `melaka import` — Import reviewed translations
|
|
111
|
+
- [ ] Human review workflow support
|
|
112
|
+
|
|
113
|
+
- [ ] **Field Mappings**
|
|
114
|
+
- [ ] Detailed field configuration
|
|
115
|
+
- [ ] Field-level descriptions for AI context
|
|
116
|
+
- [ ] Custom schema type overrides
|
|
117
|
+
|
|
118
|
+
- [ ] **Local Development**
|
|
119
|
+
- [ ] Firebase emulator support
|
|
120
|
+
- [ ] Local translation preview
|
|
121
|
+
- [ ] Watch mode for development
|
|
122
|
+
|
|
123
|
+
### Documentation
|
|
124
|
+
|
|
125
|
+
- [ ] Advanced configuration examples
|
|
126
|
+
- [ ] Human review workflow guide
|
|
127
|
+
- [ ] Local development guide
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Phase 4: Dashboard (v0.4.0)
|
|
132
|
+
|
|
133
|
+
**Goal:** Web UI for translation management.
|
|
134
|
+
|
|
135
|
+
### Features
|
|
136
|
+
|
|
137
|
+
- [ ] **Review Dashboard**
|
|
138
|
+
- [ ] Web interface for reviewing translations
|
|
139
|
+
- [ ] Side-by-side source/translation view
|
|
140
|
+
- [ ] Mark as reviewed functionality
|
|
141
|
+
- [ ] Edit and save translations
|
|
142
|
+
|
|
143
|
+
- [ ] **Analytics**
|
|
144
|
+
- [ ] Translation statistics
|
|
145
|
+
- [ ] Cost tracking
|
|
146
|
+
- [ ] Error monitoring
|
|
147
|
+
|
|
148
|
+
- [ ] **Team Features**
|
|
149
|
+
- [ ] Multiple reviewers
|
|
150
|
+
- [ ] Review assignments
|
|
151
|
+
- [ ] Comment system
|
|
152
|
+
|
|
153
|
+
### Technical
|
|
154
|
+
|
|
155
|
+
- [ ] React/Next.js dashboard
|
|
156
|
+
- [ ] Firebase Auth integration
|
|
157
|
+
- [ ] Hosted version option
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Phase 5: Enterprise (v1.0.0)
|
|
162
|
+
|
|
163
|
+
**Goal:** Enterprise-ready features for large-scale deployments.
|
|
164
|
+
|
|
165
|
+
### Features
|
|
166
|
+
|
|
167
|
+
- [ ] **Translation Memory**
|
|
168
|
+
- [ ] Store and reuse translations
|
|
169
|
+
- [ ] Similarity matching
|
|
170
|
+
- [ ] Cost savings through reuse
|
|
171
|
+
|
|
172
|
+
- [ ] **Advanced Glossary**
|
|
173
|
+
- [ ] Glossary management UI
|
|
174
|
+
- [ ] Import from industry standards (TBX)
|
|
175
|
+
- [ ] Per-language glossaries
|
|
176
|
+
|
|
177
|
+
- [ ] **Compliance**
|
|
178
|
+
- [ ] Audit logging
|
|
179
|
+
- [ ] Data residency options
|
|
180
|
+
- [ ] SSO integration
|
|
181
|
+
|
|
182
|
+
- [ ] **Performance**
|
|
183
|
+
- [ ] Incremental field translation
|
|
184
|
+
- [ ] Parallel processing improvements
|
|
185
|
+
- [ ] Large document handling
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Future Ideas
|
|
190
|
+
|
|
191
|
+
These are ideas for future consideration, not committed features:
|
|
192
|
+
|
|
193
|
+
### Database Adapters
|
|
194
|
+
- Supabase/PostgreSQL adapter
|
|
195
|
+
- MongoDB adapter
|
|
196
|
+
- PlanetScale adapter
|
|
197
|
+
|
|
198
|
+
### Integrations
|
|
199
|
+
- GitHub Action for CI/CD
|
|
200
|
+
- VS Code extension
|
|
201
|
+
- Slack notifications
|
|
202
|
+
|
|
203
|
+
### AI Features
|
|
204
|
+
- Quality scoring
|
|
205
|
+
- Auto-detect source language
|
|
206
|
+
- Translation suggestions
|
|
207
|
+
- Custom fine-tuned models
|
|
208
|
+
|
|
209
|
+
### Localization
|
|
210
|
+
- RTL language support
|
|
211
|
+
- Pluralization rules
|
|
212
|
+
- Date/number formatting
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Contributing
|
|
217
|
+
|
|
218
|
+
We welcome contributions! See [CONTRIBUTING.md](../CONTRIBUTING.md) for guidelines.
|
|
219
|
+
|
|
220
|
+
### Priority Areas
|
|
221
|
+
|
|
222
|
+
1. **Core functionality** — Help build the MVP
|
|
223
|
+
2. **Documentation** — Improve docs and examples
|
|
224
|
+
3. **Testing** — Add unit and integration tests
|
|
225
|
+
4. **AI adapters** — Add OpenAI and Claude support
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Release Schedule
|
|
230
|
+
|
|
231
|
+
| Version | Target | Focus |
|
|
232
|
+
|---------|--------|-------|
|
|
233
|
+
| v0.1.0 | Q2 2026 | MVP |
|
|
234
|
+
| v0.2.0 | Q2 2026 | Production ready |
|
|
235
|
+
| v0.3.0 | Q3 2026 | Developer experience |
|
|
236
|
+
| v0.4.0 | Q3 2026 | Dashboard |
|
|
237
|
+
| v1.0.0 | Q4 2026 | Enterprise |
|
|
238
|
+
|
|
239
|
+
*Dates are estimates and subject to change.*
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Feedback
|
|
244
|
+
|
|
245
|
+
Have ideas or feature requests?
|
|
246
|
+
|
|
247
|
+
- Open an issue on [GitHub](https://github.com/rizahassan/melaka/issues)
|
|
248
|
+
- Start a discussion in [GitHub Discussions](https://github.com/rizahassan/melaka/discussions)
|