I know that it’s possible to switch the WP locale by using URL paramaters, as described here, but I’m trying to build a method that would entirely rely on a custom “Language” taxonomy.
What I currently have is a simple plugin, that registers the language taxonomy and implements a locale switch if the taxonomy is present:
<?php
add_action( 'plugins_loaded', 'wpsx_register_taxonomies' );
function wpsx_register_taxonomies() {
register_taxonomy('wpsx_language', array (
0 => 'post',
1 => 'page',
), array(
'hierarchical' => true,
'label' => 'Languages',
'singular_label' => 'Language',
'show_ui' => true,
'rewrite' => false,
)
);
}
function wpsx_redefine_locale($locale) {
global $post;
if ( taxonomy_exists( 'wpsx_language' )) {
$locale = 'de_DE'; // this does work !!
if ( has_term( 'fr', 'wpsx_language' )) {
$locale = 'fr_FR'; // this does not work yet :(
}
}
return $locale;
}
add_filter('locale','wpsx_redefine_locale',10);
?>
So the little part that isn’t working is the has_term()
test. My impression is that the locale filter is running at an early step in the loading sequence, when the post content isn’t retrieved yet, and therefore conditional tests like is_single()
or has_term()
won’t return anything.
Can I force the post content to load earlier? Can I delay the locale filter?
I’m unable to figure out a solution for this. On the wp-hackers mailing list, a suggestion was to run global $post;
but this didn’t help.
Update: following the suggestion by david.binda, I found a workaround, dropping the taxonomy, and using the post slug as a trigger:
function wpsx89972_redefine_locale($locale) {
$wpsx_url = $_SERVER['REQUEST_URI'];
$wpsx_url_lang = substr($wpsx_url, -4); // test for the last 4 chars:
if ( $wpsx_url_lang == "-fr/") {
$locale = 'fr_FR';
} else if ( $wpsx_url_lang == "-en/") {
$locale = 'en_US';
} else { // fallback to default
$locale = 'de_DE';
}
return $locale;
}
add_filter('locale','wpsx89972_redefine_locale',10);
This requires the user to rewrite the post slugs, such as “my-post-title-fr” for French, “my-post-title-en” for English, etc. A bit less user-friendly than using language tickboxes, but it keeps the code simple and just works.
So now I have a functional multi-language plugin, in only 13 lines of code 🙂
Still, I will leave this question open for a couple days, to see if anyone comes up with a solution that would make use of the taxonomy…
You might be interested in url_to_postid function
Used as follows from your wpsx_redefine_locale function:
Note that this does not return the post id for custom post types but the function is located in /wp-includes/rewrite.php and might be extended if needed.
UPDATE: here’s your sample:
What have to be done further, but that’s up to you. You have to sanitize the situation when user changed language taxonomy term assigned to post, so you don’t get
my-post_de_en
instead ofmy-post_en
on post which was before in de and hadmy-post_de
slug. This would require some regular expressions stuff, but you’ll manage that 😉Here is a better solution that will not change anything in your post, but will only add a meta
For more details check my answer (on my own question) here: Set language per post
And I have a plugin that makes everything for you (link is in my answer also)