diff --git a/CHANGELOG.md b/CHANGELOG.md index a49f99fd9b3..cec4b0f1641 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Fixed a bug where newly-selected elements weren’t being rendered correctly for relational fields set to the “Card grid” view mode. ([#18362](https://github.com/craftcms/cms/issues/18362)) - Fixed a bug where card previews weren’t getting updated when a selected field was removed from the field layout. - Fixed potential JavaScript errors that could occur if a disclosure menu’s trigger or target elements were missing. ([#18358](https://github.com/craftcms/cms/issues/18358)) +- Fixed an infinite recursion bug. ([#18363](https://github.com/craftcms/cms/issues/18363)) ## 5.9.5 - 2026-01-31 diff --git a/src/fields/Link.php b/src/fields/Link.php index 79add605d73..7407870b72c 100644 --- a/src/fields/Link.php +++ b/src/fields/Link.php @@ -511,23 +511,35 @@ public function normalizeValue(mixed $value, ?ElementInterface $element): mixed $value instanceof LinkData && $element?->propagating && ($element->propagateAll || ($element->isNewForSite && !isset($element->duplicateOf))) && - isset($element->propagatingFrom) && - $this->getTranslationKey($element) !== $this->getTranslationKey($element->propagatingFrom) + isset($element->propagatingFrom) ) { - $linkedElement = $value->getElement(); - if ($linkedElement && $linkedElement::isLocalized()) { - $localizedQuery = $linkedElement->getLocalized(); - if ( - $localizedQuery instanceof ElementQueryInterface && - $localizedQuery->siteId($element->siteId)->exists() - ) { - $type = $value->getType(); - $value = [ - 'type' => $type, - 'value' => sprintf('{%s:%s@%s:url}', $linkedElement::refHandle(), $linkedElement->id, $element->siteId), - ]; + // in order to avoid infinite loop when using custom translation format with a translation key containing `include()` + // we need to prevent `View::renderObjectTemplate()` from trying to normalize this value again and again + // to do that, we can e.g. set `propagating` to false before getting the translation key + // see https://github.com/craftcms/cms/issues/18363 for more details + if ($this->translationMethod === self::TRANSLATION_METHOD_CUSTOM) { + $element->propagating = false; + } + + if ($this->getTranslationKey($element) !== $this->getTranslationKey($element->propagatingFrom)) { + $linkedElement = $value->getElement(); + if ($linkedElement && $linkedElement::isLocalized()) { + $localizedQuery = $linkedElement->getLocalized(); + if ( + $localizedQuery instanceof ElementQueryInterface && + $localizedQuery->siteId($element->siteId)->exists() + ) { + $type = $value->getType(); + $value = [ + 'type' => $type, + 'value' => sprintf('{%s:%s@%s:url}', $linkedElement::refHandle(), $linkedElement->id, $element->siteId), + ]; + } } } + + // set $propagating back to true + $element->propagating = true; } if ($value instanceof LinkData) {