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?