Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

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...

share|improve this question
    
You don't have to relly on user's input to post slug. You can keep the taxonomy box on and hook into save_post action and based on term assigned, rewrite the slug: codex.wordpress.org/Function_Reference/… –  david.binda Mar 8 '13 at 16:05
    
Right, maybe I will do that, if I find some good sample code :) –  manu Mar 8 '13 at 19:10
    
See my updated answer below –  david.binda Mar 9 '13 at 12:26

1 Answer 1

up vote 0 down vote accepted

You might be interested in url_to_postid function

Used as follows from your wpsx_redefine_locale function:

$url = $_SERVER['REQUEST_URI'];
$postid = url_to_postid( $url );

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:

function my_function(){
if ( ! wp_is_post_revision( $post_id ) ){

    // unhook this function so it doesn't loop infinitely
    remove_action('save_post', 'my_function');

    // update the post, which calls save_post again
    $my_post_args = array();
    $my_post_args['ID'] = post_id;
    $p = get_post( $post_id );
    $lang_tax = 'my_lang_tax_name';
    $language_terms = get_post_terms( $post_id, $lang_tax );
    $my_post_args['post_name'] = $p->name . '_' . $language_terms[0]->slug;
    wp_update_post( $my_post_args );

    // re-hook this function
    add_action('save_post', 'my_function');
}
add_action('save_posts', 'my_function');

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 of my-post_en on post which was before in de and had my-post_de slug. This would require some regular expressions stuff, but you'll manage that ;)

share|improve this answer
    
Ok, that's interesting. What's the implied reasoning - to retrieve the post ID, then to make a raw database query to check for the taxonomy? Unfortunately, url_to_postid() doesn't work that early in the action chain. If I include it in the locale filter, it generates a "Fatal error: Call to a member function wp_rewrite_rules() on a non-object". If I call it at a later step, it works fine. –  manu Mar 8 '13 at 14:59
    
was worth trying... wp_rewrite is defined later, apparently. I'm afraid I'm out of further ideas. –  david.binda Mar 8 '13 at 15:27
    
After all, your suggestion made me think, and I noticed that the $_SERVER['REQUEST_URI'] part was at least returning the post URL... I guess there's a reason why all existing multilanguage plugins rely on the URL. So I'm now settling for a workaround, using the last part of the URL string to switch the language, like "my-post-title-fr", "my-post-title-en", etc. A compromise, but at least it works and keeps things simple. –  manu Mar 8 '13 at 15:36
    
Oh wow, that's a great code sample! I will build upon that. Thanks a lot. –  manu Mar 14 '13 at 8:26

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.