@topy-ai/maggie 0.6.4 → 0.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -157,8 +157,8 @@ only and never stores response bodies, cookies, or credentials.
|
|
|
157
157
|
Recommended upgrade sequence for the current release:
|
|
158
158
|
|
|
159
159
|
```bash
|
|
160
|
-
npx @topy-ai/maggie@0.6.
|
|
161
|
-
npx @topy-ai/maggie@0.6.
|
|
160
|
+
npx @topy-ai/maggie@0.6.6 update --project . --force
|
|
161
|
+
npx @topy-ai/maggie@0.6.6 cleanup --project .
|
|
162
162
|
```
|
|
163
163
|
|
|
164
164
|
## MaggieDash lifecycle
|
package/README.zh-TW.md
CHANGED
|
@@ -2,11 +2,17 @@
|
|
|
2
2
|
name: maggie-content-localization
|
|
3
3
|
description: Manage translation, polish, rewrite, market localization, review, stale detection, and publishing for pages, guides, posts, services, products, and categories.
|
|
4
4
|
metadata:
|
|
5
|
-
version: 1.
|
|
5
|
+
version: 1.1.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Maggie Content Localization
|
|
9
9
|
|
|
10
|
+
Localization job filenames are derived from content identity, but content IDs
|
|
11
|
+
are data, not paths. The CLI sanitizes separators and adds a short identity
|
|
12
|
+
hash when needed, so IDs such as `site.example/static-pages` always produce a
|
|
13
|
+
single addressable file under `.maggie/localization/`. Never construct a job
|
|
14
|
+
path by interpolating an unsanitized content ID.
|
|
15
|
+
|
|
10
16
|
Use the shared [Content Localization Contract](../../references/content-localization-contract.md).
|
|
11
17
|
Use the shared [memory hook](../../references/memory-hook.md) to read prior
|
|
12
18
|
locale preferences and record confirmed terminology or translation failures.
|
|
@@ -53,3 +59,9 @@ Never change price, currency, rating, provider facts, booking URLs, legal or
|
|
|
53
59
|
health claims, slug, canonical ownership, or content identity during a copy
|
|
54
60
|
operation without structured approval. Incomplete or fallback output must be
|
|
55
61
|
`isIndexable: false`. High-risk content requires Admin approval before publish.
|
|
62
|
+
|
|
63
|
+
The current validator checks the localization record. It does not yet extract
|
|
64
|
+
strings from a host project or prove browser-rendered language output. That
|
|
65
|
+
larger capability is specified in
|
|
66
|
+
[`docs/localization-extraction-render-prd.md`](../../docs/localization-extraction-render-prd.md)
|
|
67
|
+
and remains a separate release-gated feature.
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
6
|
import argparse
|
|
7
|
+
import hashlib
|
|
7
8
|
import json
|
|
9
|
+
import re
|
|
8
10
|
import sys
|
|
9
11
|
from datetime import datetime, timezone
|
|
10
12
|
from pathlib import Path
|
|
@@ -24,6 +26,14 @@ def load(path: Path) -> dict:
|
|
|
24
26
|
return value
|
|
25
27
|
|
|
26
28
|
|
|
29
|
+
def safe_job_content_token(content_id: str) -> str:
|
|
30
|
+
"""Make a content identity safe for a single filename component."""
|
|
31
|
+
token = re.sub(r"[^A-Za-z0-9._-]+", "-", str(content_id)).strip(".-_") or "content"
|
|
32
|
+
if token != content_id:
|
|
33
|
+
token = f"{token}-{hashlib.sha256(str(content_id).encode('utf-8')).hexdigest()[:8]}"
|
|
34
|
+
return token[:180]
|
|
35
|
+
|
|
36
|
+
|
|
27
37
|
def plan_job(args: argparse.Namespace) -> int:
|
|
28
38
|
content = load(args.content)
|
|
29
39
|
if args.source_lang not in LANGUAGES or args.target_lang not in LANGUAGES:
|
|
@@ -39,7 +49,7 @@ def plan_job(args: argparse.Namespace) -> int:
|
|
|
39
49
|
if not content_id:
|
|
40
50
|
raise ValueError("contentId is required in content identity")
|
|
41
51
|
job = {
|
|
42
|
-
"jobId": f"localize-{content_id}-{args.target_lang.lower()}-{datetime.now(timezone.utc).strftime('%Y%m%d%H%M%S')}",
|
|
52
|
+
"jobId": f"localize-{safe_job_content_token(content_id)}-{args.target_lang.lower()}-{datetime.now(timezone.utc).strftime('%Y%m%d%H%M%S')}",
|
|
43
53
|
"content": content,
|
|
44
54
|
"contentId": content_id,
|
|
45
55
|
"contentType": identity.get("contentType", "page"),
|