From 23cb541b01949960112a9961f6c8f15fae0e6f19 Mon Sep 17 00:00:00 2001 From: Erique Souza <102301295+erique-souza@users.noreply.github.com> Date: Mon, 24 Aug 2026 21:07:11 -0300 Subject: [PATCH 1/4] Update QuestionTypeItem.php fix(form): use dropdown translation in generated ticket content --- src/Glpi/Form/QuestionType/QuestionTypeItem.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Glpi/Form/QuestionType/QuestionTypeItem.php b/src/Glpi/Form/QuestionType/QuestionTypeItem.php index daf5d3835e2..9f33e48e02f 100644 --- a/src/Glpi/Form/QuestionType/QuestionTypeItem.php +++ b/src/Glpi/Form/QuestionType/QuestionTypeItem.php @@ -43,6 +43,7 @@ use Datacenter; use DbUtils; use Dropdown; +use DropdownTranslation; use Glpi\Application\View\TemplateRenderer; use Glpi\DBAL\JsonFieldInterface; use Glpi\Form\Category; @@ -412,9 +413,17 @@ public function formatRawAnswer(mixed $answer, Question $question): string return $item->getFriendlyName(); } - $name = $item instanceof CommonTreeDropdown - ? $item->fields['completename'] - : $item->getFriendlyName(); + $field = $item instanceof CommonTreeDropdown ? 'completename' : 'name'; + $name = $item->fields[$field]; + + // GLPI issue #25249: apply the dropdown translation so the generated + // ticket content and title follow the requester language. + $name = DropdownTranslation::getTranslatedValue( + $item->getID(), + $item::class, + $field, + value: $name + ); // Append additional fields to match what is displayed in renderEndUserTemplate. $itemtype = $answer['itemtype']; From b279c632c1f76659b4e2e08cee7813e3ef395a00 Mon Sep 17 00:00:00 2001 From: Erique Souza <102301295+erique-souza@users.noreply.github.com> Date: Mon, 24 Aug 2026 21:12:40 -0300 Subject: [PATCH 2/4] Update QuestionTypeItemTest.php test(form): cover dropdown translation in formatRawAnswer --- .../QuestionType/QuestionTypeItemTest.php | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/tests/functional/Glpi/Form/QuestionType/QuestionTypeItemTest.php b/tests/functional/Glpi/Form/QuestionType/QuestionTypeItemTest.php index c7b0d3a3a1c..06ef6029526 100644 --- a/tests/functional/Glpi/Form/QuestionType/QuestionTypeItemTest.php +++ b/tests/functional/Glpi/Form/QuestionType/QuestionTypeItemTest.php @@ -36,6 +36,7 @@ use Computer; use Contact; +use DropdownTranslation; use Glpi\Form\Question; use Glpi\Form\QuestionType\QuestionTypeItem; use Glpi\Form\QuestionType\QuestionTypeItemDefaultValueConfig; @@ -453,4 +454,55 @@ public function testFormatRawAnswer(callable $setup): void $this->assertEquals($case['expected'], $result); } + + /** + * Non-regression test for #25249. + * + * The generated ticket content is frozen at submission time, so the item + * name has to be resolved in the requester language at that moment. Before + * the fix, formatRawAnswer() read the raw completename column and the + * answer was stored in the source language whatever the requester used. + */ + public function testFormatRawAnswerUsesDropdownTranslation(): void + { + $this->login(); + + $parent = $this->createItem(Location::class, [ + 'name' => 'Head office', + 'entities_id' => $this->getTestRootEntity(true), + ]); + $child = $this->createItem(Location::class, [ + 'name' => 'Meeting room', + 'locations_id' => $parent->getID(), + 'entities_id' => $this->getTestRootEntity(true), + ]); + + $this->createItem(DropdownTranslation::class, [ + 'items_id' => $child->getID(), + 'itemtype' => Location::class, + 'language' => 'fr_FR', + 'field' => 'completename', + 'value' => 'Siège social > Salle de réunion', + ]); + + // The translation cache is built at login, so the user must be logged + // in after the translation exists. + $this->createItem(User::class, [ + 'name' => 'fr_FR', + 'language' => 'fr_FR', + '_entities_id' => $this->getTestRootEntity(true), + '_profiles_id' => 1, + ]); + $this->login('fr_FR'); + + $result = (new QuestionTypeItem())->formatRawAnswer( + [ + 'itemtype' => Location::class, + 'items_id' => $child->getID(), + ], + new Question() + ); + + $this->assertEquals('Siège social > Salle de réunion', $result); + } } From 2de342909aeb87b68c8b89e3147a7916badd0240 Mon Sep 17 00:00:00 2001 From: Erique Souza <102301295+erique-souza@users.noreply.github.com> Date: Mon, 24 Aug 2026 21:18:13 -0300 Subject: [PATCH 3/4] Update QuestionTypeItem.php fix(form): keep getFriendlyName for non-dropdown items --- .../Form/QuestionType/QuestionTypeItem.php | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/Glpi/Form/QuestionType/QuestionTypeItem.php b/src/Glpi/Form/QuestionType/QuestionTypeItem.php index 9f33e48e02f..9be0819ae33 100644 --- a/src/Glpi/Form/QuestionType/QuestionTypeItem.php +++ b/src/Glpi/Form/QuestionType/QuestionTypeItem.php @@ -38,6 +38,7 @@ use CartridgeItem; use Cluster; use CommonDBTM; +use CommonDropdown; use CommonTreeDropdown; use ConsumableItem; use Datacenter; @@ -413,17 +414,21 @@ public function formatRawAnswer(mixed $answer, Question $question): string return $item->getFriendlyName(); } - $field = $item instanceof CommonTreeDropdown ? 'completename' : 'name'; - $name = $item->fields[$field]; + $name = $item instanceof CommonTreeDropdown + ? $item->fields['completename'] + : $item->getFriendlyName(); - // GLPI issue #25249: apply the dropdown translation so the generated - // ticket content and title follow the requester language. - $name = DropdownTranslation::getTranslatedValue( - $item->getID(), - $item::class, - $field, - value: $name - ); + // The ticket content is frozen at submission time, so the value must be + // resolved in the requester language here. Conditions are deliberately + // left untranslated: they must compare against the source value. + if ($item instanceof CommonDropdown) { + $name = DropdownTranslation::getTranslatedValue( + $item->getID(), + $item::class, + $item instanceof CommonTreeDropdown ? 'completename' : 'name', + value: $name + ); + } // Append additional fields to match what is displayed in renderEndUserTemplate. $itemtype = $answer['itemtype']; From 25fa98504cddf4c734b59e21f24d1f1cf551774b Mon Sep 17 00:00:00 2001 From: Erique Souza <102301295+erique-souza@users.noreply.github.com> Date: Tue, 25 Aug 2026 10:22:28 -0300 Subject: [PATCH 4/4] Update QuestionTypeItemTest.php test(form): translate name field and let GLPI derive completename --- .../Form/QuestionType/QuestionTypeItemTest.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/functional/Glpi/Form/QuestionType/QuestionTypeItemTest.php b/tests/functional/Glpi/Form/QuestionType/QuestionTypeItemTest.php index 06ef6029526..e4991875eab 100644 --- a/tests/functional/Glpi/Form/QuestionType/QuestionTypeItemTest.php +++ b/tests/functional/Glpi/Form/QuestionType/QuestionTypeItemTest.php @@ -477,16 +477,26 @@ public function testFormatRawAnswerUsesDropdownTranslation(): void 'entities_id' => $this->getTestRootEntity(true), ]); + // Only `name` is translated on purpose: GLPI derives the `completename` + // translation from the ancestors' translated names, and overwrites any + // `completename` row that is written directly. + $this->createItem(DropdownTranslation::class, [ + 'items_id' => $parent->getID(), + 'itemtype' => Location::class, + 'language' => 'fr_FR', + 'field' => 'name', + 'value' => 'Siège social', + ]); $this->createItem(DropdownTranslation::class, [ 'items_id' => $child->getID(), 'itemtype' => Location::class, 'language' => 'fr_FR', - 'field' => 'completename', - 'value' => 'Siège social > Salle de réunion', + 'field' => 'name', + 'value' => 'Salle de réunion', ]); // The translation cache is built at login, so the user must be logged - // in after the translation exists. + // in after the translations exist. $this->createItem(User::class, [ 'name' => 'fr_FR', 'language' => 'fr_FR',