Metadata-Version: 2.4
Name: interaktiv.alttextgenerator
Version: 1.1.0
Summary: Generate alternative texts for images.
Project-URL: Homepage, https://github.com/interaktivgmbh/interaktiv.alttextgenerator
Project-URL: PyPI, https://pypi.org/project/interaktiv.alttextgenerator
Project-URL: Source, https://github.com/interaktivgmbh/interaktiv.alttextgenerator
Project-URL: Tracker, https://github.com/interaktivgmbh/interaktiv.alttextgenerator/issues
Author-email: Interaktiv GmbH <info@interaktiv.de>
License-Expression: GPL-2.0-only
License-File: LICENSE.md
Keywords: AI,Accessibility,CMS,Plone,Python
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Web Environment
Classifier: Framework :: Plone
Classifier: Framework :: Plone :: 6.0
Classifier: Framework :: Plone :: 6.1
Classifier: Framework :: Plone :: Addon
Classifier: License :: OSI Approved :: GNU General Public License v2 (GPLv2)
Classifier: Operating System :: OS Independent
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
Requires-Python: <3.14,>=3.10
Requires-Dist: cairosvg==2.7.1
Requires-Dist: interaktiv-aiclient==1.1.0
Requires-Dist: interaktiv-alttexts==1.0.0
Requires-Dist: plone-api
Requires-Dist: plone-restapi
Requires-Dist: plone-volto
Requires-Dist: products-cmfplone
Provides-Extra: release
Requires-Dist: zest-pocompile; extra == 'release'
Requires-Dist: zest-releaser[recommended]; extra == 'release'
Requires-Dist: zestreleaser-towncrier; extra == 'release'
Provides-Extra: test
Requires-Dist: horse-with-no-namespace; extra == 'test'
Requires-Dist: plone-app-testing; extra == 'test'
Requires-Dist: plone-restapi[test]; extra == 'test'
Requires-Dist: pytest; extra == 'test'
Requires-Dist: pytest-cov; extra == 'test'
Requires-Dist: pytest-plone>=0.5.0; extra == 'test'
Description-Content-Type: text/markdown

# interaktiv.alttextgenerator

[![interaktiv.alttextgenerator CI](https://github.com/interaktivgmbh/interaktiv.alttextgenerator/actions/workflows/ci.yml/badge.svg)](https://github.com/interaktivgmbh/interaktiv.alttextgenerator/actions/workflows/ci.yml)

Generate alternative texts for images.

This add-on helps editors provide meaningful alt texts for images using AI,
improving both accessibility and SEO. By ensuring that all images have
descriptive alternative texts, the website becomes more usable for people
using assistive technologies and more discoverable by search engines.

## Prerequisites

Tested for Plone `6.0.15`.

This add-on requires `interaktiv.aiclient` for its AI capabilities and
`interaktiv.alttexts` to provide the alt text behaviour.

Currently, this add-on only works out of the box with Volto. Therefore, you
should also install the according Volto plugin [volto-interaktiv-alttextgenerator](https://github.com/interaktivgmbh/volto-interaktiv-alttextgenerator).

## Features

![Screenshot of the Alt Text Generator controlpanel](docs/controlpanel.png)

In the controlpanel, you may configure the

* system prompt
* user prompt
* allowed image types
* blacklisted paths

Remember to configure the AI client inside its own controlpanel as well, since
otherwise the generation won't work. Once you configured everything, you're all
set.

To verify that the add-on works as intended, upload an image either from
the toolbar directly or inside an image block. Toasts visually support uploads
from image blocks, whereas uploads from the toolbar are silent.

The generated alt text can look like this:

![Sample Image](docs/sample-image.jpg)
*Image by [Drosera74](https://pixabay.com/users/drosera74-48879945/) via Pixabay*

`Iridescent blue and green hummingbird hovering with outstretched wings as it
feeds from a bright purple flower against a soft green leafy background.
(OpenAI: GPT-5.1, 2025-12-15)`

The alt text is generated by AI and includes the model used and the generation
date at the end. This metadata is appended only for AI-generated alt texts,
which can be identified via the corresponding checkbox in the image’s schema.
If the alt text is manually edited, the checkbox is automatically disabled to
indicate that the alt text is no longer AI-generated.

### Language

All alt texts are generated in the site's language. This behaviour is specified
in the default user prompt. If you specify `{language}` inside your user prompt,
it will be replaced with the site language internally. If you wish to use a
specific language for the alt texts, you can leave out `{language}` and specify
your own language directly inside the user prompt.

### Blacklisting paths

To blacklist a path, you can specify a `glob pattern`. For every request, the
image path is matched against the specified patterns. If it matches any pattern,
the generation of alternative texts is skipped.

For describing patterns, the term `segment` must first be defined:

A segment is used to describe a sequence of characters, that follows after a `/`
and is interrupted by a `/`. Given a URL `www.github.com/plone/volto` and looking
at its path `/plone/volto`, two such segments can be identified (`plone` and
`volto`).

Now all patterns can be described precisely:

* `?` - This matches exactly one character inside a segment.
* `*` - This matches zero or more characters inside a segment.
* `**` - This matches one or more segments.

#### Examples

| Pattern             | Path                          | Matches? | Explanation                                        |
|---------------------|-------------------------------|----------|----------------------------------------------------|
| `/images/*`         | `/de/images/logo.png`         | ✅        | `*` matches any file directly in `/images/`.       |
| `/images/*`         | `/de/images/icons/logo.png`   | ❌        | Only matches a single segment under `/images/`.    |
| `/images/**`        | `/de/images/icons/logo.png`   | ✅        | `**` matches files in nested folders.              |
| `/media/photo?.jpg` | `/de/media/photo1.jpg`        | ✅        | `?` matches exactly one character in the filename. |
| `/media/photo?.jpg` | `/de/media/photo12.jpg`       | ❌        | `?` matches only a single character.               |
| `/private/**`       | `/private/user/data/file.png` | ✅        | Matches any file under `/private/`.                |
| `**`                | `/de/user/profile.png`        | ✅        | Deactivates generation globally.                   |

### Migrate existing images

Chances are, you already have a few images on your Plone site and want to
generate alt texts for them as well.

To generate alt texts for existing images without alt texts, you can run the
`Interaktiv Alt Text Generator: Migration` profile from the Zope Management
Interface. Beware, this will update every image, so this process may take a
while.

![Alt Text Generator Migration Profile](docs/migration.png)

The images are processed in batches, the size of which can be configured in the
control panel.

The logger will keep you up to date with the current progress of the migration.

```terminaloutput
...
INFO    [interaktiv.alttextgenerator:89][waitress-3] Processing 10 images.
INFO    [httpx:1740][waitress-3] HTTP Request: POST https://openrouter.ai/api/v1/chat/completions "HTTP/1.1 200 OK"
...
INFO    [interaktiv.alttextgenerator:94][waitress-3] Committed changes to 10 images.
INFO    [interaktiv.alttextgenerator:99][waitress-3] Processing 8 images.
INFO    [httpx:1740][waitress-3] HTTP Request: POST https://openrouter.ai/api/v1/chat/completions "HTTP/1.1 200 OK"
...
INFO    [interaktiv.alttextgenerator:104][waitress-3] Committed changes to 8 images.
INFO    [interaktiv.alttextgenerator:106][waitress-3] 108 of total 108 images migrated.
```

## Adding this add-on to your project

Install the add-on using `pip`:

```shell
pip install interaktiv.alttextgenerator
```

or if you're using uv:

```shell
uv pip install interaktiv.alttextgenerator
```

### Install from source

You can also install the add-on from the source. In your `mx.ini` file, add:

```ini
[interaktiv.alttextgenerator]
url = git@github.com:interaktivgmbh/interaktiv.alttextgenerator.git
rev = v1.1.0
extras = test
```

Or using https:

```ini
[interaktiv.alttextgenerator]
url = https://github.com/interaktivgmbh/interaktiv.alttextgenerator.git
rev = v1.1.0
extras = test
```

## Contribute

- [Issue tracker](https://github.com/interaktivgmbh/interaktiv.alttextgenerator/issues)
- [Source code](https://github.com/interaktivgmbh/interaktiv.alttextgenerator/)

## License

The project is licensed under GPLv2.

## Credits and acknowledgements 🙏

Generated using [Cookieplone (0.9.10)](https://github.com/plone/cookieplone) and [cookieplone-templates (eae593d)](https://github.com/plone/cookieplone-templates/commit/eae593d854b137cc3ab915e1c638170cbdfb3a78) on 2025-11-21 12:25:50.251349. A special thanks to all contributors and supporters!
