Content Dimensions

a generic concept of multiple 'node variants'

Neos <=8.x content

This is content for Neos <= 8.x releases.

This content is obsolete with Neos 9.0 and the event sourced Content Repository.

Content Dimensions are a generalization of the multi-language features of Neos, that's why you should read the previous page about Multiple Languages first.

#Generalizing Multilanguage

When planning multi-language support, we soon discovered that the same principles which apply to localization could also apply to other contexts like separation by customer segment or separation by country. Thus, instead of only implementing multi-language, we implemented a generalized concept which we call Content Dimensions. We call things like language, customer segment, or country a dimension.

The Content Repository allows an arbitrary number of dimensions. This enables a single-tree approach for localization, personalization or other variations of the content in a site, where the different Node Variants are still connected with each other.

To understand the task of multiple dimensions, let's look at the combination of language and target audience, which is a problem of 2 combined dimensions:

Content Dimensions

 

Let's imagine the following:

  • Most of the text is written in German, targeting individuals.
  • We start creating some more content in English and French, but if content is not available in French, we want to fall back to English content. This is explained in the Multiple Languages chapter.
  • Additionally, there exists a second dimension audience (private or sommelier), displayed on the x-axis of the diagram.

If content is rendered and thus fetched from the content repository, it will always happen in a context. This context contains a list of values for each dimension that specifies which dimension values are visible and in which fallback order these should apply. So the same node variants can yield different results depending on the context that is used to fetch the nodes.

#Configuring Multiple Dimensions

Defining multiple dimensions works pretty much like defining a single dimension - you just add multiple blocks inside Neos.ContentRepository.contentDimensions:

Configuration/Settings.yaml
Neos:
  ContentRepository:
    contentDimensions:
      language:
        label: 'Language'
        default: en_US    
        defaultPreset: en 
        presets:
          en:       
            label: 'English (US)'
            values: 
              - en_US
            uriSegment: ''
          de:            
            label: German
            values:
              - de
            uriSegment: de
      targetGroup:
        label: 'Audience'
        default: private
        defaultPreset: private
        presets:
          private:       
            label: 'Private'
            values: 
              - private
            uriSegment: ''
          sommelier:            
            label: Sommeliers
            values:
              - sommelier
            uriSegment: sommelier

Don't forget to run the Node Migration

As explained in Multiple Languages, do not forget to run the following node migration after adding or removing dimensions:
./flow node:migrate 20150716212459

#Presets and Constraints

The allowed combinations of content dimension presets can be controlled via the preset constraints feature, as there are often combinations which do not make sense and are not desirable.

A typical use case is to define separate dimensions for language and country:

Consider a website which has dedicated content for the US, Germany and France. The content for each country is available in English and their respective local language. The following configuration would make sure that the combinations “German – US”, “German - France”, “French - US” and “French - Germany” are not allowed:

yaml
Neos:
  ContentRepository:
    contentDimensions:
      'language':
        default: 'en'
        defaultPreset: 'en'
        label: 'Language'
        icon: 'icon-language'
        presets:
          'en':
            label: 'English'
            values: ['en']
            uriSegment: 'en'
          'de':
            label: 'German'
            values: ['de']
            uriSegment: 'de'
            constraints:
              country:
                'us': false
                'fr': false
          'fr':
            label: 'French'
            values: ['fr']
            uriSegment: 'fr'
            constraints:
              country:
                'us': false
                'de': false
      'country':
        default: 'us'
        defaultPreset: 'us'
        label: 'Country'
        icon: 'icon-globe'
        presets:
          'us':
            label: 'United States'
            values: ['us']
            uriSegment: 'us'
          'de':
            label: 'Germany'
            values: ['de']
            uriSegment: 'de'
          'fr':
            label: 'France'
            values: ['fr']
            uriSegment: 'fr'

Instead of configuring every constraint preset explicitly, it is also possible to allow or disallow all presets of a given dimension by using the wildcard identifier. The following configuration has the same effect like in the previous example:

yaml
Neos:
  ContentRepository:
    contentDimensions:
      'language':
        default: 'en'
        defaultPreset: 'en'
        label: 'Language'
        icon: 'icon-language'
        presets:
          'en':
            label: 'English'
            values: ['en']
            uriSegment: 'en'
          'de':
            label: 'German'
            values: ['de']
            uriSegment: 'de'
            constraints:
              country:
                'de': true
                '*': false
          'fr':
            label: 'French'
            values: ['fr']
            uriSegment: 'fr'
            constraints:
              country:
                'fr': true
                '*': false
      'country':
        default: 'us'
        defaultPreset: 'us'
        label: 'Country'
        icon: 'icon-globe'
        presets:
          'us':
            label: 'United States'
            values: ['us']
            uriSegment: 'us'
          'de':
            label: 'Germany'
            values: ['de']
            uriSegment: 'de'
          'fr':
            label: 'France'
            values: ['fr']
            uriSegment: 'fr'

While the examples only defined constraints in the language dimension configuration, it is perfectly possible to additionally or exclusively define constraints in country or other dimensions.

#Behind the Scenes: Routing

Neos provides a route-part handler that will include a prefix with the value of the uriSegment setting of a dimension preset for all configured dimensions. This means URIs will not contain any prefix by default as long as no content dimension is configured. Multiple dimensions are joined with a _ character, so the uriSegment value must not include an underscore.

The default preset can have an empty uriSegment value. The following example will lead to URLs that do not contain en if the en_US preset is active, but will show the uriSegment for other languages that are defined as well:

Configuration/Settings.yaml
Neos:
  ContentRepository:
    contentDimensions:

      'language':
        default: 'en'
        defaultPreset: 'en_US'
        label: 'Language'
        icon: 'icon-language'
        presets:
          'en':
            label: 'English (US)'
            values: ['en_US']
            uriSegment: ''

The only limitation is that all segments must be unique across all dimensions. If you need non-unique segments, you can switch support for non-empty dimensions off:

Configuration/Settings.yaml
Neos:
  Neos:
    routing:
      supportEmptySegmentForDimensions: false