Related Content Dimensions

Hey there.

I’m strugling with content dimensions that aren’t completely distinct.

The obvious example for different content dimensions is language and country.
The obvious example for fallback of content dimensions is language.

Both examples are not only obvious but actually part of the official documentation:
http://neos.readthedocs.org/en/2.0/CreatingASite/ContentDimensions.html

But as soon as languages with fallback on one side should go together with countries on the other side, those aren’t really distinct dimensions any longer.

Here’s a quick example.

  • Germany should use german only.
  • France should use french only.
  • Switzerland should use both, german and frech.
  • If no german node for Switzerland is available, the german node for Germany should be used.
  • If no french node for Switzerland is available, the french node for France should be used.

That’s actually not a language fallback but a country fallback. But the country to fall back to depends on the selected language.

This kind of configuration is not possible currently. And to be honest, I fear allowing such things renders the dimension configuration way too complex.

So you might end up with something like this, which works with the current feature set:

contentDimensions:
  'locale':
    default: 'de-DE'
    defaultPreset: 'de-DE'
    label: 'Language'
    icon: 'icon-language'
    presets:
      'de-DE':
        label: 'German (Germany)'
        values: ['de-DE']
        uriSegment: 'de-DE'
      'fr-FR':
        label: 'French (France)'
        values: ['fr-FR']
        uriSegment: 'fr-FR'
      'de-CH':
        label: 'German (Switzerland)'
        values: ['de-CH', 'de-DE']
        uriSegment: 'de-CH'
      'fr-CH':
        label: 'French (Switzerland)'
        values: ['fr-CH', 'fr-FR']
        uriSegment: 'fr-CH'

Here the country and language information got lost completely in favor of proper fallback configuration.
But now the drawback is being not able to create language menus or country menus based on dimensions any longer. Plus: A single select field for locales in the Neos backend gets ugly in huge projects.
So although that’s a working solution, it’s kind of an unsatisfying one.

I must confess, I cannot give a nice solution for that. There is an idea, but it requires a lot of configuration for just that simple example.

I thought about “derived dimensions”. On top of the “locale” dimension above, a new dimension “country” (being derived from locale) can be skipped from URI parts and shell not be used for resolving but could be used to ease up backend handling and to create a language menu.

Any comments about this?

Regards,
Stephan.

1 Like

Hey Stephan,

thanks for your thoughts! I have also thought about this topic beforehand; but same as you, do not have a good solution in mind yet. One thing which could make sense though is that we could externalize the “fallback-chain-generation” to a Strategy; so for these advanced use-cases, people could write some PHP code which do the proper fallbacks.

Do you think this would solve your issue?

All the best,
Sebastian

We already have dimension combination constraints, which are AFAIK only applied for editing currently.
I guess it could be an option to check for them also when retrieving nodes which might make this kind of fallback possible.

Since my initial post lacks the configuration of different dimensions for country and language pointing out what exactly seems to conflict currently: Here we go.

The following example requires the “country” dimension to go two different fallback ways, depending on the value of the other dimension “language”.

contentDimensions:
  'country':
    default: 'de'
    defaultPreset: 'de'
    label: 'Language'
    icon: 'icon-language'
    presets:
      'de':
        label: 'Germany'
        values: ['de']
        uriSegment: 'de'
        constraints:
          language:
            'de': true
            'fr': false
      'fr':
        label: 'France'
        values: ['fr']
        uriSegment: 'fr'
        constraints:
          language:
            'de': false
            'fr': true
      'ch':
        label: 'Switzerland'
        # In case the "country:ch, language:de" is asked for but unavailable, "country:de, language:de" is the next best thing.
        values: ['ch', 'de']
        # In case the "country:ch, language:fr" is asked for but unavailable, "country:fr, language:fr" is the next best thing.
        values: ['ch', 'fr']
        uriSegment: 'ch'
        constraints:
          language:
            'de': true
            'fr': true
  'language':
    default: 'de'
    defaultPreset: 'de'
    label: 'Language'
    icon: 'icon-language'
    presets:
      'de':
        label: 'German'
        values: ['de']
        uriSegment: 'de'
        constraints:
          country:
            'de': true
            'fr': false
            'ch': true
      'fr':
        label: 'French'
        values: ['fr']
        uriSegment: 'fr'
        constraints:
          country:
            'de': false
            'fr': true
            'ch': true

And now in direct response to your posts, Sebastian and Christian.

First things first: Thank you for your comments. Having someone to talk to really makes improoving this easier.

Of course it would. As soon as all fallback magic is done in my very own PHP code, the default Neos fallback behavior is irelevant to me. But I don’t think that should be the prefered way to go as soon as one leaves the hello world example of dimensions. And to me it doesn’t make much difference if there’s a fallbackOrderManipulator class configuration in the Settings.yaml or if I’m going to somehow aspect a couple of methods.

Unfortunately, to me that’s the part which doesn’t cover it.

In my opinion, the constraint and fallback situation doesn’t live inside a single dimension. If anything, it lives inside of all dimensions covered by that constraint at the same time. See my previous example, the language/country constraint can be seen both ways. This kind of makes me think having constriants configured “as part of a single dimension” is not the way to go.

As a retrospect to my recent projects, the most likely use case for every dimension/fallback situation comes as either a single list of all combinations or a list of lists of them.

So to me the constraints and fallback part of content dimensions should go on the same level as all individual dimensios go, not nested inside some of them. Which doesn’t necessarily mean the concept of constraints should be dropped at all.

That’s the best thing I could come up with looks like this, it’s basically a complete example of the last sentences of my initial post:

contentDimensions:
  'locale':
    default: 'de-DE'
    defaultPreset: 'de-DE'
    label: 'Language'
    icon: 'icon-language'
    presets:
      'de-DE':
        label: 'German (Germany)'
        values: ['de-DE']
        uriSegment: 'de-DE'
      'fr-FR':
        label: 'French (France)'
        values: ['fr-FR']
        uriSegment: 'fr-FR'
      'de-CH':
        label: 'German (Switzerland)'
        values: ['de-CH', 'de-DE']
        uriSegment: 'de-CH'
      'fr-CH':
        label: 'French (Switzerland)'
        values: ['fr-CH', 'fr-FR']
        uriSegment: 'fr-CH'
  'language':
    derived: true
    basedOn: 'locale'
    presets:
      'de'
        label: 'German'
        contains: ['de-DE', 'de-CH']
      'fr'
        label: 'French'
        contains: ['fr-FR', 'fr-CH']
  'country':
    derived: true
    basedOn: 'locale'
    presets:
      'de'
        label: 'Germany'
        contains: ['de-DE']
      'fr'
        label: 'France'
        contains: ['fr-FR']
      'ch'
        label: 'Switzerland'
        contains: ['de-CH', 'fr-CH']

The very first part is exactly what I used in my initial post. So this completely covers fallbacks orders and all valid combinations of country and language in just one dimension.

The second and third part are “derived” dimensions. They are no real distinct dimensions but only a subset of an existing one. The derived “langauge” dimension names all languages being used in the locale and the individual options of the locale each languave covers. A “derived” dimension is not meant to go into resolving fallbacks, nor is it used as part of the URI part. But derived dimensions can perfectly be used to create menus in both, BE and FE.

You might see: I only added a new subtype of dimensions providing new features, the existing dimensions mechanism is just as it is, plus the very convention: Non-derived dimensions need to be completely orthogonal.

Any thoghts on this one?

Regards,
Stephan.