Skip to content

IBX-10684: Document translation management - #3249

Merged
dabrt merged 34 commits into
release_5.0.10from
translations-management
Aug 20, 2026
Merged

dabrt merged 34 commits into
release_5.0.10from
translations-management

Conversation

@dabrt

@dabrt dabrt commented Jun 18, 2026

Copy link
Copy Markdown
Contributor
Question Answer
JIRA Ticket IBX-10684
Versions 5.0 and up
Edition all

Document translation management

Checklist

  • Text renders correctly
  • Text has been checked with vale
  • Description metadata is up to date
  • Code samples are working
  • PHP code samples have been fixed with PHP CS fixer
  • Added link to this PR in relevant JIRA ticket or code PR

@adriendupuis
adriendupuis marked this pull request as draft June 19, 2026 07:12
Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated
Comment thread docs/api/event_reference/translations_management_events.md Outdated
@dabrt
dabrt requested a review from mikadamczyk June 24, 2026 07:02
@dabrt
dabrt marked this pull request as ready for review June 25, 2026 12:41
dabrt and others added 5 commits June 25, 2026 16:34
Co-Authored-By: dabrt <dabrt@users.noreply.github.com>
Co-Authored-By: Marek Nocoń <mnocon@users.noreply.github.com>
@dabrt
dabrt requested a review from AnnaKaih July 22, 2026 12:53
Comment thread docs/api/event_reference/translations_management_events.md Outdated
Comment thread docs/multisite/translations_management/configure_translations_management.md Outdated
Comment thread code_samples/translations_management/config/services.yaml Outdated
Comment thread docs/multisite/translations_management/configure_translations_management.md Outdated
Comment thread docs/multisite/translations_management/configure_translations_management.md Outdated
Comment thread docs/multisite/translations_management/configure_translations_management.md Outdated
Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated
Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated
Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated

@mnocon mnocon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review without the "Extend..." article (will do the review of it soon)

Comment thread code_samples/translations_management/config/services.yaml Outdated
Comment thread docs/api/event_reference/translations_management_events.md Outdated
Comment thread docs/api/event_reference/translations_management_events.md Outdated
Comment thread docs/multisite/translations_management/translations_management_guide.md Outdated
Comment thread docs/multisite/translations_management/translations_management_guide.md Outdated
Comment thread docs/multisite/translations_management/translations_management_guide.md Outdated
Comment thread docs/multisite/translations_management/configure_translations_management.md Outdated
Comment thread docs/multisite/translations_management/configure_translations_management.md Outdated
Comment thread docs/multisite/translations_management/translations_management_guide.md Outdated
@dabrt
dabrt requested a review from mnocon August 18, 2026 14:18
Comment thread docs/multisite/translations_management/translations_management.md Outdated
Comment thread docs/multisite/translations_management/configure_translations_management.md Outdated
Comment thread docs/multisite/translations_management/configure_translations_management.md Outdated
Comment thread docs/multisite/translations_management/configure_translations_management.md Outdated
Comment thread docs/multisite/translations_management/configure_translations_management.md Outdated
Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated
Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated
Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated
Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated
Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated
@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown

Summary

Status Count
🔍 Total 750666
🔗 Unique 15033
✅ Successful 6268
⏳ Timeouts 0
🔀 Redirected 8
👻 Excluded 744372
❓ Unknown 0
🚫 Errors 26
⛔ Unsupported 0

Errors per input

Errors in site/administration/configuration/configuration/index.html

Errors in site/api/php_api/php_api/index.html

Errors in site/infrastructure_and_maintenance/cache/http_cache/reverse_proxy/index.html

Errors in site/multisite/translations_management/configure_translations_management/index.html

  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/userdoc-5.0/site/content_management/translate_content/index.html#add-new-translation (at 14811:25) | Cannot find fragment
  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/userdoc-5.0/site/content_management/translate_content/index.html#manage-translation-services-and-language-pairs (at 14815:17) | Cannot find fragment
  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/userdoc-5.0/site/content_management/translate_content/index.html#side-by-side-translation-view (at 14817:17) | Cannot find fragment
  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/userdoc-5.0/site/content_management/translate_content/index.html#side-by-side-translation-view (at 14826:109) | Cannot find fragment

Errors in site/multisite/translations_management/translate_with_cli/index.html

  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/userdoc-5.0/site/content_management/translate_content/index.html#add-new-translation (at 14310:112) | Cannot find fragment

Errors in site/multisite/translations_management/translations_management_guide/index.html

  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/userdoc-5.0/site/content_management/translate_content/index.html#review-automatic-translation (at 14478:22) | Cannot find fragment
  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/userdoc-5.0/site/content_management/translate_content/index.html#side-by-side-translation-view (at 14455:50) | Cannot find fragment

Errors in site/permissions/custom_policies/index.html

Errors in site/release_notes/ibexa_dxp_v4.6/index.html

  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/devdoc-4.6/site/content_management/rich_text/extend_online_editor/index.html#provide-translations-for-custom-tags (at 17146:39) | Cannot find fragment
  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/devdoc-4.6/site/infrastructure_and_maintenance/background_tasks/index.html#siteaccessstamp (at 17142:44) | Cannot find fragment
  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/devdoc-4.6/site/update_and_migration/from_4.6/update_from_4.6/index.html#v4632 (at 17164:49) | Cannot find fragment

Errors in site/release_notes/ibexa_dxp_v5.0/index.html

  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/devdoc-5.0/site/content_management/rich_text/extend_online_editor/index.html#provide-translations-for-custom-tags (at 15766:39) | Cannot find fragment
  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/devdoc-5.0/site/infrastructure_and_maintenance/background_tasks/index.html#siteaccessstamp (at 15762:44) | Cannot find fragment
  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/devdoc-5.0/site/multisite/translations_management/extend_translations_management/index.html (at 15711:39) | File not found. Check if file exists and path is correct
  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/devdoc-5.0/site/release_notes/cohesivo_v6.0_deprecations/index.html (at 15760:83) | File not found. Check if file exists and path is correct
  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/devdoc-5.0/site/update_and_migration/from_5.0/update_from_5.0/index.html#v5010 (at 15778:49) | Cannot find fragment
  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/userdoc-5.0/site/content_management/translate_content/index.html#side-by-side-translation-view (at 15691:15) | Cannot find fragment
  • [ERROR] file:///home/runner/work/documentation-developer/documentation-developer/repositories/userdoc-5.0/site/content_management/translate_content/index.html#side-by-side-translation-view (at 15693:39) | Cannot find fragment
  • [404] https://github.com/ibexa/commerce/releases/tag/v5.0.10 (at 15776:14) | Rejected status code: 404 Not Found
  • [404] https://github.com/ibexa/experience/releases/tag/v5.0.10 (at 15775:14) | Rejected status code: 404 Not Found
  • [404] https://github.com/ibexa/headless/releases/tag/v5.0.10 (at 15774:14) | Rejected status code: 404 Not Found

Errors in site/search/search_criteria_and_sort_clauses/index.html

Redirects per input

Redirects in site/administration/back_office/customize_search_suggestion/index.html

Redirects in site/administration/project_organization/project_organization/index.html

Redirects in site/api/php_api/php_api/index.html

Redirects in site/api/rest_api/extending_rest_api/creating_new_rest_resource/index.html

Redirects in site/commerce/checkout/checkout/index.html

Redirects in site/commerce/checkout/configure_checkout/index.html

Redirects in site/content_management/field_types/type_and_value/index.html

Redirects in site/release_notes/ez_platform_v3.0_deprecations/index.html

Full Github Actions output

@github-advanced-security github-advanced-security AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SonarCloud found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

@dabrt
dabrt changed the base branch from 5.0 to release_5.0.10 August 19, 2026 08:54
@dabrt
dabrt requested a review from mnocon August 19, 2026 20:11

@julitafalcondusza julitafalcondusza left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check my comments.

Comment thread docs/api/event_reference/translations_management_events.md Outdated
Comment thread docs/api/event_reference/translations_management_events.md Outdated
Comment thread docs/api/event_reference/translations_management_events.md Outdated
Comment thread docs/multisite/img/translations_management_flow.png
Comment thread docs/multisite/translations_management/configure_translations_management.md Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Benefits" section is missing.
There is a list of challenges at the top of the article, but the corresponding list of benefits is missing at the end. Adding one would help summarize the feature and highlight its value.

Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated
Comment thread docs/multisite/translations_management/configure_translations_management.md Outdated
Comment thread docs/multisite/translations_management/translations_management_guide.md Outdated
Comment thread docs/multisite/translations_management/translations_management_guide.md Outdated
Comment thread docs/multisite/translations_management/configure_translations_management.md Outdated
Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated
Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated
Comment thread docs/multisite/translations_management/configure_translations_management.md Outdated
Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated
Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated
Comment thread docs/multisite/translations_management/translations_management_guide.md Outdated
Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated

@julitafalcondusza julitafalcondusza left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conditional approve, after release please add mentioned "Benefits" section and update the diagram.

@mnocon mnocon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small things to follow-up with

``` yaml
[[= include_code('code_samples/translations_management/config/services.yaml', 1, 1) =]]
[[= include_code('code_samples/translations_management/config/services.yaml', 15, 27) =]]
[[= include_code('code_samples/translations_management/config/services.yaml', 15, 23) =]]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

It's still showing too much, it includes the "Exlude with existing class" code sample

Comment thread docs/multisite/translations_management/extend_translations_management.md Outdated
@github-actions

Copy link
Copy Markdown

code_samples/ change report

Before (on target branch)After (in current PR)

code_samples/translations_management/config/services.yaml


code_samples/translations_management/config/services.yaml

docs/multisite/translations_management/extend_translations_management.md@34:``` yaml
docs/multisite/translations_management/extend_translations_management.md@35:[[= include_code('code_samples/translations_management/config/services.yaml', 1, 6) =]]
docs/multisite/translations_management/extend_translations_management.md@36:```

001⫶services:
002⫶ App\TranslationsManagement\MyCustomProvider:
003⫶ tags:
004⫶ - name: 'ibexa.translations_management.auto_translate.provider'
005⫶ identifier: 'my_custom_provider'
006⫶ validation_profile: 'my_custom_profile'

docs/multisite/translations_management/extend_translations_management.md@51:``` yaml
docs/multisite/translations_management/extend_translations_management.md@52:[[= include_code('code_samples/translations_management/config/services.yaml', 1, 1) =]]
docs/multisite/translations_management/extend_translations_management.md@53:[[= include_code('code_samples/translations_management/config/services.yaml', 29, 33) =]]
docs/multisite/translations_management/extend_translations_management.md@54:```

001⫶services:
002⫶ App\TranslationsManagement\MyCustomAiProvider:
003⫶ tags:
004⫶ - name: 'ibexa.translations_management.auto_translate.provider'
005⫶ identifier: 'my_custom_ai_provider'
006⫶ validation_profile: 'ai_generic'

docs/multisite/translations_management/extend_translations_management.md@73:``` yaml
docs/multisite/translations_management/extend_translations_management.md@74:[[= include_code('code_samples/translations_management/config/services.yaml', 1, 1) =]]
docs/multisite/translations_management/extend_translations_management.md@75:[[= include_code('code_samples/translations_management/config/services.yaml', 34, 37) =]]
docs/multisite/translations_management/extend_translations_management.md@76:```

001⫶services:
002⫶ App\TranslationsManagement\MyCustomLanguageNormalizer:
003⫶ tags:
004⫶ - name: 'ibexa.translations_management.auto_translate.provider.language_normalizer'
005⫶ priority: 10

docs/multisite/translations_management/extend_translations_management.md@93:``` yaml
docs/multisite/translations_management/extend_translations_management.md@94:[[= include_code('code_samples/translations_management/config/services.yaml', 1, 1) =]]
docs/multisite/translations_management/extend_translations_management.md@95:[[= include_code('code_samples/translations_management/config/services.yaml', 7, 10) =]]
docs/multisite/translations_management/extend_translations_management.md@96:```

001⫶services:
002⫶ App\TranslationsManagement\MyProviderValidator:
003⫶ tags:
004⫶ - name: 'ibexa.translations_management.auto_translate.provider.validator'
005⫶ profile: 'my_custom_profile'

docs/multisite/translations_management/extend_translations_management.md@124:``` yaml
docs/multisite/translations_management/extend_translations_management.md@125:[[= include_code('code_samples/translations_management/config/services.yaml', 1, 1) =]]
docs/multisite/translations_management/extend_translations_management.md@126:[[= include_code('code_samples/translations_management/config/services.yaml', 11, 14) =]]
docs/multisite/translations_management/extend_translations_management.md@127:```

001⫶services:
002⫶ App\TranslationsManagement\ImageAltTextTransformer:
003⫶ tags:
004⫶ - name: 'ibexa.translations_management.auto_translate.field_value_transformer'
005⫶ field_type_identifier: 'ibexa_image'

docs/multisite/translations_management/extend_translations_management.md@153:``` yaml
docs/multisite/translations_management/extend_translations_management.md@154:[[= include_code('code_samples/translations_management/config/services.yaml', 1, 1) =]]
docs/multisite/translations_management/extend_translations_management.md@155:[[= include_code('code_samples/translations_management/config/services.yaml', 15, 18) =]]
docs/multisite/translations_management/extend_translations_management.md@156:```

001⫶services:
002⫶ App\TranslationsManagement\MyCustomExclusionRule:
003⫶ tags:
004⫶ - { name: 'ibexa.translations_management.side_by_side.exclusion_rule' }
005⫶ app.translations_management.exclusion_rule.custom_field_types:

docs/multisite/translations_management/extend_translations_management.md@172:``` yaml
docs/multisite/translations_management/extend_translations_management.md@173:[[= include_code('code_samples/translations_management/config/services.yaml', 1, 1) =]]
docs/multisite/translations_management/extend_translations_management.md@174:[[= include_code('code_samples/translations_management/config/services.yaml', 24, 28) =]]
docs/multisite/translations_management/extend_translations_management.md@175:```

001⫶services:
002⫶ App\TranslationsManagement\TwigComponent\MyTranslationModalFooter:
003⫶ tags:
004⫶ - name: ibexa.twig.component
005⫶ group: 'admin-ui-content-translation-modal-footer'
006⫶ priority: 10


code_samples/translations_management/install/schema.mysql.sql


code_samples/translations_management/install/schema.mysql.sql

docs/multisite/translations_management/configure_translations_management.md@46:    ```sql
docs/multisite/translations_management/configure_translations_management.md@47: [[= include_code('code_samples/translations_management/install/schema.mysql.sql', indent_level=1) =]]
docs/multisite/translations_management/configure_translations_management.md@48: ```

001⫶ CREATE TABLE IF NOT EXISTS ibexa_auto_translation (
002⫶ id INT AUTO_INCREMENT NOT NULL,
003⫶ provider_identifier VARCHAR(190) NOT NULL,
004⫶ content_id INT NOT NULL,
005⫶ version_no INT NOT NULL,
006⫶ source_language_id BIGINT NOT NULL,
007⫶ target_language_id BIGINT NOT NULL,
008⫶ review_status VARCHAR(64) NOT NULL,
009⫶ created_at DATETIME NOT NULL COMMENT '(DC2Type:datetime_immutable)',
010⫶ updated_at DATETIME NOT NULL COMMENT '(DC2Type:datetime_immutable)',
011⫶ INDEX ibexa_auto_translation_content_version_idx (content_id, version_no),
012⫶ INDEX ibexa_auto_translation_target_language_idx (target_language_id),
013⫶ INDEX ibexa_auto_translation_review_status_idx (review_status),
014⫶ UNIQUE INDEX ibexa_auto_translation_context_uidx (content_id, version_no, source_language_id, target_language_id),
015⫶ PRIMARY KEY(id)
016⫶ ) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_520_ci` ENGINE = InnoDB;
017⫶
018⫶ CREATE TABLE IF NOT EXISTS ibexa_auto_translation_review_log (
019⫶ id INT AUTO_INCREMENT NOT NULL,
020⫶ auto_translation_id INT DEFAULT NULL,
021⫶ user_id INT NOT NULL,
022⫶ status VARCHAR(64) NOT NULL,
023⫶ operation VARCHAR(64) NOT NULL,
024⫶ created_at DATETIME NOT NULL COMMENT '(DC2Type:datetime_immutable)',
025⫶ INDEX IDX_325A3B737CE350E8 (auto_translation_id),
026⫶ INDEX ibexa_auto_translation_review_log_auto_translation_created_idx (auto_translation_id, created_at, id),
027⫶ INDEX ibexa_auto_translation_review_log_status_created_idx (status, created_at),
028⫶ INDEX ibexa_auto_translation_review_log_user_idx (user_id),
029⫶ PRIMARY KEY(id)
030⫶ ) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_520_ci` ENGINE = InnoDB;
031⫶
032⫶ ALTER TABLE ibexa_auto_translation_review_log ADD CONSTRAINT ibexa_auto_translation_review_log_auto_translation_fk
033⫶ FOREIGN KEY (auto_translation_id) REFERENCES ibexa_auto_translation (id) ON UPDATE CASCADE ON DELETE SET NULL;
034⫶ ALTER TABLE ibexa_auto_translation_review_log ADD CONSTRAINT ibexa_auto_translation_review_log_user_fk
035⫶ FOREIGN KEY (user_id) REFERENCES ibexa_user (contentobject_id) ON UPDATE CASCADE ON DELETE RESTRICT;


code_samples/translations_management/install/schema.postgresql.sql


code_samples/translations_management/install/schema.postgresql.sql

docs/multisite/translations_management/configure_translations_management.md@52:    ```sql
docs/multisite/translations_management/configure_translations_management.md@53: [[= include_code('code_samples/translations_management/install/schema.postgresql.sql', indent_level=1) =]]
docs/multisite/translations_management/configure_translations_management.md@54: ```

001⫶ CREATE TABLE IF NOT EXISTS ibexa_auto_translation (
002⫶ id SERIAL NOT NULL,
003⫶ provider_identifier VARCHAR(190) NOT NULL,
004⫶ content_id INT NOT NULL,
005⫶ version_no INT NOT NULL,
006⫶ source_language_id BIGINT NOT NULL,
007⫶ target_language_id BIGINT NOT NULL,
008⫶ review_status VARCHAR(64) NOT NULL,
009⫶ created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
010⫶ updated_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
011⫶ PRIMARY KEY(id)
012⫶ );
013⫶
014⫶ CREATE INDEX IF NOT EXISTS ibexa_auto_translation_content_version_idx ON ibexa_auto_translation (content_id, version_no);
015⫶ CREATE INDEX IF NOT EXISTS ibexa_auto_translation_target_language_idx ON ibexa_auto_translation (target_language_id);
016⫶ CREATE INDEX IF NOT EXISTS ibexa_auto_translation_review_status_idx ON ibexa_auto_translation (review_status);
017⫶ CREATE UNIQUE INDEX IF NOT EXISTS ibexa_auto_translation_context_uidx ON ibexa_auto_translation (content_id, version_no, source_language_id, target_language_id);
018⫶ COMMENT ON COLUMN ibexa_auto_translation.created_at IS '(DC2Type:datetime_immutable)';
019⫶ COMMENT ON COLUMN ibexa_auto_translation.updated_at IS '(DC2Type:datetime_immutable)';
020⫶
021⫶ CREATE TABLE IF NOT EXISTS ibexa_auto_translation_review_log (
022⫶ id SERIAL NOT NULL,
023⫶ auto_translation_id INT DEFAULT NULL,
024⫶ user_id INT NOT NULL,
025⫶ status VARCHAR(64) NOT NULL,
026⫶ operation VARCHAR(64) NOT NULL,
027⫶ created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
028⫶ PRIMARY KEY(id)
029⫶ );
030⫶
031⫶ CREATE INDEX IF NOT EXISTS IDX_325A3B737CE350E8 ON ibexa_auto_translation_review_log (auto_translation_id);
032⫶ CREATE INDEX IF NOT EXISTS ibexa_auto_translation_review_log_auto_translation_created_idx ON ibexa_auto_translation_review_log (auto_translation_id, created_at, id);
033⫶ CREATE INDEX IF NOT EXISTS ibexa_auto_translation_review_log_status_created_idx ON ibexa_auto_translation_review_log (status, created_at);
034⫶ CREATE INDEX IF NOT EXISTS ibexa_auto_translation_review_log_user_idx ON ibexa_auto_translation_review_log (user_id);
035⫶ COMMENT ON COLUMN ibexa_auto_translation_review_log.created_at IS '(DC2Type:datetime_immutable)';
036⫶
037⫶ ALTER TABLE ibexa_auto_translation_review_log ADD CONSTRAINT ibexa_auto_translation_review_log_auto_translation_fk
038⫶ FOREIGN KEY (auto_translation_id) REFERENCES ibexa_auto_translation (id) ON UPDATE CASCADE ON DELETE SET NULL;
039⫶ ALTER TABLE ibexa_auto_translation_review_log ADD CONSTRAINT ibexa_auto_translation_review_log_user_fk
040⫶ FOREIGN KEY (user_id) REFERENCES ibexa_user (contentobject_id) ON UPDATE CASCADE ON DELETE RESTRICT;


code_samples/translations_management/src/TranslationsManagement/ImageAltTextTransformer.php


code_samples/translations_management/src/TranslationsManagement/ImageAltTextTransformer.php

docs/multisite/translations_management/extend_translations_management.md@116:``` php hl_lines="21 31 37 46-58"
docs/multisite/translations_management/extend_translations_management.md@117:[[= include_code('code_samples/translations_management/src/TranslationsManagement/ImageAltTextTransformer.php') =]]
docs/multisite/translations_management/extend_translations_management.md@118:```

001⫶<?php
002⫶
003⫶declare(strict_types=1);
004⫶
005⫶namespace App\TranslationsManagement;
006⫶
007⫶use Ibexa\Contracts\Core\Repository\Values\Content\Field;
008⫶use Ibexa\Contracts\TranslationsManagement\AutoTranslate\Transformer\Field\EncodedFieldValue;
009⫶use Ibexa\Contracts\TranslationsManagement\AutoTranslate\Transformer\Field\FieldValueTransformerInterface;
010⫶use Ibexa\Core\Base\Exceptions\InvalidArgumentException;
011⫶use Ibexa\Core\FieldType\Image\Value as ImageValue;
012⫶use Ibexa\Core\FieldType\Value;
013⫶
014⫶final class ImageAltTextTransformer implements FieldValueTransformerInterface
015⫶{
016⫶ public function getFieldTypeIdentifier(): string
017⫶ {
018⫶ return 'ibexa_image';
019⫶ }
020⫶
021❇️ public function encode(Field $field): EncodedFieldValue
022⫶ {
023⫶ $value = $field->getValue();
024⫶ if (!$value instanceof ImageValue) {
025⫶ throw new InvalidArgumentException(
026⫶ '$field',
027⫶ sprintf('Expected %s, got %s.', ImageValue::class, get_debug_type($value))
028⫶ );
029⫶ }
030⫶
031❇️ return new EncodedFieldValue($value->alternativeText ?? '');
032⫶ }
033⫶
034⫶ /**
035⫶ * @param array<string, mixed> $metadata
036⫶ */
037❇️ public function decode(string $value, mixed $previousFieldValue, array $metadata): Value
038⫶ {
039⫶ if (!$previousFieldValue instanceof ImageValue) {
040⫶ throw new InvalidArgumentException(
041⫶ '$previousFieldValue',
042⫶ sprintf('Expected %s, got %s.', ImageValue::class, get_debug_type($previousFieldValue))
043⫶ );
044⫶ }
045⫶
046❇️ return new ImageValue([
047❇️ 'id' => $previousFieldValue->id,
048❇️ 'fileName' => $previousFieldValue->fileName,
049❇️ 'fileSize' => $previousFieldValue->fileSize,
050❇️ 'uri' => $previousFieldValue->uri,
051❇️ 'imageId' => $previousFieldValue->imageId,
052❇️ 'inputUri' => $previousFieldValue->inputUri,
053❇️ 'width' => $previousFieldValue->width,
054❇️ 'height' => $previousFieldValue->height,
055❇️ 'alternativeText' => $value,
056❇️ 'additionalData' => $previousFieldValue->additionalData,
057❇️ 'mime' => $previousFieldValue->mime,
058❇️ ]);
059⫶ }
060⫶}


code_samples/translations_management/src/TranslationsManagement/MyApiClient.php


code_samples/translations_management/src/TranslationsManagement/MyCustomAiProvider.php


code_samples/translations_management/src/TranslationsManagement/MyApiClient.php


code_samples/translations_management/src/TranslationsManagement/MyCustomAiProvider.php

docs/multisite/translations_management/extend_translations_management.md@44:``` php hl_lines="53 60"
docs/multisite/translations_management/extend_translations_management.md@45:[[= include_code('code_samples/translations_management/src/TranslationsManagement/MyCustomAiProvider.php') =]]
docs/multisite/translations_management/extend_translations_management.md@46:```

001⫶<?php
002⫶
003⫶declare(strict_types=1);
004⫶
005⫶namespace App\TranslationsManagement;
006⫶
007⫶use Ibexa\Contracts\TranslationsManagement\AutoTranslate\Provider\AiTranslationProviderInterface;
008⫶use Ibexa\Contracts\TranslationsManagement\AutoTranslate\TranslationDataInterface;
009⫶
010⫶final readonly class MyCustomAiProvider implements AiTranslationProviderInterface
011⫶{
012⫶ /**
013⫶ * Replace MyApiClient with your HTTP client, SDK wrapper, or any service
014⫶ * that communicates with the external AI translation API.
015⫶ */
016⫶ public function __construct(
017⫶ private MyApiClient $apiClient,
018⫶ private string $actionConfigurationIdentifier,
019⫶ ) {
020⫶ }
021⫶
022⫶ public function getIdentifier(): string
023⫶ {
024⫶ return 'my_custom_ai_provider';
025⫶ }
026⫶
027⫶ public function getName(): string
028⫶ {
029⫶ return 'My AI Translation Service';
030⫶ }
031⫶
032⫶ public function getVendorName(): string
033⫶ {
034⫶ return 'My Company Ltd';
035⫶ }
036⫶
037⫶ public function translate(TranslationDataInterface $translationData): string
038⫶ {
039⫶ return $this->apiClient->translate(
040⫶ $translationData->getText(),
041⫶ $translationData->getSourceLanguage(),
042⫶ $translationData->getTargetLanguage()
043⫶ );
044⫶ }
045⫶
046⫶ /** @return array<string> */
047⫶ public function getSupportedLanguageCodes(): array
048⫶ {
049⫶ return ['eng-GB', 'ger-DE', 'fre-FR'];
050⫶ }
051⫶
052⫶ /** @return array<string, mixed> */
053❇️ public function getConfiguration(): array
054⫶ {
055⫶ return [
056⫶ 'actionConfigurationIdentifier' => $this->actionConfigurationIdentifier,
057⫶ ];
058⫶ }
059⫶
060❇️ public function isConfigured(): bool
061⫶ {
062⫶ return $this->actionConfigurationIdentifier !== '';
063⫶ }
064⫶}


code_samples/translations_management/src/TranslationsManagement/MyCustomExclusionRule.php


code_samples/translations_management/src/TranslationsManagement/MyCustomExclusionRule.php

docs/multisite/translations_management/extend_translations_management.md@146:``` php
docs/multisite/translations_management/extend_translations_management.md@147:[[= include_code('code_samples/translations_management/src/TranslationsManagement/MyCustomExclusionRule.php') =]]
docs/multisite/translations_management/extend_translations_management.md@148:```

001⫶<?php
002⫶
003⫶declare(strict_types=1);
004⫶
005⫶namespace App\TranslationsManagement;
006⫶
007⫶use Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo;
008⫶use Ibexa\Contracts\TranslationsManagement\SideBySide\Service\SideBySideExclusionRuleInterface;
009⫶
010⫶final class MyCustomExclusionRule implements SideBySideExclusionRuleInterface
011⫶{
012⫶ public function isExcluded(ContentInfo $contentInfo): bool
013⫶ {
014⫶ return $contentInfo->getContentType()->identifier === 'my_excluded_type';
015⫶ }
016⫶}


code_samples/translations_management/src/TranslationsManagement/MyCustomLanguageCodeNormalizer.php


code_samples/translations_management/src/TranslationsManagement/MyCustomLanguageCodeNormalizer.php

docs/multisite/translations_management/extend_translations_management.md@64:``` php
docs/multisite/translations_management/extend_translations_management.md@65:[[= include_code('code_samples/translations_management/src/TranslationsManagement/MyCustomLanguageCodeNormalizer.php') =]]
docs/multisite/translations_management/extend_translations_management.md@66:```

001⫶<?php
002⫶
003⫶declare(strict_types=1);
004⫶
005⫶namespace App\TranslationsManagement;
006⫶
007⫶use Ibexa\Contracts\TranslationsManagement\AutoTranslate\Exception\UnsupportedLanguageException;
008⫶use Ibexa\Contracts\TranslationsManagement\AutoTranslate\Provider\LanguageNormalizer\LanguageNormalizerInterface;
009⫶use Ibexa\Contracts\TranslationsManagement\AutoTranslate\Provider\TranslationProviderInterface;
010⫶
011⫶final class MyCustomLanguageCodeNormalizer implements LanguageNormalizerInterface
012⫶{
013⫶ private const LANGUAGE_MAP = [
014⫶ 'eng-GB' => 'en-GB',
015⫶ 'ger-DE' => 'de',
016⫶ 'fre-FR' => 'fr',
017⫶ ];
018⫶
019⫶ public function supports(TranslationProviderInterface $provider): bool
020⫶ {
021⫶ return $provider->getIdentifier() === 'my_custom_ai_provider';
022⫶ }
023⫶
024⫶ public function normalize(
025⫶ TranslationProviderInterface $provider,
026⫶ string $languageCode
027⫶ ): string {
028⫶ if (isset(self::LANGUAGE_MAP[$languageCode])) {
029⫶ return self::LANGUAGE_MAP[$languageCode];
030⫶ }
031⫶
032⫶ throw new UnsupportedLanguageException(
033⫶ $languageCode,
034⫶ $provider->getIdentifier(),
035⫶ array_values(self::LANGUAGE_MAP)
036⫶ );
037⫶ }
038⫶}


code_samples/translations_management/src/TranslationsManagement/MyCustomProvider.php


code_samples/translations_management/src/TranslationsManagement/MyCustomProvider.php

docs/multisite/translations_management/extend_translations_management.md@27:``` php hl_lines="36-49"
docs/multisite/translations_management/extend_translations_management.md@28:[[= include_code('code_samples/translations_management/src/TranslationsManagement/MyCustomProvider.php') =]]
docs/multisite/translations_management/extend_translations_management.md@29:```

001⫶<?php
002⫶
003⫶declare(strict_types=1);
004⫶
005⫶namespace App\TranslationsManagement;
006⫶
007⫶use Ibexa\Contracts\TranslationsManagement\AutoTranslate\Provider\TranslationProviderInterface;
008⫶use Ibexa\Contracts\TranslationsManagement\AutoTranslate\TranslationDataInterface;
009⫶
010⫶final readonly class MyCustomProvider implements TranslationProviderInterface
011⫶{
012⫶ /**
013⫶ * Replace MyApiClient with your HTTP client, SDK wrapper, or any service
014⫶ * that communicates with the external translation API.
015⫶ */
016⫶ public function __construct(
017⫶ private MyApiClient $apiClient,
018⫶ ) {
019⫶ }
020⫶
021⫶ public function getIdentifier(): string
022⫶ {
023⫶ return 'my_custom_provider';
024⫶ }
025⫶
026⫶ public function getName(): string
027⫶ {
028⫶ return 'My Translation Service';
029⫶ }
030⫶
031⫶ public function getVendorName(): string
032⫶ {
033⫶ return 'My Company Ltd';
034⫶ }
035⫶
036❇️ public function translate(TranslationDataInterface $translationData): string
037❇️ {
038❇️ return $this->apiClient->translate(
039❇️ $translationData->getText(),
040❇️ $translationData->getSourceLanguage(),
041❇️ $translationData->getTargetLanguage()
042❇️ );
043❇️ }
044❇️
045❇️ /** @return array<string> */
046❇️ public function getSupportedLanguageCodes(): array
047❇️ {
048❇️ return ['eng-GB', 'ger-DE', 'fre-FR'];
049❇️ }
050⫶}

Download colorized diff

@dabrt
dabrt merged commit 9e9d421 into release_5.0.10 Aug 20, 2026
7 of 11 checks passed
@dabrt
dabrt deleted the translations-management branch August 20, 2026 12:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants