CHECKING STATUS
I AM LISTENING TO
|

Solutions: WordPress + MultiSite + WPML + Simplied folder structure

LAST MODIFIED: 14. August 2025
4. May 2024
.SHARE

Table of Contents

THE QUESTION

A while back a potential customer asked me, if it is possible to restructure a WordPress Multisite setup and WPML with a more simplified and custom url structure?


THE ROUGH IDEA

1 . BASE.website web.site (with possibly different languages)

web.site/de/
web.site/en/

2. SUB.website web.site/nl-nl/ 

Languages would normally be added like this:

web.site/nl-nl/de/
web.site/nl-nl/en/

The customer wanted it to be restructured / simplified like this:

web.site/de-nl/
web.site/en-nl/

This basically mimics the structure of a single WPML website with custom languages, but with all the benefits of a multisite.

THE SOLUTION

This is nothing that WPML or WordPress Multisite provides out of the box. 
I built a prototype setup to make it work. 

Not something that I would propose for anyone, as it requires a lot of tweaks for anything that handles dynamic links (plugins, hooks, core systems, page.builder …) 

Its doable :)

BASIC URL HANDLING

One thing that needs to be tweaked globally, is the mapping of the new url structure.

So web.site/nl-nl/en/ needs to become web.site/en-nl/

This needs to be handled on the server side, by proxying the original to the new structure.
This can be easily done using Apache or NGINX.

With that web.site/nl-nl/en/ will be proxied to web.site/en-nl/, but any core navigation will not work yet.

This is the fastest solution that I came up with, within the hour I gave myself ;) 

There surely are other options, like the core rewrites / restructuring of the core shorturl handling. But these approaches might break things in far more areas. 

Using the proxy approach, keeps the core as it is. The solution needs to be as simple as possible, allowing to maintain it in the future :)

HOOKS TO THE RESCUE

Just for the basic setup a couple of hooks are required to make this work, more might be needed depending on the plugins in use.

Here a couple of examples ….
WordPress site_url

add_filter( 'site_url', 'custom_site_url' );

function custom_site_url( $url )
{
    if( is_admin() ) // you probably don't want this in admin side
        return $url;

    return  str_replace( "/nl-nl/en/","/en-nl/", $url);
}

WordPress Nav Links

add_filter( 'post_link',  'changePermalinks', 10, 3);
add_filter( 'page_link', 'changePermalinks', 10, 3);
add_filter( 'post_type_link',  'changePermalinks', 10, 3);
add_filter( 'category_link',  'changePermalinks', 11, 3);
add_filter( 'tag_link',  'changePermalinks', 10, 3);
add_filter( 'author_link',  'changePermalinks', 11, 3);
add_filter( 'day_link',  'changePermalinks', 11, 3);
add_filter( 'month_link','changePermalinks', 11, 3);
add_filter( 'year_link',  'changePermalinks', 11, 3);

function changePermalinks( $url, $post, $leavename=false ) {
    $url = str_replace("/nl-nl/en/","/en-nl/", $url);
    return $url;
}

WPML

add_filter( 'icl_ls_languages', 'wpml_url_fix');

function wpml_url_fix( $languages ) {
 
  global $wpml_url_converter;
 
  $abs_home = $wpml_url_converter->get_abs_home();
  foreach( $languages as $lang => $element ){


    $languages[$lang]['url'] = str_replace( "/nl-nl/en/","/en-nl/", $languages[$lang]['url'] );
    
  }
  return $languages;
}



Rankmath

add_filter( 'rank_math/frontend/canonical', function( $canonical ) {
	return str_replace( "/nl-nl/en/","/en-nl/", $canonical);
});

This will not cover every angle, but will give you a starting point! I love my puzzles and there always is a viable solution :)

Need something similar … get in touch!

Happy coding …

Let’s Talk!

Looking for a reliable partner to bring your project to the next level? Whether it’s development, design, security, or ongoing support—I’d love to chat and see how I can help.

Get in touch,
and let’s create something amazing together!

RELATED POSTS

Spend a lot of time with Vikunja (cubicFUSION Vikunja Importer) lately, one thing that it is currently missing is an easy way to style the interface. Especially the task view is just one long page without any clear section separation. LET’S TWEAK IT Here a quick starting point to tweak the style quickly. You can […]

File synchronization is usually treated as a cloud problem. Put the folder in Dropbox, Google Drive, OneDrive, or iCloud, wait for everything to upload, and hope the storage quota, privacy model, transfer speed, and client support all line up with your workflow. That works for office documents. It gets awkward fast when you are syncing […]

An Elementor widget that renders a fully configurable honeycomb grid. Each hexagon cell carries an icon or image, title, text, and a link. The grid supports two orientations, responsive column and size controls, rounded corners, hover effects, hover-reveal modes, per-cell style overrides, a media-gallery source with lightbox, auto-fit columns, background fill, and drop shadows. Content […]

Alexander

I am a full-stack developer. My expertise include:

  • Server, Network and Hosting Environments
  • Data Modeling / Import / Export
  • Business Logic
  • API Layer / Action layer / MVC
  • User Interfaces
  • User Experience
  • Understand what the customer and the business needs


I have a deep passion for programming, design, and server architecture—each of these fuels my creativity, and I wouldn’t feel complete without them.

With a broad range of interests, I’m always exploring new technologies and expanding my knowledge wherever needed. The tech world evolves rapidly, and I love staying ahead by embracing the latest innovations.

Beyond technology, I value peace and surround myself with like-minded individuals.

I firmly believe in the principle: Help others, and help will find its way back to you when you need it.