To be able to translate configuration, the Drupal configuration translation system requires config to have a so-called "property path" pointing to the specific values being translated.
To make Canvas component trees stored in config entities symmetrically translatable, we then need to be able to point to specific inputs in specific component instances in the component tree.
For now: internal change, do not start using config translation yet!
⚠️ We first want to achieve both content and config translation before we start explicitly supporting this.
Update path
An automatic update path is provided for all Canvas config entity types that can store component trees (ContentTemplate, PageRegion, Pattern), as well as for the default value of a configurable field (FieldConfig) using the Canvas field type.
Change #1: no more JSON blobs (#3586342)
- Before
- The
inputsfor a component instance in a component tree are stored as a JSON blob:component_tree: - uuid: fd141b6e-c57a-4355-9885-a8b2e60627d6 component_id: sdc.canvas_test_sdc.heading component_version: 8c01a2bdb897a810 inputs: '{"text":"Hello there","style":"primary","element":"h1"}'This makes it impossible to target specifically the
textinput.This was due to the use of
type: ignorein the config schema.
- After
-
component_tree: - uuid: fd141b6e-c57a-4355-9885-a8b2e60627d6 component_id: sdc.canvas_test_sdc.heading component_version: 8c01a2bdb897a810 inputs: text: Hello there style: primary element: h1Now it is possible to specify a "property path" (
component_tree.0.inputs.text) to store the translation, which would store the following for thenltranslation:component_tree: - inputs: text: Hoi daar💡 It's this property path that is used by the Config translation system to override only the translated values.
Change #2: unique sequence keys (#3582464)
The above made it possible to reliably store a symmetrical translation for a specific input. But as soon as the component instance would've been moved, it'd break.
For example: the above default (English) translation contains a single component instance. If a new component instance was added before it, then the translation would continue to target component_tree.0.inputs.text, but in reality it should be targeting component_tree.1.inputs.text now. This is a common pitfall in the design of Drupal configuration entities (even in core, e.g. #3382464: [Style] CKEditor 5 styles config storage is not compatible with config ovverides).
- Before
- Zero-indexed sequence keys that are not reliable to target for Config Translation:
component_tree: 0: uuid: fd141b6e-c57a-4355-9885-a8b2e60627d6 component_id: sdc.canvas_test_sdc.heading component_version: 8c01a2bdb897a810 inputs: text: Hello there style: primary element: h1its translation:
component_tree: 0: inputs: text: Hoi daarThis makes it impossible to reliably target specifically this component instance: what if another component instance is inserted before that? Then the translation would end up targeting the new instance at sequence key zero!
(Actually … it was more complex. The root-level component instances were 0…n, but for instances in slots you'd have gotten sequence keys like
0:the_body:1for the 2nd instance in the "the body" slot of the first root-level instance. But the same analysis applies: position alone is not a reliable target for config translation!)
- After
-
component_tree: fd141b6e-c57a-4355-9885-a8b2e60627d6: uuid: fd141b6e-c57a-4355-9885-a8b2e60627d6 component_id: sdc.canvas_test_sdc.heading component_version: 8c01a2bdb897a810 inputs: text: Hello there style: primary element: h1its translation:
component_tree: fd141b6e-c57a-4355-9885-a8b2e60627d6: inputs: text: Hoi daar
To ensure good config management DX, Canvas provides config import/export transformations (see \Drupal\canvas\EventSubscriber\ComponentTreeConfigEntityTransformer::export()) that encode position information to keep config diffs clear:
component_tree:
0:fd141b6e-c57a-4355-9885-a8b2e60627d6:
uuid: fd141b6e-c57a-4355-9885-a8b2e60627d6
component_id: sdc.canvas_test_sdc.heading
component_version: 8c01a2bdb897a810
inputs:
text: Hello there
style: primary
element: h1
# or for the second component instance in the "the body" slot of the not-pictured 5th root-level component instance:
4:the_body:1:19c5e30f-069a-46c7-b512-7b70f4d1a8e7
uuid: 19c5e30f-069a-46c7-b512-7b70f4d1a8e7
component_id: sdc.canvas_test_sdc.heading
component_version: 8c01a2bdb897a810
inputs:
text: 👋 Hello there from somewhere deep in the component tree
style: primary
element: h1
👆 Note the position information is encoded in each sequence key; the actual sequence key is encoded after the last :, everything before it is to ensure sane config diffs.
Recipe maintainers
It is recommended to apply the update path and re-export your recipe's config, if it includes one of the aforementioned Canvas config entity types.