Metadata-Version: 2.4
Name: cs.linguacopier
Version: 2.1
Summary: Content-copier useful to copy basic content from one language-tree to another to start working with the whole content-tree
Home-page: https://pypi.python.org/pypi/cs.linguacopier
Author: Mikel Larreategi
Author-email: mlarreategi@codesyntax.com
License: GPL version 2
Keywords: Python Plone
Classifier: Environment :: Web Environment
Classifier: Framework :: Plone
Classifier: Framework :: Plone :: 6.2
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Operating System :: OS Independent
Classifier: Development Status :: 5 - Production/Stable
Requires-Python: >3.9,<3.15
Description-Content-Type: text/markdown
Requires-Dist: plone.api
Requires-Dist: plone.app.multilingual
Requires-Dist: plone.app.textfield
Requires-Dist: plone.app.z3cform
Requires-Dist: plone.base
Requires-Dist: plone.dexterity
Requires-Dist: plone.protect
Requires-Dist: plone.uuid
Requires-Dist: Products.GenericSetup>=1.8.2
Requires-Dist: z3c.form
Requires-Dist: z3c.relationfield
Requires-Dist: zope.intid
Requires-Dist: Zope
Provides-Extra: test
Requires-Dist: plone.app.contenttypes; extra == "test"
Requires-Dist: plone.app.dexterity; extra == "test"
Requires-Dist: plone.app.relationfield; extra == "test"
Requires-Dist: plone.app.robotframework[debug]; extra == "test"
Requires-Dist: plone.app.testing; extra == "test"
Requires-Dist: plone.browserlayer; extra == "test"
Requires-Dist: plone.restapi; extra == "test"
Requires-Dist: plone.testing; extra == "test"
Requires-Dist: Products.statusmessages; extra == "test"
Requires-Dist: requests; extra == "test"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: license
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# cs.linguacopier

[![PyPI](https://img.shields.io/pypi/v/cs.linguacopier)](https://pypi.org/project/cs.linguacopier/)
[![Python versions](https://img.shields.io/pypi/pyversions/cs.linguacopier)](https://pypi.org/project/cs.linguacopier/)
[![Plone versions](https://img.shields.io/pypi/frameworkversions/plone/cs.linguacopier)](https://pypi.org/project/cs.linguacopier/)
[![Tests](https://github.com/codesyntax/cs.linguacopier/actions/workflows/test-matrix.yml/badge.svg)](https://github.com/codesyntax/cs.linguacopier/actions)
[![License](https://img.shields.io/pypi/l/cs.linguacopier)](https://github.com/codesyntax/cs.linguacopier/blob/master/LICENSE.txt)
[![GitHub issues](https://img.shields.io/github/issues/codesyntax/cs.linguacopier)](https://github.com/codesyntax/cs.linguacopier/issues)
[![GitHub last commit](https://img.shields.io/github/last-commit/codesyntax/cs.linguacopier)](https://github.com/codesyntax/cs.linguacopier/commits/master)

[Full Documentation](https://codesyntax.github.io/cs.linguacopier/)

This products adds an action to copy contents to a selected language.

We have faced many times the work to create the contents of a site in one language and then recreate
it in another language to let the customer or translators translate it.

This products provides an action with several options, which allows the content editor to recreate the contents of one section of the site in one or more languages, easing the work of the content editor.

Disclaimer: [check the documentation](https://codesyntax.github.io/cs.linguacopier/) to learn how this product can help you on effectively translating the content.

## Translation

If a translation service is configured in Plone — for example Google Translate or DeepL — a copy can optionally **translate** the copied text as it goes.

- Tick **Translate the copied content?** in the classic UI form, or send `"translate": true` over REST.
- Page titles, descriptions, and rich text are translated with the configured service, preserving rich-text markup.
- Fields marked language-independent (for example a shared relation) are left to `plone.app.multilingual`; this add-on does not copy or translate them.
- When nothing can translate a value, the original is kept and the copy is not aborted.
- The copy report shows, per object, whether it was translated, partially translated, or left as-is.

Translation is optional. Without a configured service — or without the (merged but unreleased) `plone.app.multilingual` [external-translation API](https://github.com/plone/plone.app.multilingual/pull/468) — the copy behaves exactly like a plain copy.

## Installation

Install cs.linguacopier by adding `cs.linguacopier` it to your project's dependencies (either buildout, pyproject.toml, requirements.txt, uv or whatever you use to manage your Plone project's dependencies).

## REST API

When [`plone.restapi`](https://pypi.org/project/plone.restapi/) is installed, the copier is also available over REST, so a Volto front end can use it:

```
POST /<content>/@copy-content-to
```

with a JSON body such as:

```json
{
  "target_languages": ["es", "ca"],
  "include_context": true,
  "include_children": true,
  "translate": true
}
```

The endpoint requires the **Manage portal** permission and always answers `200` with a per-object result, including the translation outcome of each copied object. See the [documentation](https://codesyntax.github.io/cs.linguacopier/) for the full request and response contract.

## Contribute

- [Issue tracker](https://github.com/codesyntax/cs.linguacopier/issues)
- [Source code](https://github.com/codesyntax/cs.linguacopier)
- [Use case](https://erral.github.io/ploneconf2017-multi-plone/)

## Support

If you are having issues, please let us know using the Github Issue Tracker: https://github.com/codesyntax/cs.linguacopier/issues

## License

The project is licensed under the GPLv2.

## Contributors

- Mikel Larreategi, mlarreategi@codesyntax.com


# Changelog

<!--
   You should *NOT* be adding new change log entries to this file.
   You should create a file in the news directory instead.
   For helpful instructions, please see:
   https://github.com/plone/plone.releaser/blob/master/ADD-A-NEWS-ITEM.rst
-->

<!-- towncrier release notes start -->

## 2.1 (2026-10-05)


### New features

- Add a ``translate`` option to the content copier: a checkbox in the
  ``@@copy-content-to`` form and a ``translate`` boolean on the
  ``@copy-content-to`` REST request. When set, the copied text field values are
  translated with the external translation service configured in Plone, keeping
  the original value when nothing can translate it. Fields marked as
  language-independent are left to plone.app.multilingual, which shares and keeps
  them in sync, so the copier does not copy them. The copy report shows which
  items were translated in full, in part, or not at all. 


### Documentation

- Document the optional translation of copied content: the translate option in the
  classic UI form and the REST API, the three-valued translation outcome in the copy
  report, the field selection and fallbacks, and the external translation service it
  relies on. 

## 2.0 (2026-10-02)


### Breaking changes

- Replace ``pkg_resources`` namespace with PEP 420 native namespace.
  Support only Plone 6.2 and Python 3.10+. #3928
- Rename the ``@@copy-content-to`` form fields to ``include_context`` and
  ``include_children``, matching the new REST API parameter names. 


### New features

- Add a ``POST /<content>/@copy-content-to`` REST service so that a Volto front end
  can copy content and its subobjects into target languages. The endpoint is
  available when ``plone.restapi`` is installed. 
- Show the outcome of a copy in the classic-UI ``@@copy-content-to`` form: a
  per-object report (created, updated, skipped, failed) with the reasons for the
  failures, exportable as CSV. 
- Stop offering the content's own language as a copy target: the
  ``@@copy-content-to`` form lists only the other supported languages (and is
  hidden when there is none), and the REST endpoint rejects a request that names
  the content's own language. 


### Bug fixes

- Fix ``copy_other_things`` adapter lookup and updating of existing
  properties in ``copy_other_properties``. 


### Internal

- Update configuration files @plone 


### Tests

- Add unit and integration tests for the content copier. 

## 1.3 (2025-08-28)


### Internal

- Repackage @erral


## 1.2 (2024-07-23)

- Remove includeDependencies for Plone 6 compatibility. @erral


## 1.1 (2021-03-22)

- add my name @libargutxi
- RelationList @libargutxi
- RelationList fields @libargutxi

## 1.0 (2019-07-11)

- Initial release. @erral
