Translations
Contents
Translations#
Note
This is only available on Plone 5.
Since Plone 5 the product plone.app.multilingual is included in the base Plone installation although it is not enabled by default.
Multilingualism in Plone not only allows the managers of the site to configure the site interface texts to be in one language or another (such as the configuration menus, error messages, information messages or other static text) but also to configure Plone to handle multilingual content. To achieve that it provides the user interface for managing content translations.
You can get additional information about the multilingual capabilities of Plone in the documentation.
In connection with that capabilities, plone.restapi provides a @translations endpoint to handle the translation information of the content objects.
Once we have installed plone.app.multilingual and enabled more than one language we can link two content-items of different languages to be the translation of each other issuing a POST query to the @translations endpoint including the id of the content which should be linked to. The id of the content must be a full URL of the content object:
http
POST /plone/en/test-document/@translations HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json
{
"id": "http://localhost:55001/plone/es/test-document"
}
curl
curl -i -X POST http://nohost/plone/en/test-document/@translations -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"id": "http://localhost:55001/plone/es/test-document"}' --user admin:secret
httpie
echo '{
"id": "http://localhost:55001/plone/es/test-document"
}' | http POST http://nohost/plone/en/test-document/@translations Accept:application/json Content-Type:application/json -a admin:secret
python-requests
requests.post('http://nohost/plone/en/test-document/@translations', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'id': 'http://localhost:55001/plone/es/test-document'}, auth=('admin', 'secret'))
Note
"id" is a required field and needs to point to an existing content on the site.
The API will return a 201 Created response if the linking was successful.
HTTP/1.1 201 Created
Content-Type: application/json
Location: http://localhost:55001/plone/en/test-document
{}
We can also use the object's path to link the translation instead of the full URL:
http
POST /plone/en/test-document/@translations HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json
{
"id": "/es/test-document"
}
curl
curl -i -X POST http://nohost/plone/en/test-document/@translations -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"id": "/es/test-document"}' --user admin:secret
httpie
echo '{
"id": "/es/test-document"
}' | http POST http://nohost/plone/en/test-document/@translations Accept:application/json Content-Type:application/json -a admin:secret
python-requests
requests.post('http://nohost/plone/en/test-document/@translations', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'id': '/es/test-document'}, auth=('admin', 'secret'))
HTTP/1.1 201 Created
Content-Type: application/json
Location: http://localhost:55001/plone/en/test-document
{}
We can also use the object's UID to link the translation:
http
POST /plone/en/test-document/@translations HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json
{
"id": "SomeUUID000000000000000000000003"
}
curl
curl -i -X POST http://nohost/plone/en/test-document/@translations -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"id": "SomeUUID000000000000000000000003"}' --user admin:secret
httpie
echo '{
"id": "SomeUUID000000000000000000000003"
}' | http POST http://nohost/plone/en/test-document/@translations Accept:application/json Content-Type:application/json -a admin:secret
python-requests
requests.post('http://nohost/plone/en/test-document/@translations', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'id': 'SomeUUID000000000000000000000003'}, auth=('admin', 'secret'))
HTTP/1.1 201 Created
Content-Type: application/json
Location: http://localhost:55001/plone/en/test-document
{}
After linking the contents we can get the list of the translations of that
content item by issuing a GET
request on the @translations endpoint of
that content item.:
http
GET /plone/en/test-document/@translations HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
curl
curl -i -X GET http://nohost/plone/en/test-document/@translations -H "Accept: application/json" --user admin:secret
httpie
http http://nohost/plone/en/test-document/@translations Accept:application/json -a admin:secret
python-requests
requests.get('http://nohost/plone/en/test-document/@translations', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json
{
"@id": "http://localhost:55001/plone/en/test-document/@translations",
"items": [
{
"@id": "http://localhost:55001/plone/es/test-document",
"language": "es"
}
],
"root": {
"de": "http://localhost:55001/plone/de",
"en": "http://localhost:55001/plone/en",
"es": "http://localhost:55001/plone/es",
"fr": "http://localhost:55001/plone/fr"
}
}
To unlink the content, issue a DELETE
request on the @translations
endpoint of the content item and provide the language code you want to unlink.:
http
DELETE /plone/en/test-document/@translations HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json
{
"language": "es"
}
curl
curl -i -X DELETE http://nohost/plone/en/test-document/@translations -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"language": "es"}' --user admin:secret
httpie
echo '{
"language": "es"
}' | http DELETE http://nohost/plone/en/test-document/@translations Accept:application/json Content-Type:application/json -a admin:secret
python-requests
requests.delete('http://nohost/plone/en/test-document/@translations', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'language': 'es'}, auth=('admin', 'secret'))
Note
"language" is a required field.
HTTP/1.1 204 No Content
Creating a translation from an existing content#
The POST content endpoint to a folder is capable also of linking this new content with an
exising translation using two parameters: translationOf
and language
.
http
POST /plone/de HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json
{
"@type": "Document",
"id": "mydocument",
"language": "de",
"title": "My German Document",
"translation_of": "SomeUUID000000000000000000000003"
}
curl
curl -i -X POST http://nohost/plone/de -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"@type": "Document", "id": "mydocument", "language": "de", "title": "My German Document", "translation_of": "SomeUUID000000000000000000000003"}' --user admin:secret
httpie
echo '{
"@type": "Document",
"id": "mydocument",
"language": "de",
"title": "My German Document",
"translation_of": "SomeUUID000000000000000000000003"
}' | http POST http://nohost/plone/de Accept:application/json Content-Type:application/json -a admin:secret
python-requests
requests.post('http://nohost/plone/de', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'@type': 'Document', 'id': 'mydocument', 'language': 'de', 'title': 'My German Document', 'translation_of': 'SomeUUID000000000000000000000003'}, auth=('admin', 'secret'))
HTTP/1.1 201 Created
Content-Type: application/json
Location: http://localhost:55001/plone/de/mydocument
{
"@components": {
"actions": {
"@id": "http://localhost:55001/plone/de/mydocument/@actions"
},
"breadcrumbs": {
"@id": "http://localhost:55001/plone/de/mydocument/@breadcrumbs"
},
"contextnavigation": {
"@id": "http://localhost:55001/plone/de/mydocument/@contextnavigation"
},
"navigation": {
"@id": "http://localhost:55001/plone/de/mydocument/@navigation"
},
"translations": {
"@id": "http://localhost:55001/plone/de/mydocument/@translations"
},
"types": {
"@id": "http://localhost:55001/plone/de/mydocument/@types"
},
"workflow": {
"@id": "http://localhost:55001/plone/de/mydocument/@workflow"
}
},
"@id": "http://localhost:55001/plone/de/mydocument",
"@type": "Document",
"UID": "SomeUUID000000000000000000000005",
"allow_discussion": false,
"changeNote": "",
"contributors": [],
"created": "1995-07-31T13:45:00",
"creators": [
"admin"
],
"description": "",
"effective": null,
"exclude_from_nav": false,
"expires": null,
"id": "mydocument",
"is_folderish": false,
"language": {
"title": "Deutsch",
"token": "de"
},
"layout": "document_view",
"lock": {
"locked": false,
"stealable": true
},
"modified": "1995-07-31T17:30:00",
"next_item": {},
"parent": {
"@id": "http://localhost:55001/plone/de",
"@type": "LRF",
"description": "",
"review_state": "published",
"title": "Deutsch"
},
"previous_item": {
"@id": "http://localhost:55001/plone/de/assets",
"@type": "LIF",
"description": "",
"title": "Assets"
},
"relatedItems": [],
"review_state": "private",
"rights": "",
"subjects": [],
"table_of_contents": null,
"text": null,
"title": "My German Document",
"version": "current",
"versioning_enabled": true,
"working_copy": null,
"working_copy_of": null
}
Get location in the tree for new translations#
When you create a translation in Plone, there are policies in place for finding a suitable placement for it. This endpoint returns the proper placement for the newly going to be created translation.
http
GET /plone/es/test-document/@translation-locator?target_language=de HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
curl
curl -i -X GET 'http://nohost/plone/es/test-document/@translation-locator?target_language=de' -H "Accept: application/json" --user admin:secret
httpie
http 'http://nohost/plone/es/test-document/@translation-locator?target_language=de' Accept:application/json -a admin:secret
python-requests
requests.get('http://nohost/plone/es/test-document/@translation-locator?target_language=de', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json
{
"@id": "http://localhost:55001/plone/de"
}
Expansion#
This endpoint can be used with the Expansion mechanism which allows to get additional information about a content item in one query, avoiding unnecesary requests.
If a simple GET
request is done on the content item, a new entry will be shown on the @components
entry with the URL of the @translations endpoint: