Metadata-Version: 2.4
Name: cs.linguacopier
Version: 2.3
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.folder
Requires-Dist: plone.i18n
Requires-Dist: plone.namedfile
Requires-Dist: plone.protect
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: collective.z3cform.datagridfield; 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.autoform; extra == "test"
Requires-Dist: plone.browserlayer; extra == "test"
Requires-Dist: plone.namedfile; 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.3 (2026-10-15)


### New features

- Data grid field values are no longer copied verbatim: their free-text columns
  are translated row by row (using the same free-text-only rule), while numbers,
  choices and other non-text columns are copied as is. 


### Bug fixes

- Only free-text field values are now sent to the translation service. Controlled
  tokens (vocabulary/taxonomy choices), numbers, booleans, dates and times, e-mail
  addresses, URLs, passwords, relations, JSON, and file/image blobs are copied
  verbatim, so missing translation calls are avoided and their values are never
  sent to a translator. 
- Ownership metadata fields (creators, contributors and rights) are copied verbatim
  and no longer sent to the translation service. 
- Related items are now remapped to the corresponding translated objects when
  copying, for single relation choices as well as relation lists, and for relation
  fields provided by a behavior and not just those on the object's own schema. An
  unused, Archetypes-era helper that duplicated this for UID lists is removed. 


### Internal

- Update configuration files @plone 

## 2.2 (2026-10-08)


### New features

- When a copy translates content, the copied object's id (its URL segment) is now
  derived from its translated title, normalized with the target language's rules,
  so a translated page has a URL in the target language instead of the original
  wording. It applies only when a translation is first created, keeps the default
  id when the title is empty, and makes colliding ids unique the Plone way. 


### Bug fixes

- A copied subtree now keeps the source's sibling order. The copier enumerates each
  folder's direct children in their position order and, once the copy is done, sets
  each target folder's order to match its source, so a translated section reads in
  the same sequence as the original (including nested folders and existing
  translations). 
- Stop translating fields whose value is a controlled token — a vocabulary term, a
  taxonomy value, or any other enumerated value. Such fields are now copied
  verbatim, so a translated copy never stores an invalid value that can break the
  page that renders it; free text is still translated. 

## 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
