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,453 @@
|
|
|
1
|
+
# Configuration Reference
|
|
2
|
+
|
|
3
|
+
This document describes the configuration options for Melaka.
|
|
4
|
+
|
|
5
|
+
## Config File
|
|
6
|
+
|
|
7
|
+
Melaka uses a TypeScript configuration file (`melaka.config.ts`) at the root of your Firebase project.
|
|
8
|
+
|
|
9
|
+
### Basic Example
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { defineConfig } from 'melaka';
|
|
13
|
+
|
|
14
|
+
export default defineConfig({
|
|
15
|
+
languages: ['ms-MY', 'zh-CN', 'ja-JP'],
|
|
16
|
+
|
|
17
|
+
ai: {
|
|
18
|
+
provider: 'gemini',
|
|
19
|
+
model: 'gemini-2.5-flash',
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
collections: [
|
|
23
|
+
{
|
|
24
|
+
path: 'articles',
|
|
25
|
+
fields: ['title', 'content'],
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
});
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Full Example
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { defineConfig } from 'melaka';
|
|
35
|
+
|
|
36
|
+
export default defineConfig({
|
|
37
|
+
// Target languages for translation
|
|
38
|
+
languages: ['ms-MY', 'zh-CN', 'ja-JP'],
|
|
39
|
+
|
|
40
|
+
// AI provider configuration
|
|
41
|
+
ai: {
|
|
42
|
+
provider: 'gemini', // 'gemini' | 'openai' | 'claude'
|
|
43
|
+
model: 'gemini-2.5-flash', // Model name
|
|
44
|
+
temperature: 0.3, // 0-1, lower = more consistent
|
|
45
|
+
apiKeySecret: 'GEMINI_API_KEY', // Firebase secret name
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
// Firebase region for deployed functions
|
|
49
|
+
region: 'asia-southeast1',
|
|
50
|
+
|
|
51
|
+
// Default batch processing settings
|
|
52
|
+
defaults: {
|
|
53
|
+
batchSize: 20,
|
|
54
|
+
maxConcurrency: 10,
|
|
55
|
+
forceUpdate: false,
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
// Shared glossary (applies to all collections)
|
|
59
|
+
glossary: {
|
|
60
|
+
'checkout': 'checkout',
|
|
61
|
+
'cart': 'cart',
|
|
62
|
+
'wishlist': 'wishlist',
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
// Collections to translate
|
|
66
|
+
collections: [
|
|
67
|
+
{
|
|
68
|
+
path: 'articles',
|
|
69
|
+
fields: ['title', 'content', 'summary'],
|
|
70
|
+
prompt: 'This is blog content for an e-commerce platform.',
|
|
71
|
+
glossary: {
|
|
72
|
+
'sale': 'jualan',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
path: 'products',
|
|
77
|
+
fields: ['name', 'description'],
|
|
78
|
+
batchSize: 10,
|
|
79
|
+
maxConcurrency: 5,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
path: 'notifications',
|
|
83
|
+
isCollectionGroup: true, // For subcollections
|
|
84
|
+
fields: ['title', 'body', 'message'],
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Configuration Options
|
|
93
|
+
|
|
94
|
+
### Root Options
|
|
95
|
+
|
|
96
|
+
| Option | Type | Required | Description |
|
|
97
|
+
|--------|------|----------|-------------|
|
|
98
|
+
| `languages` | `string[]` | ✅ | Target language codes (BCP 47 format) |
|
|
99
|
+
| `ai` | `AIConfig` | ✅ | AI provider configuration |
|
|
100
|
+
| `region` | `string` | ❌ | Firebase region (default: `us-central1`) |
|
|
101
|
+
| `defaults` | `DefaultsConfig` | ❌ | Default settings for all collections |
|
|
102
|
+
| `glossary` | `Record<string, string>` | ❌ | Shared glossary for all collections |
|
|
103
|
+
| `collections` | `CollectionConfig[]` | ✅ | Collections to translate |
|
|
104
|
+
|
|
105
|
+
### AI Configuration
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
interface AIConfig {
|
|
109
|
+
provider: 'gemini' | 'openai' | 'claude';
|
|
110
|
+
model: string;
|
|
111
|
+
temperature?: number; // Default: 0.3
|
|
112
|
+
apiKeySecret?: string; // Firebase secret name
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
#### Supported Models
|
|
117
|
+
|
|
118
|
+
**Gemini (Google):**
|
|
119
|
+
- `gemini-2.5-flash` — Fast, cost-effective (recommended)
|
|
120
|
+
- `gemini-2.5-pro` — Higher quality, slower
|
|
121
|
+
- `gemini-2.0-flash` — Previous generation
|
|
122
|
+
|
|
123
|
+
**OpenAI:**
|
|
124
|
+
- `gpt-4o` — Latest GPT-4
|
|
125
|
+
- `gpt-4o-mini` — Faster, cheaper
|
|
126
|
+
- `gpt-4-turbo` — Previous flagship
|
|
127
|
+
|
|
128
|
+
**Claude (Anthropic):**
|
|
129
|
+
- `claude-sonnet-4-20250514` — Balanced speed/quality
|
|
130
|
+
- `claude-opus-4-20250514` — Highest quality
|
|
131
|
+
|
|
132
|
+
### Defaults Configuration
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
interface DefaultsConfig {
|
|
136
|
+
batchSize?: number; // Documents per batch (default: 20)
|
|
137
|
+
maxConcurrency?: number; // Concurrent tasks (default: 10)
|
|
138
|
+
forceUpdate?: boolean; // Re-translate unchanged docs (default: false)
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Collection Configuration
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
interface CollectionConfig {
|
|
146
|
+
path: string; // Collection path
|
|
147
|
+
isCollectionGroup?: boolean; // Use collection group query
|
|
148
|
+
fields?: string[]; // Fields to translate (auto-detect if omitted)
|
|
149
|
+
fieldMappings?: FieldMapping[]; // Detailed field configuration
|
|
150
|
+
prompt?: string; // Context for AI translation
|
|
151
|
+
glossary?: Record<string, string>; // Collection-specific glossary
|
|
152
|
+
batchSize?: number; // Override default
|
|
153
|
+
maxConcurrency?: number; // Override default
|
|
154
|
+
forceUpdate?: boolean; // Override default
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Field Mapping Configuration
|
|
159
|
+
|
|
160
|
+
For fine-grained control over field translation:
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
interface FieldMapping {
|
|
164
|
+
sourceField: string; // Field name in source document
|
|
165
|
+
targetField?: string; // Field name in translation (default: same)
|
|
166
|
+
schemaType?: SchemaType; // Override auto-detection
|
|
167
|
+
required?: boolean; // Fail if field missing
|
|
168
|
+
description?: string; // Help AI understand context
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
type SchemaType =
|
|
172
|
+
| 'string'
|
|
173
|
+
| 'string[]'
|
|
174
|
+
| 'number'
|
|
175
|
+
| 'number[]'
|
|
176
|
+
| 'boolean'
|
|
177
|
+
| 'object'
|
|
178
|
+
| 'object[]'
|
|
179
|
+
| 'object|null'
|
|
180
|
+
| 'DocumentReference'
|
|
181
|
+
| 'DocumentReference[]';
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Language Codes
|
|
187
|
+
|
|
188
|
+
Use BCP 47 language tags:
|
|
189
|
+
|
|
190
|
+
| Code | Language |
|
|
191
|
+
|------|----------|
|
|
192
|
+
| `ms-MY` | Malay (Malaysia) |
|
|
193
|
+
| `zh-CN` | Chinese (Simplified) |
|
|
194
|
+
| `zh-TW` | Chinese (Traditional) |
|
|
195
|
+
| `ta-IN` | Tamil (India) |
|
|
196
|
+
| `hi-IN` | Hindi (India) |
|
|
197
|
+
| `id-ID` | Indonesian |
|
|
198
|
+
| `th-TH` | Thai |
|
|
199
|
+
| `vi-VN` | Vietnamese |
|
|
200
|
+
| `ja-JP` | Japanese |
|
|
201
|
+
| `ko-KR` | Korean |
|
|
202
|
+
| `es-ES` | Spanish (Spain) |
|
|
203
|
+
| `fr-FR` | French (France) |
|
|
204
|
+
| `de-DE` | German |
|
|
205
|
+
| `pt-BR` | Portuguese (Brazil) |
|
|
206
|
+
| `ar-SA` | Arabic |
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Glossary
|
|
211
|
+
|
|
212
|
+
Glossaries ensure consistent translation of domain-specific terms.
|
|
213
|
+
|
|
214
|
+
### Shared Glossary
|
|
215
|
+
|
|
216
|
+
Applied to all collections:
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
export default defineConfig({
|
|
220
|
+
glossary: {
|
|
221
|
+
// Term: Translation (or same to preserve)
|
|
222
|
+
'checkout': 'checkout',
|
|
223
|
+
'wishlist': 'senarai hajat',
|
|
224
|
+
'Acme Inc': 'Acme Inc', // Proper noun, don't translate
|
|
225
|
+
},
|
|
226
|
+
// ...
|
|
227
|
+
});
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Collection Glossary
|
|
231
|
+
|
|
232
|
+
Override or extend for specific collections:
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
collections: [
|
|
236
|
+
{
|
|
237
|
+
path: 'recipes',
|
|
238
|
+
glossary: {
|
|
239
|
+
'simmer': 'reneh',
|
|
240
|
+
'sauté': 'tumis',
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Glossary Merging
|
|
247
|
+
|
|
248
|
+
Collection glossary is merged with shared glossary:
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
// Effective glossary for 'recipes' collection:
|
|
252
|
+
{
|
|
253
|
+
...sharedGlossary,
|
|
254
|
+
...collectionGlossary, // Overrides shared
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Translation Prompts
|
|
261
|
+
|
|
262
|
+
Custom prompts provide context to the AI:
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
collections: [
|
|
266
|
+
{
|
|
267
|
+
path: 'recipes',
|
|
268
|
+
prompt: `
|
|
269
|
+
This is cooking recipe content.
|
|
270
|
+
Translate ingredient names and cooking instructions clearly.
|
|
271
|
+
Keep measurements in their original units.
|
|
272
|
+
`,
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
path: 'promotions',
|
|
276
|
+
prompt: `
|
|
277
|
+
This is promotional content for retail offers.
|
|
278
|
+
Keep the promotional tone engaging.
|
|
279
|
+
Preserve all coupon codes, addresses, and links exactly.
|
|
280
|
+
`,
|
|
281
|
+
},
|
|
282
|
+
],
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Collection Groups
|
|
288
|
+
|
|
289
|
+
For subcollections that appear in multiple places:
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
// Translates all 'comments' subcollections across the database
|
|
293
|
+
// e.g., /posts/{pid}/comments/{id}, /products/{prodId}/comments/{id}
|
|
294
|
+
|
|
295
|
+
collections: [
|
|
296
|
+
{
|
|
297
|
+
path: 'comments',
|
|
298
|
+
isCollectionGroup: true,
|
|
299
|
+
fields: ['text', 'reply'],
|
|
300
|
+
},
|
|
301
|
+
],
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Examples
|
|
307
|
+
|
|
308
|
+
### Minimal Config
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { defineConfig } from 'melaka';
|
|
312
|
+
|
|
313
|
+
export default defineConfig({
|
|
314
|
+
languages: ['ms-MY'],
|
|
315
|
+
ai: { provider: 'gemini', model: 'gemini-2.5-flash' },
|
|
316
|
+
collections: [
|
|
317
|
+
{ path: 'articles', fields: ['title', 'content'] },
|
|
318
|
+
],
|
|
319
|
+
});
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Multi-Language E-commerce Config
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
import { defineConfig } from 'melaka';
|
|
326
|
+
|
|
327
|
+
export default defineConfig({
|
|
328
|
+
languages: ['ms-MY', 'zh-CN', 'ja-JP', 'ko-KR'],
|
|
329
|
+
|
|
330
|
+
ai: {
|
|
331
|
+
provider: 'gemini',
|
|
332
|
+
model: 'gemini-2.5-flash',
|
|
333
|
+
temperature: 0.3,
|
|
334
|
+
},
|
|
335
|
+
|
|
336
|
+
region: 'asia-southeast1',
|
|
337
|
+
|
|
338
|
+
glossary: {
|
|
339
|
+
'Acme Store': 'Acme Store',
|
|
340
|
+
'free shipping': 'penghantaran percuma',
|
|
341
|
+
},
|
|
342
|
+
|
|
343
|
+
collections: [
|
|
344
|
+
{
|
|
345
|
+
path: 'products',
|
|
346
|
+
fields: ['name', 'description', 'features'],
|
|
347
|
+
prompt: 'E-commerce product descriptions. Keep brand names unchanged.',
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
path: 'categories',
|
|
351
|
+
fields: ['name', 'description'],
|
|
352
|
+
prompt: 'Product category names and descriptions.',
|
|
353
|
+
},
|
|
354
|
+
],
|
|
355
|
+
});
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Advanced Field Mappings
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
import { defineConfig } from 'melaka';
|
|
362
|
+
|
|
363
|
+
export default defineConfig({
|
|
364
|
+
languages: ['ms-MY'],
|
|
365
|
+
ai: { provider: 'gemini', model: 'gemini-2.5-flash' },
|
|
366
|
+
|
|
367
|
+
collections: [
|
|
368
|
+
{
|
|
369
|
+
path: 'products',
|
|
370
|
+
fieldMappings: [
|
|
371
|
+
{
|
|
372
|
+
sourceField: 'name',
|
|
373
|
+
schemaType: 'string',
|
|
374
|
+
required: true,
|
|
375
|
+
description: 'Product name - keep brand names unchanged',
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
sourceField: 'description',
|
|
379
|
+
schemaType: 'string',
|
|
380
|
+
required: true,
|
|
381
|
+
description: 'Product description with markdown formatting',
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
sourceField: 'features',
|
|
385
|
+
schemaType: 'string[]',
|
|
386
|
+
required: false,
|
|
387
|
+
description: 'List of product features',
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
sourceField: 'price',
|
|
391
|
+
schemaType: 'number',
|
|
392
|
+
required: true,
|
|
393
|
+
// Numbers are copied, not translated
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
sourceField: 'category_ref',
|
|
397
|
+
schemaType: 'DocumentReference',
|
|
398
|
+
required: true,
|
|
399
|
+
// References are copied, not translated
|
|
400
|
+
},
|
|
401
|
+
],
|
|
402
|
+
},
|
|
403
|
+
],
|
|
404
|
+
});
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## Environment Variables
|
|
410
|
+
|
|
411
|
+
For local development, create a `.env` file:
|
|
412
|
+
|
|
413
|
+
```bash
|
|
414
|
+
# .env (do not commit!)
|
|
415
|
+
GEMINI_API_KEY=your-api-key-here
|
|
416
|
+
OPENAI_API_KEY=your-api-key-here
|
|
417
|
+
ANTHROPIC_API_KEY=your-api-key-here
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
For production, use Firebase secrets:
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
firebase functions:secrets:set GEMINI_API_KEY
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## Validation
|
|
429
|
+
|
|
430
|
+
Melaka validates your config on startup and deployment:
|
|
431
|
+
|
|
432
|
+
```bash
|
|
433
|
+
$ melaka validate
|
|
434
|
+
|
|
435
|
+
✓ Config file found: melaka.config.ts
|
|
436
|
+
✓ Languages valid: ms-MY, zh-CN
|
|
437
|
+
✓ AI provider configured: gemini
|
|
438
|
+
✓ Collections configured: 3
|
|
439
|
+
- articles (3 fields)
|
|
440
|
+
- products (2 fields)
|
|
441
|
+
- comments (collection group, 2 fields)
|
|
442
|
+
✓ Glossary entries: 15
|
|
443
|
+
|
|
444
|
+
Config is valid!
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
## Next Steps
|
|
450
|
+
|
|
451
|
+
- [CLI Reference](./CLI.md) — Available commands
|
|
452
|
+
- [AI Providers](./AI_PROVIDERS.md) — Provider-specific setup
|
|
453
|
+
- [Architecture](./ARCHITECTURE.md) — System design
|