@jahia/agentic 0.2.0 → 0.3.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/CHANGELOG.md +4 -0
- package/README.md +28 -0
- package/dist/claude/.claude/skills/jahia/SKILL.md +18 -10
- package/dist/claude/.claude/skills/jahia-content/SKILL.md +102 -84
- package/dist/claude/.claude/skills/jahia-content-create-content/SKILL.md +255 -280
- package/dist/claude/.claude/skills/jahia-content-explore-structure/SKILL.md +187 -96
- package/dist/claude/.claude/skills/jahia-content-media-upload/SKILL.md +197 -0
- package/dist/claude/.claude/skills/jahia-content-move-content/SKILL.md +160 -165
- package/dist/claude/.claude/skills/jahia-content-organize/SKILL.md +209 -0
- package/dist/claude/.claude/skills/jahia-content-publish/SKILL.md +181 -0
- package/dist/claude/.claude/skills/jahia-content-query-content/SKILL.md +122 -92
- package/dist/claude/.claude/skills/jahia-content-translate-content/SKILL.md +154 -225
- package/dist/claude/.claude/skills/jahia-dev-cypress/SKILL.md +150 -330
- package/dist/claude/.claude/skills/jahia-dev-query-content/SKILL.md +93 -296
- package/dist/claude/.claude/skills/jahia-jcr-sql2/SKILL.md +258 -0
- package/dist/claude/CLAUDE.md +1 -7
- package/dist/codex/.agents/skills/jahia/SKILL.md +18 -10
- package/dist/codex/.agents/skills/jahia-content/SKILL.md +102 -84
- package/dist/codex/.agents/skills/jahia-content-create-content/SKILL.md +255 -280
- package/dist/codex/.agents/skills/jahia-content-explore-structure/SKILL.md +187 -96
- package/dist/codex/.agents/skills/jahia-content-media-upload/SKILL.md +197 -0
- package/dist/codex/.agents/skills/jahia-content-move-content/SKILL.md +160 -165
- package/dist/codex/.agents/skills/jahia-content-organize/SKILL.md +209 -0
- package/dist/codex/.agents/skills/jahia-content-publish/SKILL.md +181 -0
- package/dist/codex/.agents/skills/jahia-content-query-content/SKILL.md +122 -92
- package/dist/codex/.agents/skills/jahia-content-translate-content/SKILL.md +154 -225
- package/dist/codex/.agents/skills/jahia-dev-cypress/SKILL.md +150 -330
- package/dist/codex/.agents/skills/jahia-dev-query-content/SKILL.md +93 -296
- package/dist/codex/.agents/skills/jahia-jcr-sql2/SKILL.md +258 -0
- package/dist/codex/AGENTS.md +2 -4
- package/dist/copilot/.agents/skills/jahia/SKILL.md +18 -10
- package/dist/copilot/.agents/skills/jahia-content/SKILL.md +102 -84
- package/dist/copilot/.agents/skills/jahia-content-create-content/SKILL.md +255 -280
- package/dist/copilot/.agents/skills/jahia-content-explore-structure/SKILL.md +187 -96
- package/dist/copilot/.agents/skills/jahia-content-media-upload/SKILL.md +197 -0
- package/dist/copilot/.agents/skills/jahia-content-move-content/SKILL.md +160 -165
- package/dist/copilot/.agents/skills/jahia-content-organize/SKILL.md +209 -0
- package/dist/copilot/.agents/skills/jahia-content-publish/SKILL.md +181 -0
- package/dist/copilot/.agents/skills/jahia-content-query-content/SKILL.md +122 -92
- package/dist/copilot/.agents/skills/jahia-content-translate-content/SKILL.md +154 -225
- package/dist/copilot/.agents/skills/jahia-dev-cypress/SKILL.md +150 -330
- package/dist/copilot/.agents/skills/jahia-dev-query-content/SKILL.md +93 -296
- package/dist/copilot/.agents/skills/jahia-jcr-sql2/SKILL.md +258 -0
- package/dist/copilot/AGENTS.md +2 -4
- package/dist/cursor/.agents/skills/jahia/SKILL.md +18 -10
- package/dist/cursor/.agents/skills/jahia-content/SKILL.md +102 -84
- package/dist/cursor/.agents/skills/jahia-content-create-content/SKILL.md +255 -280
- package/dist/cursor/.agents/skills/jahia-content-explore-structure/SKILL.md +187 -96
- package/dist/cursor/.agents/skills/jahia-content-media-upload/SKILL.md +197 -0
- package/dist/cursor/.agents/skills/jahia-content-move-content/SKILL.md +160 -165
- package/dist/cursor/.agents/skills/jahia-content-organize/SKILL.md +209 -0
- package/dist/cursor/.agents/skills/jahia-content-publish/SKILL.md +181 -0
- package/dist/cursor/.agents/skills/jahia-content-query-content/SKILL.md +122 -92
- package/dist/cursor/.agents/skills/jahia-content-translate-content/SKILL.md +154 -225
- package/dist/cursor/.agents/skills/jahia-dev-cypress/SKILL.md +150 -330
- package/dist/cursor/.agents/skills/jahia-dev-query-content/SKILL.md +93 -296
- package/dist/cursor/.agents/skills/jahia-jcr-sql2/SKILL.md +258 -0
- package/dist/gemini/.agents/skills/jahia/SKILL.md +18 -10
- package/dist/gemini/.agents/skills/jahia-content/SKILL.md +102 -84
- package/dist/gemini/.agents/skills/jahia-content-create-content/SKILL.md +255 -280
- package/dist/gemini/.agents/skills/jahia-content-explore-structure/SKILL.md +187 -96
- package/dist/gemini/.agents/skills/jahia-content-media-upload/SKILL.md +197 -0
- package/dist/gemini/.agents/skills/jahia-content-move-content/SKILL.md +160 -165
- package/dist/gemini/.agents/skills/jahia-content-organize/SKILL.md +209 -0
- package/dist/gemini/.agents/skills/jahia-content-publish/SKILL.md +181 -0
- package/dist/gemini/.agents/skills/jahia-content-query-content/SKILL.md +122 -92
- package/dist/gemini/.agents/skills/jahia-content-translate-content/SKILL.md +154 -225
- package/dist/gemini/.agents/skills/jahia-dev-cypress/SKILL.md +150 -330
- package/dist/gemini/.agents/skills/jahia-dev-query-content/SKILL.md +93 -296
- package/dist/gemini/.agents/skills/jahia-jcr-sql2/SKILL.md +258 -0
- package/dist/gemini/AGENTS.md +2 -4
- package/dist/gemini/GEMINI.md +2 -2
- package/dist/opencode/.agents/skills/jahia/SKILL.md +18 -10
- package/dist/opencode/.agents/skills/jahia-content/SKILL.md +102 -84
- package/dist/opencode/.agents/skills/jahia-content-create-content/SKILL.md +255 -280
- package/dist/opencode/.agents/skills/jahia-content-explore-structure/SKILL.md +187 -96
- package/dist/opencode/.agents/skills/jahia-content-media-upload/SKILL.md +197 -0
- package/dist/opencode/.agents/skills/jahia-content-move-content/SKILL.md +160 -165
- package/dist/opencode/.agents/skills/jahia-content-organize/SKILL.md +209 -0
- package/dist/opencode/.agents/skills/jahia-content-publish/SKILL.md +181 -0
- package/dist/opencode/.agents/skills/jahia-content-query-content/SKILL.md +122 -92
- package/dist/opencode/.agents/skills/jahia-content-translate-content/SKILL.md +154 -225
- package/dist/opencode/.agents/skills/jahia-dev-cypress/SKILL.md +150 -330
- package/dist/opencode/.agents/skills/jahia-dev-query-content/SKILL.md +93 -296
- package/dist/opencode/.agents/skills/jahia-jcr-sql2/SKILL.md +258 -0
- package/dist/opencode/AGENTS.md +2 -4
- package/dist/windsurf/.windsurf/skills/jahia/SKILL.md +18 -10
- package/dist/windsurf/.windsurf/skills/jahia-content/SKILL.md +102 -84
- package/dist/windsurf/.windsurf/skills/jahia-content-create-content/SKILL.md +255 -280
- package/dist/windsurf/.windsurf/skills/jahia-content-explore-structure/SKILL.md +187 -96
- package/dist/windsurf/.windsurf/skills/jahia-content-media-upload/SKILL.md +197 -0
- package/dist/windsurf/.windsurf/skills/jahia-content-move-content/SKILL.md +160 -165
- package/dist/windsurf/.windsurf/skills/jahia-content-organize/SKILL.md +209 -0
- package/dist/windsurf/.windsurf/skills/jahia-content-publish/SKILL.md +181 -0
- package/dist/windsurf/.windsurf/skills/jahia-content-query-content/SKILL.md +122 -92
- package/dist/windsurf/.windsurf/skills/jahia-content-translate-content/SKILL.md +154 -225
- package/dist/windsurf/.windsurf/skills/jahia-dev-cypress/SKILL.md +150 -330
- package/dist/windsurf/.windsurf/skills/jahia-dev-query-content/SKILL.md +93 -296
- package/dist/windsurf/.windsurf/skills/jahia-jcr-sql2/SKILL.md +258 -0
- package/dist/windsurf/AGENTS.md +2 -4
- package/package.json +3 -3
|
@@ -1,273 +1,208 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jahia-content-translate-content
|
|
3
|
-
description: Adds
|
|
3
|
+
description: Adds site languages and translates existing Jahia content using MCP tools. Use when asked to enable a locale, fill in missing translations, or publish translated pages and content.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Skill: jahia-content-translate-content
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Translates existing content and manages multi-language support using MCP tools via the `jahia` MCP server.
|
|
9
|
+
|
|
10
|
+
> **Never call Jahia's GraphQL API directly.** Use only MCP tools. If a capability is missing, report it — do not work around with curl/GraphQL.
|
|
9
11
|
|
|
10
12
|
---
|
|
11
13
|
|
|
12
14
|
## Prerequisites
|
|
13
15
|
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
**Always include both auth flags:**
|
|
19
|
-
```bash
|
|
20
|
-
curl -s -u root:root1234 \
|
|
21
|
-
-H "Content-Type: application/json" \
|
|
22
|
-
-H "Origin: http://localhost:8080" \
|
|
23
|
-
-X POST http://localhost:8080/modules/graphql \
|
|
24
|
-
-d '{"query": "..."}'
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
> ⚠️ The `Origin` header is **required** — omitting it returns `Permission denied`.
|
|
16
|
+
- MCP server `jahia` connected with a valid API token
|
|
17
|
+
- Know the target `siteKey` (call `site.list` if unsure)
|
|
18
|
+
- Content already exists in a source locale
|
|
28
19
|
|
|
29
20
|
---
|
|
30
21
|
|
|
31
|
-
## Step 1 —
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
# Check currently enabled languages
|
|
37
|
-
curl -s -u root:root1234 \
|
|
38
|
-
-H "Content-Type: application/json" \
|
|
39
|
-
-H "Origin: http://localhost:8080" \
|
|
40
|
-
-X POST http://localhost:8080/modules/graphql \
|
|
41
|
-
-d '{
|
|
42
|
-
"query": "{ jcr { nodeByPath(path: \"/sites/mySite\") { properties(names: [\"j:languages\",\"j:defaultLanguage\"]) { name values } } } }"
|
|
43
|
-
}'
|
|
44
|
-
|
|
45
|
-
# Add a language (e.g. "fr") — use setPropertiesBatch with the full new list
|
|
46
|
-
curl -s -u root:root1234 \
|
|
47
|
-
-H "Content-Type: application/json" \
|
|
48
|
-
-H "Origin: http://localhost:8080" \
|
|
49
|
-
-X POST http://localhost:8080/modules/graphql \
|
|
50
|
-
-d '{
|
|
51
|
-
"query": "mutation { jcr { mutateNode(pathOrId: \"/sites/mySite\") { setPropertiesBatch(properties: [{name: \"j:languages\", values: [\"en\", \"fr\"]}]) { path } } } }"
|
|
52
|
-
}'
|
|
22
|
+
## Step 1 — Check site languages
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
tool: site.get
|
|
26
|
+
args: { "siteKey": "SITE_KEY" }
|
|
53
27
|
```
|
|
54
28
|
|
|
55
|
-
|
|
29
|
+
Check `languages` and `defaultLanguage`.
|
|
56
30
|
|
|
57
|
-
|
|
31
|
+
- If the target locale is already present, continue.
|
|
32
|
+
- If the target locale is missing, add it to the site first before writing translations.
|
|
58
33
|
|
|
59
|
-
|
|
34
|
+
---
|
|
60
35
|
|
|
61
|
-
|
|
36
|
+
## Step 2 — Read the source content
|
|
62
37
|
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
-d '{
|
|
70
|
-
"query": "{ jcr { nodesByQuery(query: \"SELECT * FROM [jmix:i18n] WHERE ISDESCENDANTNODE(\u0027/sites/mySite/contents\u0027) ORDER BY [jcr:path] ASC\", queryLanguage: SQL2) { nodes { path primaryNodeType { name } properties(language: \"fr\") { name value } } } } }"
|
|
71
|
-
}'
|
|
38
|
+
```
|
|
39
|
+
tool: content.get
|
|
40
|
+
args: {
|
|
41
|
+
"path": "/sites/SITE_KEY/home/about/main/intro-text",
|
|
42
|
+
"locale": "en"
|
|
43
|
+
}
|
|
72
44
|
```
|
|
73
45
|
|
|
74
|
-
|
|
46
|
+
Note the properties that actually contain human-readable text.
|
|
75
47
|
|
|
76
|
-
|
|
77
|
-
curl -s -u root:root1234 \
|
|
78
|
-
-H "Content-Type: application/json" \
|
|
79
|
-
-H "Origin: http://localhost:8080" \
|
|
80
|
-
-X POST http://localhost:8080/modules/graphql \
|
|
81
|
-
-d '{
|
|
82
|
-
"query": "{ jcr { nodesByQuery(query: \"SELECT * FROM [namespace:article] WHERE ISDESCENDANTNODE(\u0027/sites/mySite/contents\u0027)\", queryLanguage: SQL2) { nodes { path properties(language: \"fr\") { name value } } } } }"
|
|
83
|
-
}'
|
|
84
|
-
```
|
|
48
|
+
To find a batch of nodes to translate:
|
|
85
49
|
|
|
86
|
-
|
|
50
|
+
```
|
|
51
|
+
tool: content.search
|
|
52
|
+
args: {
|
|
53
|
+
"siteKey": "SITE_KEY",
|
|
54
|
+
"nodeType": "jmix:droppableContent",
|
|
55
|
+
"locale": "en",
|
|
56
|
+
"limit": 50
|
|
57
|
+
}
|
|
58
|
+
```
|
|
87
59
|
|
|
88
60
|
---
|
|
89
61
|
|
|
90
|
-
## Step 3 —
|
|
91
|
-
|
|
92
|
-
### Single node
|
|
62
|
+
## Step 3 — Identify which properties are i18n
|
|
93
63
|
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
-H "Origin: http://localhost:8080" \
|
|
98
|
-
-X POST http://localhost:8080/modules/graphql \
|
|
99
|
-
-d '{
|
|
100
|
-
"query": "mutation { jcr { mutateNode(pathOrId: \"/sites/mySite/contents/articles/my-article\") { setPropertiesBatch(properties: [{name: \"jcr:title\", value: \"Mon article\", language: \"fr\"}, {name: \"body\", value: \"<p>Contenu ici</p>\", language: \"fr\"}]) { path } } } }"
|
|
101
|
-
}'
|
|
64
|
+
```
|
|
65
|
+
tool: content.type
|
|
66
|
+
args: { "name": "jnt:bigText" }
|
|
102
67
|
```
|
|
103
68
|
|
|
104
|
-
|
|
69
|
+
Translate only properties marked as internationalized.
|
|
105
70
|
|
|
106
|
-
|
|
71
|
+
Common i18n properties:
|
|
72
|
+
- `jcr:title`
|
|
73
|
+
- `text`
|
|
74
|
+
- `body`
|
|
75
|
+
- `description`
|
|
76
|
+
- `subtitle`
|
|
107
77
|
|
|
108
|
-
|
|
78
|
+
Common non-i18n properties:
|
|
79
|
+
- `j:view`
|
|
80
|
+
- `j:templateName`
|
|
81
|
+
- `jcr:primaryType`
|
|
82
|
+
- references such as `j:node`
|
|
83
|
+
- numeric or technical settings
|
|
109
84
|
|
|
110
|
-
|
|
85
|
+
---
|
|
111
86
|
|
|
112
|
-
|
|
113
|
-
curl -s -u root:root1234 \
|
|
114
|
-
-H "Content-Type: application/json" \
|
|
115
|
-
-H "Origin: http://localhost:8080" \
|
|
116
|
-
-X POST http://localhost:8080/modules/graphql \
|
|
117
|
-
-d '{
|
|
118
|
-
"query": "mutation { jcr { mutateNode(pathOrId: \"/sites/mySite/contents/articles/my-article\") { setPropertiesBatch(properties: [{name: \"body\", value: \"<p>Contenu ici</p>\", language: \"fr\"}, {name: \"jcr:title\", value: \"Mon article\", language: \"fr\"}]) { path } } } }"
|
|
119
|
-
}'
|
|
120
|
-
```
|
|
87
|
+
## Step 4 — Write translated properties
|
|
121
88
|
|
|
122
|
-
|
|
89
|
+
Use `content.update` with the target locale:
|
|
123
90
|
|
|
124
|
-
|
|
91
|
+
```
|
|
92
|
+
tool: content.update
|
|
93
|
+
args: {
|
|
94
|
+
"path": "/sites/SITE_KEY/home/about/main/intro-text",
|
|
95
|
+
"locale": "fr",
|
|
96
|
+
"properties": {
|
|
97
|
+
"jcr:title": "À propos",
|
|
98
|
+
"text": "<p>Bienvenue sur notre site.</p>"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
125
102
|
|
|
126
|
-
|
|
103
|
+
Key rules:
|
|
104
|
+
- Set all mandatory i18n properties in the same call.
|
|
105
|
+
- Translate only i18n properties.
|
|
106
|
+
- Preserve the HTML structure for rich text.
|
|
107
|
+
- Do not translate technical choicelist values.
|
|
127
108
|
|
|
128
|
-
|
|
129
|
-
import json
|
|
130
|
-
from urllib.request import Request, urlopen
|
|
109
|
+
---
|
|
131
110
|
|
|
132
|
-
|
|
133
|
-
AUTH = ("root", "root1234")
|
|
111
|
+
## Step 5 — Translate page titles
|
|
134
112
|
|
|
135
|
-
|
|
136
|
-
token = base64.b64encode(f"{AUTH[0]}:{AUTH[1]}".encode()).decode()
|
|
137
|
-
HEADERS = {
|
|
138
|
-
"Content-Type": "application/json",
|
|
139
|
-
"Origin": JAHIA,
|
|
140
|
-
"Authorization": f"Basic {token}",
|
|
141
|
-
}
|
|
113
|
+
Page titles are also i18n:
|
|
142
114
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
# 1. List all articles missing French title
|
|
153
|
-
result = gql(
|
|
154
|
-
'{ jcr { nodesByQuery(query: "SELECT * FROM [namespace:article] '
|
|
155
|
-
"WHERE ISDESCENDANTNODE('/sites/mySite/contents') "
|
|
156
|
-
'ORDER BY [jcr:path] ASC", queryLanguage: SQL2) '
|
|
157
|
-
'{ nodes { path properties(language: "fr") { name value } } } } }'
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
nodes = result["data"]["jcr"]["nodesByQuery"]["nodes"]
|
|
161
|
-
missing_fr = [
|
|
162
|
-
n["path"]
|
|
163
|
-
for n in nodes
|
|
164
|
-
if not any(p["name"] == "jcr:title" and p["value"] for p in n["properties"])
|
|
165
|
-
]
|
|
166
|
-
|
|
167
|
-
# 2. Set French translations (replace with actual translated values)
|
|
168
|
-
translations = {
|
|
169
|
-
"/sites/mySite/contents/articles/article-1": ("Titre FR 1", "<p>Corps FR 1</p>"),
|
|
170
|
-
"/sites/mySite/contents/articles/article-2": ("Titre FR 2", "<p>Corps FR 2</p>"),
|
|
115
|
+
```
|
|
116
|
+
tool: content.update
|
|
117
|
+
args: {
|
|
118
|
+
"path": "/sites/SITE_KEY/home/about",
|
|
119
|
+
"locale": "fr",
|
|
120
|
+
"properties": {
|
|
121
|
+
"jcr:title": "À propos"
|
|
122
|
+
}
|
|
171
123
|
}
|
|
172
|
-
|
|
173
|
-
for path, (title, body) in translations.items():
|
|
174
|
-
r = gql(
|
|
175
|
-
f'mutation {{ jcr {{ mutateNode(pathOrId: "{path}") {{'
|
|
176
|
-
f' setPropertiesBatch(properties: ['
|
|
177
|
-
f' {{name: "body", value: {json.dumps(body)}, language: "fr"}},'
|
|
178
|
-
f' {{name: "jcr:title", value: {json.dumps(title)}, language: "fr"}}'
|
|
179
|
-
f' ]) {{ path }} }} }} }}'
|
|
180
|
-
)
|
|
181
|
-
ok = "errors" not in r
|
|
182
|
-
print(f" {'✓' if ok else '✗'} {path.split('/')[-1]}")
|
|
183
124
|
```
|
|
184
125
|
|
|
185
126
|
---
|
|
186
127
|
|
|
187
|
-
## Step
|
|
128
|
+
## Step 6 — Verify translations
|
|
188
129
|
|
|
189
|
-
|
|
130
|
+
Check the translated locale directly:
|
|
190
131
|
|
|
191
|
-
|
|
132
|
+
```
|
|
133
|
+
tool: content.get
|
|
134
|
+
args: {
|
|
135
|
+
"path": "/sites/SITE_KEY/home/about/main/intro-text",
|
|
136
|
+
"locale": "fr"
|
|
137
|
+
}
|
|
138
|
+
```
|
|
192
139
|
|
|
193
|
-
|
|
194
|
-
// In the view component — translate the stored key to a display label
|
|
195
|
-
const STATUS_LABELS: Record<string, Record<string, string>> = {
|
|
196
|
-
en: { featured: "Featured", draft: "Draft" },
|
|
197
|
-
fr: { featured: "En vedette", draft: "Brouillon" },
|
|
198
|
-
};
|
|
140
|
+
Or search in the target locale:
|
|
199
141
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
142
|
+
```
|
|
143
|
+
tool: content.search
|
|
144
|
+
args: {
|
|
145
|
+
"siteKey": "SITE_KEY",
|
|
146
|
+
"nodeType": "jmix:droppableContent",
|
|
147
|
+
"locale": "fr",
|
|
148
|
+
"limit": 20,
|
|
149
|
+
"projectProperties": ["jcr:title"]
|
|
150
|
+
}
|
|
203
151
|
```
|
|
204
152
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
### Hardcoded UI strings
|
|
153
|
+
---
|
|
208
154
|
|
|
209
|
-
|
|
155
|
+
## Step 7 — Publish the translated locale
|
|
210
156
|
|
|
211
|
-
|
|
212
|
-
const LABELS = {
|
|
213
|
-
en: { readMore: "Read more", by: "By" },
|
|
214
|
-
fr: { readMore: "Lire la suite", by: "Par" },
|
|
215
|
-
};
|
|
157
|
+
Publish the page or subtree in the target language:
|
|
216
158
|
|
|
217
|
-
const t = LABELS[renderContext.getMainResourceLocale().getLanguage()] ?? LABELS.en;
|
|
218
|
-
// Usage: <a>{t.readMore}</a>
|
|
219
159
|
```
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
When you remove the `i18n` flag from a CND property (or delete a language from the site), orphaned `j:translation_XX` child nodes may remain. Inspect and remove them if needed:
|
|
226
|
-
|
|
227
|
-
```bash
|
|
228
|
-
# Find translation sub-nodes for a content node
|
|
229
|
-
curl -s -u root:root1234 \
|
|
230
|
-
-H "Content-Type: application/json" \
|
|
231
|
-
-H "Origin: http://localhost:8080" \
|
|
232
|
-
-X POST http://localhost:8080/modules/graphql \
|
|
233
|
-
-d '{
|
|
234
|
-
"query": "{ jcr { nodeByPath(path: \"/sites/mySite/contents/articles/my-article\") { children { nodes { name primaryNodeType { name } } } } } }"
|
|
235
|
-
}'
|
|
236
|
-
|
|
237
|
-
# Delete an orphaned translation node
|
|
238
|
-
curl -s -u root:root1234 \
|
|
239
|
-
-H "Content-Type: application/json" \
|
|
240
|
-
-H "Origin: http://localhost:8080" \
|
|
241
|
-
-X POST http://localhost:8080/modules/graphql \
|
|
242
|
-
-d '{
|
|
243
|
-
"query": "mutation { jcr { deleteNode(pathOrId: \"/sites/mySite/contents/articles/my-article/j:translation_fr\") }"
|
|
244
|
-
}'
|
|
160
|
+
tool: publication.publish
|
|
161
|
+
args: {
|
|
162
|
+
"path": "/sites/SITE_KEY/home/about",
|
|
163
|
+
"languages": ["fr"]
|
|
164
|
+
}
|
|
245
165
|
```
|
|
246
166
|
|
|
167
|
+
If the translation touches both a page and child content, publish the page path so the subtree is included.
|
|
168
|
+
|
|
247
169
|
---
|
|
248
170
|
|
|
249
|
-
##
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
171
|
+
## Common patterns
|
|
172
|
+
|
|
173
|
+
### Translate all content under a page
|
|
174
|
+
|
|
175
|
+
1. Discover the page structure:
|
|
176
|
+
```
|
|
177
|
+
tool: page.structure
|
|
178
|
+
args: { "path": "/sites/SITE_KEY/home/about" }
|
|
179
|
+
```
|
|
180
|
+
2. Read each child node in the source locale:
|
|
181
|
+
```
|
|
182
|
+
tool: content.get
|
|
183
|
+
args: { "path": "CHILD_PATH", "locale": "en" }
|
|
184
|
+
```
|
|
185
|
+
3. Write translated values to the target locale:
|
|
186
|
+
```
|
|
187
|
+
tool: content.update
|
|
188
|
+
args: {
|
|
189
|
+
"path": "CHILD_PATH",
|
|
190
|
+
"locale": "fr",
|
|
191
|
+
"properties": { "jcr:title": "...", "text": "..." }
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
4. Publish the page in the new language.
|
|
195
|
+
|
|
196
|
+
### Audit whether a page is publish-ready in the new locale
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
tool: publication.status
|
|
200
|
+
args: {
|
|
201
|
+
"path": "/sites/SITE_KEY/home/about",
|
|
202
|
+
"language": "fr",
|
|
203
|
+
"subNodes": true,
|
|
204
|
+
"references": true
|
|
205
|
+
}
|
|
271
206
|
```
|
|
272
207
|
|
|
273
208
|
---
|
|
@@ -276,22 +211,16 @@ curl -s -u root:root1234 \
|
|
|
276
211
|
|
|
277
212
|
| Error | Cause | Fix |
|
|
278
213
|
|-------|-------|-----|
|
|
279
|
-
| `
|
|
280
|
-
|
|
|
281
|
-
|
|
|
282
|
-
|
|
|
283
|
-
| Choicelist key changed per language | Property incorrectly declared `i18n` in CND | Remove `i18n` from the CND property; translate keys in the view |
|
|
214
|
+
| `MANDATORY_PROPERTY_MISSING` | Not all required i18n properties were set | Set all mandatory translated properties in one `content.update` call |
|
|
215
|
+
| Language not available | Locale not enabled on the site | Add the locale to the site first |
|
|
216
|
+
| Properties appear empty | Wrong locale was used | Verify configured locales with `site.get` |
|
|
217
|
+
| Translation not visible on the public site | It is still only in EDIT | Publish with `publication.publish` |
|
|
284
218
|
|
|
285
219
|
---
|
|
286
220
|
|
|
287
|
-
##
|
|
221
|
+
## Related skills
|
|
222
|
+
|
|
223
|
+
- `/jahia-content-explore-structure` — find the right pages, nodes, and types first
|
|
224
|
+
- `/jahia-content-publish` — publish translated content and inspect language-scoped status
|
|
225
|
+
- `/jahia-content-create-content` — create new pages or content that will later need translation
|
|
288
226
|
|
|
289
|
-
```
|
|
290
|
-
1. Enable language → mutateNode j:languages with full list
|
|
291
|
-
2. Audit → nodesByQuery with properties(language: "XX") to find gaps
|
|
292
|
-
3. Translate → setPropertiesBatch with language: "XX" for each i18n field
|
|
293
|
-
4. View strings → add locale-keyed label maps in .server.tsx
|
|
294
|
-
5. Choicelists → translate keys in the view, not the JCR
|
|
295
|
-
6. Publish → publish(languages: ["XX"]) for all affected nodes
|
|
296
|
-
7. Verify → query back with language: "XX" to confirm values
|
|
297
|
-
```
|