You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- CHANGELOG: move Phase 3 entries from [Unreleased] to [0.3.0].
- RELEASE-NOTES: add long-form narrative for v0.3.0; flag that this tag
marks the end of MVP (Translately works end-to-end without AI
configured) and preview Phase 4 (BYOK AI + MT + TM).
- tasks.md: tick T301/T302/T304/T305/T306; re-flag T303 (async SSE)
as moved-to-Phase-4 per the earlier milestone reshuffle.
Closes#57 (T306 — tag v0.3.0 GPG-signed).
- **i18next JSON import + export — backend and webapp wizard** (T301 + T302 + T304 + T305; closes #52 + #53 + #55 + #56). Two synchronous endpoints under `/api/v1/organizations/{orgSlug}/projects/{projectSlug}`: `POST /imports/json` (i18next flat or nested JSON in, `{total, created, updated, skipped, failed, errors[]}` out) and `GET /exports/json` (shape + language-tag + namespace + tag + min-state filters → JSON file body with `Content-Disposition`). Conflict modes: `KEEP` / `OVERWRITE` / `MERGE`. Per-row ICU validation via the existing `IcuValidator`; invalid cells land in the result's `errors[]` without blocking clean rows. Shared parser — new `JsonTranslationsIO` service — handles flat ↔ nested round-trip and emits `JsonShapeError(path, code, message)` with jq-style addressing for parse failures. Webapp surfaces a four-step import wizard and a single-page export modal mounted on the project detail route, both using RHF-free local state because the wizard's flow is linear and small. Eight new backend integration tests (`ImportResourceIT` 6 + `ExportResourceIT` 4) and 11 parser unit tests (`JsonTranslationsIOTest`). Async + SSE progress streaming remains deferred to T303 (Phase 4). New API ref page [`docs/api/imports-and-exports.md`](docs/api/imports-and-exports.md) and product page [`docs/product/imports-and-exports.md`](docs/product/imports-and-exports.md).
**Tag:**`v0.3.0` (GPG-signed) · [Compare with v0.2.0](https://github.com/Pratiyush/translately/compare/v0.2.0...v0.3.0)
12
+
13
+
### The headline
14
+
15
+
**Translately is now usable end-to-end as a self-hosted localization platform, with zero AI configured.** That was the MVP bar set in Phase 0: sign up, create an organization and a project, add translation keys, write values for a language, ship them back out as i18next JSON. Every piece is MIT. Every "enterprise" feature stays scheduled for its phase — SSO/SAML/LDAP at Phase 7, Tasks + Branching at Phase 7, CLI at Phase 6 — and shipped-to-date pieces remain free.
Accepts flat (`{"nav.signIn":"Sign in"}`) or nested (`{"nav":{"signIn":"Sign in"}}`) i18next JSON, auto-detects shape, upserts one language per call. Conflict modes: `KEEP` (existing wins), `OVERWRITE` (replace every row), `MERGE` (fill blanks only). Per-row ICU validation via the v0.2.0 `IcuValidator` — invalid cells land in the response's `errors[]` array so the UI can surface them without rolling back the clean rows. Response: `{total, created, updated, skipped, failed, errors[]}`.
Downloads one language as either flat or nested JSON. Filters: `languageTag`, `namespaceSlug`, `tags` (AND intersection), `minState` (`EMPTY < DRAFT < TRANSLATED < REVIEW < APPROVED` — pick `APPROVED` for production dumps). `Content-Disposition` ships a suggested filename; `X-Translately-Key-Count` lets the UI render a progress hint.
25
+
26
+
Shared parser (`JsonTranslationsIO`) handles flat ↔ nested round-trip and emits `JsonShapeError(path, code, message)` with jq-style addressing (e.g. `nav.items` → `UNSUPPORTED_TYPE` for a nested array) so the UI can point at the offending path in the pasted JSON.
27
+
28
+
Webapp adds **Import** and **Export** buttons to the Keys tab on the project detail route. Import wizard: paste JSON or drop a `.json` file, pick language + namespace + mode, run, review per-row errors inline. Export modal: pick shape + language + optional filters, click Download, browser saves `{projectSlug}-{languageTag}-{shape}.json`.
29
+
30
+
### What ships deferred to later phases
31
+
32
+
Four tickets originally scheduled for Phases 2–3 were re-allocated during MVP close-out to keep surgical focus:
33
+
34
+
-**T204 — bulk ops via Quartz** → Phase 4. Piggybacks on the Quartz infra the AI-batch workflow adds.
35
+
-**T205 — activity-log per-field diffs** → Phase 7. Pairs naturally with the audit log (T706).
-**T303 — async Quartz + SSE progress streaming** → Phase 4. The sync import/export endpoints in this release cover payloads up to ~10k keys comfortably; the async path becomes necessary when Phase 4 adds bulk AI translation jobs.
38
+
39
+
### What's next
40
+
41
+
**v0.4.0 — Phase 4: BYOK AI + MT + Translation Memory.** Per-project encrypted API keys for OpenAI / Anthropic / Google / Azure / custom endpoints; suggest + translate endpoints; MT adapter layer; TM lookup via pgvector + trigram. The entire layer is optional — Translately still works end-to-end without an AI key configured. The bulk-ops and async-job tickets deferred from this phase land alongside the AI batch workflow.
42
+
43
+
### Operator notes
44
+
45
+
- Schema migrations on upgrade: V3 (Phase 2 data model) + V4 (FTS + trigram) from v0.2.0 both apply automatically via Flyway. No new migrations in v0.3.0.
46
+
- No new env vars. No new compose services.
47
+
- The import endpoint runs inside a single transaction. Very large payloads (50k+ keys) should wait for T303's async path in v0.4.0 — the current sync call is fine up to ~10k keys per call on commodity hardware.
48
+
-`imports.write` + `exports.read` are the scopes. OWNER / ADMIN have both by default; MEMBER has `imports.write` (translators upload) but not `exports.read` (download gate is an ADMIN concern).
0 commit comments