WordPress Custom Taxonomy url slugs in multiple languages in a multisite setup

Normally, I try and write this blog in German but since I found no solution to this problem that really worked, I’ll put this in English so that it will, hopefully, help more people.

The problem

The initial setup

I recently did a re-design of parts of our company website (which is based on WordPress) where we have several sections that used a special formatting with several nested divs to get the info on the page formatted nicely. The problem, however, was that the html had to be input for every entry on the page – something that only really worked if the person doing the editing was keeping close attention and knew HTML.

For several client projects I had started messing around with Custom Post Types and Custom Taxonomies and outputting the results of those on overview pages as well as individual single-item pages. So I decided to implement the same thing for our website.

The new setup

So I added several custom post types to the functions.php file of WordPress. This is pretty easy to set up if you start with the examples on the Codex page of WordPress. Our website is a WordPress Multisite Setup with two “blogs” for the german and english version of the website that are being tied together with a plugin that adds the correct link to the other language version of a page. All content is the same on both language version.

After some research I also found that the labels for the custom post types can be translated like most other things in WordPress. This was important because I also output some of the labels in the fronted (the name of the post type for example). Since I do not link to the individual single page entries of the custom post types I was not concerned with the urls of those items. So far, so good. For one Custom Post Type, however, I also wanted to add Custom Taxonomies. Custom Taxonomies are like Tags and Categories but allow you to add an infinite amount of such fields to classify the information.

The Custom Post Type got three different taxonomies that act like Tags because I did not need a hierarchy between the terms. As with the custom post types, all labels can be translated. But then I ran into a roadblock: Turns out, the one thing that cannot be translated here is the url slug!

Research & Trial and Error

I started doing research because I felt certain that I was not the first person to run into this problem but there comes the next problem: how do you search for such a complicated scenario? I found some resources, mainly forum posts, but in most cases people were mainly telling the question asker why they were doing this in the first place and that one shouldn’t mess with the url scheme like that (which I would generally agree with but there are certain situation where you have to).

Of course, the easiest option would have been to add a child theme for one language and just change that one part of the theme but I got bullheaded and wanted to solve it this way. After a while I found a solution (Another Option by Christopher Davis) that worked in a single site installation of wordpress (which I was running locally at that point) but did not work for multisite. This seems to be due to the way the multisite handles WPLANG.

At this point I started testing several things and doing more research – and mainly asking some friends who know more about PHP and server setup (because I wasn’t sure if maybe it was a problem with out setup). But no one had a simple solution for me or had the time to had a deeper look at it.

Today I finally had the chance to take a deeper look at it – and got a good clue about how it might work due to a closed ticket for the next WordPress release, 3.4. There someone had reported a problem with setting the RSS language in a multisite setup. There they used get_bloginfo(‘language’) to get the correct value.

The solution

I started by looking at the output I got for




which I simply printed onto the front page of my local installation (which I had changed to a multisite setup, too). Both showed the correct output but for some reason, get_bloginfo(‘language’) puts out the language as de-DE instead of de_DE that WPLAN and get_locale() show. But at least I knew that both versions of the page showed the correct answer. Now I “simply” needed to adapt the code I had gotten from the solution I linked to above to my new filtering. This basically just told wordpress: if the language is set to german, take this term as the input for the slug of the custom taxonomy (which can be anything you want it to be). After some more trial and error (I have no real knowledge of PHP) I came up with the following code that works as expected on my local installation. Tomorrow I’ll test it on our production system.

function service_get_slug() { 
//get the language of the site 
$lang = get_bloginfo('language'); 

//test which language is set and then set the url slug accordingly 
if( $lang === 'de-DE' ) return 'referenzen/leistung'; 
else return 'references/services'; } 

//hook into the init action and call create_book_taxonomies when it fires 
add_action( 'init', 'create_reference_taxonomies', 0 ); 

//connect the slug setup with the taxonomy 
function create_reference_taxonomies() { $slug = service_get_slug(); 

// Add new taxonomy, NOT hierarchical (like tags) 
$labels = array( 
'name' => __( 'Services', 'twentyten' ), '
singular_name' => __( 'Service', 'twentyten' ), 
'search_items' => __( 'Search services' ), 
'popular_items' => __( 'popular services' ), 
'all_items' => __( 'All Services' ), 
'parent_item' => null, 
'parent_item_colon' => null, 
'edit_item' => __( 'Edit Service' ), 
'update_item' => __( 'Update Service' ), 
'add_new_item' => __( 'Add New Service' ), 
'new_item_name' => __( 'New Service Name' ), 
'separate_items_with_commas' => __( 'Separate services with commas' ), 
'add_or_remove_items' => __( 'Add or remove services' ), 
'choose_from_most_used' => __( 'Choose from the most used services' ), 
'menu_name' => __( 'Services' ),

'hierarchical' => false, 
'labels' => $labels, 
'show_ui' => true, 
'update_count_callback' => 
'query_var' => true, 
'rewrite' => 
array('slug' => $slug), 

Remember, after any changes you make to the URL structure, you need to flush the permalinks by visiting the permalink page of the admin area of wordpress.

I hope this helps someone 🙂 and if you have suggestions for making the code easier, let me know 🙂

Be the first to leave a comment. Don’t be shy.

Join the Discussion

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>