19

I have been developing a language plugin for wordpress which works completely. The only thing that is missing now is the url-rewriting. I have been looking at a lot of websites, sources and other questions on stackoverflow, but I can't seem to get my permalinks to work.

I have been able to add a query string variable like so:

public function append_query_string($url) 
{
    $args = array('lang' => $this->get_locale());
    return add_query_arg($args, $url);
}
add_filter('page_link', array($this, 'append_query_string'));
add_filter('post_link', array($this, 'append_query_string'));
add_filter('the_permalink', array($this, 'append_query_string'));

This changes my links to http://www.mylink.com?lang=en_us for example. What I want now, is to add a permastruct so that user can have pretty url's (e.g. http://www.mylink.com/en/)

I have added the following piece of code:

public function add_query_var($vars)
{
    $vars['lang'] = $this->get_locale();
    return $vars;
}
add_filter('request' , array($this, 'add_query_var'), 10, 2 );

public function custom_permastruct() 
{
    add_permastruct('language', '%lang%', false);
}
add_action('wp_loaded', array($this, 'custom_permastruct'));

The only thing I need now is a rewrite rule, I presume, but I could be totally wrong. Anyone who knows what the best solution is for adding this permastruct?

EDIT I have been trying to get this working for a month now and I don't seem to be able to get a grasp on permalinks, not even with all the previous answers and my own research. So that's why I'm bumping this post with a bounty yet again. What I need: I have a function (get_locale) that returns a language code. This language code should be implemented in my url as follows: "http://www.mywebsite.com/LANGUAGE_HERE/..."

I know I need to register my own permalink structure for that, but that is where everything goes wrong. What filters do I need and what should I put in my filter functions? Any help is greatly appreciated, because I'm getting pretty desperate here.

EDIT 2

So I added rewrite rules, but they don't seem to work either. I am getting a bit desperate here. Anyway, this is the code for the rewrite rules:

public function add_rewrite_rules()
{   
    $languages = $this->get_all_languages();
    foreach($languages as $language) {
        add_rewrite_rule('^' . $language->code . '/([^/]*)/?$', 'index.php?lang=$matches[1]', 'top');
    }
}
add_action('init', array($this, 'add_rewrite_rules'));
Michiel Standaert
  • 4,096
  • 7
  • 27
  • 49

4 Answers4

6

A properly setup Wordpress 2.0+ will redirect all requests to /index.php so it won't need any htaccess updates, and your registered perma-struct looks fine. I think all that is left is configuring wordpress to use your %lang struct using a custom structure and you should be good to go

Sjon
  • 4,989
  • 6
  • 28
  • 46
3

Try the following code

function custom_rewrite_rules(){
  global $langs; 
   //Array containing locale => pretty permalink key value pair
   /*
    $langs = array (
             'en_us' => 'en',
            )
   */

  foreach($langs as $locale => $lang) {
  add_rewrite_rule(
                   '^'.$lang.'/\/(.*)/?$',
                   'index.php?lang='.$locale,
                   'top'
                   );
  }

}
add_action( 'init', 'custom_rewrite_rules' );
Yash
  • 929
  • 9
  • 25
3

I've had problems with permalink structures too. Sometimes clicking the permalink you want, and save again solves the problem. As WordPress rewrites the htaccess when saving.

Jeroen Bellemans
  • 2,049
  • 2
  • 25
  • 42
1

Well well well, here's a block of code that achieves what you are asking for.

public function init(){

    $permalink_structure = get_option( 'permalink_structure' );

    if( $permalink_structure != '' ){

        global $wp_rewrite;

        $lang = '/' . get_locale();

        if ( ! got_url_rewrite() )
            $prefix = '/index.php';

        if ( is_multisite() && !is_subdomain_install() && is_main_site() )
            $blog_prefix = '/blog';


        if ( ! empty( $permalink_structure ) ) {

            $permalink_structure = preg_replace( 
                '#/+#',
                '/',
                '/' . str_replace( '#', '', $permalink_structure )
            );

            if ( $prefix && $blog_prefix )
                $permalink_structure = $prefix . preg_replace( 
                    '#^/?index\.php#',
                    '',
                    $permalink_structure
                );
            else
                $permalink_structure = $blog_prefix . $permalink_structure;
        }


        if( substr( $permalink_structure, 0, strlen($lang) ) !== $lang ){
            $permalink_structure = $lang . $permalink_structure;
        }

        $wp_rewrite->set_permalink_structure( $permalink_structure );

    }          
}

Notes:

1) Make sure you are using the init( you can give the function any name ) function within the init hook.

2) In the wp-admin folder look for options-permalink.php. Starting at line 75 you will see some interesting codes that form the basis of this answer.

3) you might also want to read this article on the codex

The above code does not require a user to manually select a permalink structure. Any permalink structure used will be prepended with the locale.

MMK
  • 609
  • 5
  • 16
  • I am going to check this tonight! ;) – Michiel Standaert Sep 11 '15 at 08:25
  • This code doesn't seem to do the trick, because every time I change the language, my permalink just adds the current language to its structure (like so: /nl_NL/pl_PL/en_US/%postname%) – Michiel Standaert Sep 12 '15 at 09:15
  • Hmmm, What you can do is to check against a predefined list of locales and if that locale exists in the `$permalink_structure` then remove it and add the new locale. That would be pure PHP. A second option, since you are dealing with WordPress, would be to store an option in the database which would hold the previously set locale. Each time you change the language your plugin would check if that old locale exists in the `$permalink_structure`. If it does then remove it. If you opt for the 2nd option then your code should be placed before `$permalink_structure = $lang . $permalink_structure` – MMK Sep 13 '15 at 22:24