I've setup a localized site (de/en) with custom routing for my categories (which are marked as translatable). I use a tag route for my categories which points to the same template as my structure. Everything seemed to work fine but then I realized that the custom filter (via relatedTo) also outputs entries that don't belong to the current category locale.

To make it clear I'll try to give a rough schemata of my setup (using Craft Pro 2.3.2640):

section projects:

has the entry url format:
  de -> projekte/{slug}    
  en -> projects/{slug}
entry template path:

single projectsIndex:

has the entry url format:
  de -> projekte  
  en -> projects
entry template path:


de -> projekte/(tag)
  template path: projects/index
en -> projects/(tag)
  template path: projects/index


doesn't have a it's own url
category field is marked as translatable

category entries (german version and the english translation):

 - de -> kultur      en -> culture    | (resp. title and slug)
 - de -> industrie   en -> industry   | (resp. title and slug)

project entries:

 - Entry A:
     de -> category relations ['industrie', 'kultur']
     en -> category relations ['industry']
 - Entry B:
     de -> category relations ['kultur']
     en -> category relations ['culture']

template projects/index.html:

{% set _filter = tag|default(null) %}
{% set _category = craft.categories.slug(_filter) %}
{% for entry in craft.entries.section('projects').relatedTo(_category) %}

urls (here comes the trouble):

 - /projekte
     -> lists german version of 'Entry A' and 'Entry B'  (expected)
 - /en/projects
     -> lists english version of 'Entry A' and 'Entry B' (expected)

 - /projekte/kultur
     -> lists german version of 'Entry A' and 'Entry B'  (expected)
 - /en/projects/culture
     -> lists english version of 'Entry A' (NOT expected) and 'Entry B'

...'Entry A' on '/en/projects/culture' shouldn't show up just because there's the 'kultur' category attached to the german version of this entry!

I already tried to explicitly restrict the '_category' by using the '.locale' method but that didn't help either. Now I wonder if I'm doing something fundamentally wrong or if this is a bug by craft itself.

Any tips are appreciated.


Update: Answering my own question here.

2 Answers 2


To answer my own question see below:

As carlcs pointed out correctly the problem actually isn't located in getting the category - which works just well and is the right way to do it - but in how the relation to the entries is done.

  1. I should check if the tag (coming from the url) actually resolves to a "real" category, otherwise just all entries will be shown.
  2. just handling over the category to the .relatedTo method on craft.entries won't do it because that just fetches all entries related to this category irrespective to its locale - sourceLocale: craft.locale needs to be set.
  3. Still not finished; because we want to "find elements related to the given element, where the given element is the target of the relation" – target in this sense is the category – we need to define it as tagetElement in the relatedTo method.


Getting the entries should now look like this:

{% if categories|length %}
    {% set entries = 
                 targetElement: categories,
                 sourceLocale: craft.locale
    {% for entry in entries %}
    {% endfor %}
{% endif %}


And the actual title of my question should be "How to do category relations with locales" ;)

  • Nice catch with that sourceLocale parameter! Setting targetElement is probably not necessary, element should do it if there's no other relations between these elements.
    – carlcs
    Commented Apr 1, 2015 at 13:32

An elements slug property is saved per locale, so you shouldn't get categories with a slug "culture" in your german locale. The locale property is set to your current locale by default, so there's no need to set that explicitly.

I just did a simple test to see if there's no exception to category ElementCriteriaModels.

{% set categories = craft.categories.slug('alkoholfrei') %}
{{ categories|length ? categories.first().title }}

And I can confirm it works as expected, a category with a translated german slug of "alkoholfrei" is not returned in other locales.

I would recommend to double check your category slugs, you probably only translated the title and your slug is not yet updated.

But the actual problem with your code is not how you get the categories, but how you're dealing with them in the craft.entries ElementCriteriaModel. You should check if there's actually categories found, because otherwise your relatedTo param doesn't do anything and you simple get all your "project" entries returned.

{% if categories|length %}
    {% set entries = craft.entries.section('projects').relatedTo(categories) %}
    {% for entry in entries %}
    {% endfor %}
{% endif %}
  • I just double checked - the slug's are translated for sure. Outputting the categories slug (and title); on the english page I get culture and on the german page I get kultur. Getting the right category doesn't seem the problem ... It looks more like the issues is with the relatedTo method not distinguishing between the locales of the category?!
    – m9dfukc
    Commented Apr 1, 2015 at 12:14
  • Ahhh, now I think I know where the mistake is, will edit the answer...
    – carlcs
    Commented Apr 1, 2015 at 12:36
  • I've oversimplified the code to be more clear ... actually I do check if there where categories found. Anyway ... I think I found the answer, which has to do setting targetElement and locale explicitly in relatedTo. ... I'll submit a separate answer.
    – m9dfukc
    Commented Apr 1, 2015 at 12:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.