Problem/Motivation

Rich text content is not processed using the language context and so links (via linkit module) or embedded media are not the correct language.

Steps to reproduce

1. Have a multilingual site setup using content translation.
2. Create a config page, with a rich text field and language context enabled.
3. Add a block for the config page to a page.
3. Add values for the config page in both languages with a link to a node that's translated.
4. Visit the page in both languages - both will link to the default language version of the node, and when visiting in the non-default language will lead to a 404.

Proposed resolution

Not sure on a resolution, the processed text filters pass in the language of the field being rendered, which as config pages aren't translatable, this is set to und. The linkit and drupal media filters both use the language code passed in to load the right target entity.

Remaining tasks

Figure out a solution.

User interface changes

N/A

API changes

N/A

Data model changes

N/A?

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mjpa created an issue. See original summary.

mjpa’s picture

Status: Active » Needs review

I've created a MR with a potential fix that seems to work in our case. The preprocess field changes the #langcode property on the render arrays where it's set to the value from the language context of the config page that the field belongs to.

With the MR applied, links to translated content now link to the language version that matches the language context from the config page, instead of the default language of the site.

yoerioptr’s picture

I've attached MR as a patch to this ticket.

shumer made their first commit to this issue’s fork.

shumer’s picture

Assigned: Unassigned » shumer

After reviewing the original patch (MR !43) that uses hook_preprocess_field(), we decided to switch to a custom EntityViewBuilder for the following reasons:

Why the approach changed:

1. Render cache compatibility. hook_preprocess_field() runs after the render cache layer. This means on a cache hit the hook never fires, so #langcode isn't set until the cache is rebuilt. EntityViewBuilder::buildComponents() runs before caching, so
the langcode is baked into the cached render array.
2. Covers all rendering paths. Config page fields can be rendered in two ways:
- Entity-level: via EntityViewBuilder::view() → buildComponents() (e.g. block plugin, direct entity rendering).
- Field-level: via FieldItemList::view() → EntityViewBuilder::viewField() (e.g. ConfigPagesLoaderService::getFieldView(), Twig config_pages_field() function).

The preprocess hook only covers the first path. The custom ViewBuilder covers both by overriding buildComponents() and viewField().
3. Idiomatic Drupal pattern. Overriding the view builder is the standard way to customize entity rendering behavior, rather than relying on theme-layer hooks for logic that is entity-specific.

What was done:

  1. - Created ConfigPagesViewBuilder extending EntityViewBuilder:
  2. - buildComponents(): after parent call, extracts language from the entity's serialized context and sets #langcode on all field items.
  3. - viewField(): same logic for the field-level rendering path.
  4. - Helper methods: extractLanguageFromContext() and applyLangcodeToFieldItems().
  5. - Updated ConfigPages entity annotation to use the new view builder handler.
  6. - Removed config_pages_preprocess_field() from config_pages.module.
  7. - Added ConfigPagesViewBuilderTest (Kernel): 9 tests / 63 assertions covering:
  8. - Entity rendering with real field types (string, text_long, link).
  9. - Field-level rendering via viewField().
  10. - Loader service path via getFieldView().
  11. - Edge cases: no language context, empty context, corrupted context, multiple context items.

  • shumer committed 8b9ce755 on 8.x-2.x authored by mjpa
    Issue #3500828: Add a preprocess_field to set the langcode from the...
shumer’s picture

Status: Needs review » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.