WPML language switcher for custom rewrite rules

I am making custom rewrite rules for categories in a dual-language project (german as main, english as second language). The urls look like this

example.com/fliegen shows archive.php for category fliegen

example.com/en/aviation shows archive.php for category aviation (the translated fliegen)

This could be achieved by changing the category-base to . (although it doesn't seem to work in my case?)

Unfortunately that wouldn't be enough for me, anyways; there is a custom taxonomy called filter in the game aswell, which requires urls like this:

example.com/fliegen/filter/some-filter

example.com/en/aviation/filter/some-filter-translated

When the project was still single-language, I went that route:

add_filter(rewrite_rules_array, function($rules) {
    $newRules = array();

    $cats = get_terms(category, array(hide_empty = false));

    foreach ($cats as $id = $cat) {
        $slug = $cat-slug;
        $newRules[$slug . /?$] = index.php?category_name= . $slug;
        $newRules[$slug . /filter/(.+?)/?$] = 'index.php?category_name=' . $slug . 'filter=$matches[1]';
    }

    return $newRules;
});

This code now also includes the translated category-terms, but obviously doesn't care about the needed /en/ in the rewrite-rule; So I now need a way to ask inside the foreach loop what language the current term represents.

Hoooow can I do that?

.

.

PS: If anybody knows where to find proper Docs for all the icl_-php functions, that seem to come with WPML, please let me know!

.

Edit

I found a solution to this myself.

The key is a filter-hook called wpml_element_language_details. But WPML changes core functions like get_terms so one gets only the terms for the current language. This may be very convenient in most cases, creating rewrite rules based on the currently active language in the backend? Not a good idea... therefore you have to temporarily remove the wpml-filters. Which filters to remove? No idea, .. found that online.

add_filter(rewrite_rules_array, function($rules) {
    $newRules = array();

    // remove WPML term filters
    global $sitepress;
    remove_filter('get_term', array($sitepress,'get_term_adjust_id'));
    remove_filter('get_terms_args', array($sitepress, 'get_terms_args_filter'));
    remove_filter('terms_clauses', array($sitepress,'terms_clauses'));
     
    // now get ALL categories of ALL languages,
    $cats = get_terms(category, array(hide_empty = false)); 
     
    // restore WPML term filters
    add_filter('get_term', array($sitepress,'get_term_adjust_id'));
    add_filter('get_terms_args', array($sitepress, 'get_terms_args_filter'));
    add_filter('terms_clauses', array($sitepress,'terms_clauses'));

    // Loop through the $cats
    foreach ($cats as $id = $cat) {

        $details = apply_filters(wpml_element_language_details, null, array(element_id = $cat-term_id, element_type = category));

        $slug = $cat-slug;

        // if necessary, add language prefix
        // not having a source_language_code means this is part of the main language and (in our case) therefore doesn't need a prefix at all
        // (!) this may be different for your WPML installation!
        $lang_prefix = ($details-source_language_code != NULL) 
            ? $details-language_code . /
            : 
        ;

        $newRules[$lang_prefix . $slug . /?$] = index.php?category_name= . $slug;
        $newRules[$lang_prefix . $slug . /filter/(.+?)/?$] = 'index.php?category_name=' . $slug . 'filter=$matches[1]';
    }

.

Language switcher

So far my language switcher looks like this,

$lang_switcher = icl_get_languages(skip_missing=0);

foreach ($lang_switcher as $lang) {
    $activeClass = (($lang[active])) ?  active : ;
    echo '
        a href=' . $lang[url] . ' class='.$activeClass.''. $lang[native_name] .'/a
    ';
}

I have more special cases, like filterable search-page, filterable author-pages.

How can I now link these different custom urls to each other properly?

Topic rewrite-rules url-rewriting plugin-wpml multi-language Wordpress

Category Web


A more simple solution for generating the rewrite rules would be to temporarily disable the WPML plugin. I did this using WP-CLI as follows:

wp plugin deactivate sitepress-multilingual-cms
wp rewrite flush
wp plugin activate sitepress-multilingual-cms

Note that this only works a single time. Each time you add/modify a category, the rewrite list is flushed and only the current language categories show up there. So this is only a solution when your categories do not change, or not often.

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.