PluginProbe
Polylang / 0.3.1
Polylang v0.3.1
3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 3.0.3 All 233 releases
polylang / polylang.php

polylang.php in Polylang 0.3.1, at polylang.php

700 lines 26.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: Polylang
4 Plugin URI: http://wordpress.org/extend/plugins/polylang/
5 Version: 0.3.1
6 Author: F. Demarle
7 Description: Adds multilingual capability to Wordpress
8 */
9
10 /* Copyright 2011 F. Demarle
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License, version 2, as
14 published by the Free Software Foundation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 define('POLYLANG_VERSION', '0.3');
27 define('POLYLANG_DIR', dirname(__FILE__));
28 require_once(POLYLANG_DIR.'/base.php');
29 require_once(POLYLANG_DIR.'/admin.php');
30 require_once(POLYLANG_DIR.'/widget.php');
31
32 class Polylang extends Polylang_Base {
33 var $curlang;
34 var $default_locale;
35 var $list_textdomains = array();
36 var $search_form_filter = false;
37
38 function __construct() {
39
40 // manages plugin activation and deactivation
41 register_activation_hook( __FILE__, array(&$this, 'activate') );
42 register_deactivation_hook( __FILE__, array(&$this, 'deactivate') );
43
44 // plugin and widget initialization
45 add_action('init', array(&$this, 'init'));
46 add_action('widgets_init', array(&$this, 'widgets_init'));
47
48 // rewrite rules
49 add_filter('rewrite_rules_array', array(&$this, 'rewrite_rules_array' ));
50
51 // filters categories and post tags by language
52 add_filter('terms_clauses', array(&$this, 'terms_clauses'), 10, 3);
53
54 if (is_admin())
55 new Polylang_Admin();
56 else {
57 // text domain management
58 add_filter('locale', array(&$this, 'get_locale'));
59 add_filter('override_load_textdomain', array(&$this, 'mofile'), 10, 3);
60 add_action('wp', array(&$this, 'load_textdomains'));
61
62 // filters posts according to the language
63 add_filter('pre_get_posts', array(&$this, 'pre_get_posts'));
64
65 // meta in the html head section
66 remove_action('wp_head', 'rel_canonical');
67 add_action('wp_head', array(&$this, 'wp_head'));
68
69 // prevents redirection of the homepage
70 add_filter('redirect_canonical', array(&$this, 'redirect_canonical'), 10, 2);
71
72 // adds javascript at the end of the document
73 add_action('wp_print_footer_scripts', array(&$this, 'wp_print_footer_scripts'));
74
75 // adds the language information in the search form
76 add_filter('get_search_form', array(&$this, 'get_search_form'));
77
78 // filters the pages according to the current language
79 add_filter('get_pages', array(&$this, 'get_pages'), 10, 2);
80
81 // filters the comments according to the current language
82 add_filter('comments_clauses', array(&$this, 'comments_clauses'));
83
84 // rewrites feed links to filter them by language
85 add_filter('feed_link', array(&$this, 'feed_link'), 10, 2);
86
87 // rewrites archives links to filter them by language
88 add_filter('getarchives_join', array(&$this, 'posts_join'));
89 add_filter('getarchives_where', array(&$this, 'posts_where'));
90 add_filter('get_archives_link', array(&$this, 'get_archives_link'));
91
92 // rewrites next and previous post links to filter them by language
93 add_filter('get_previous_post_join', array(&$this, 'posts_join'));
94 add_filter('get_next_post_join', array(&$this, 'posts_join'));
95 add_filter('get_previous_post_where', array(&$this, 'posts_where'));
96 add_filter('get_next_post_where', array(&$this, 'posts_where'));
97
98 // filters the nav menus according to the current language
99 add_filter('wp_nav_menu_args', array(&$this, 'wp_nav_menu_args'));
100
101 // filters the widgets according to the current language
102 add_filter('widget_display_callback', array(&$this, 'widget_display_callback'), 10, 3);
103
104 // allows a new value for the 'show' parameter to display the homepage url according to the current language
105 add_filter('bloginfo_url', array(&$this, 'bloginfo_url'), 10, 2);
106
107 // Template tags
108 add_action('the_languages', array(&$this, 'the_languages'));
109 }
110 }
111
112 // plugin activation
113 function activate() {
114 // create the termmeta table - not provided by WP by default - if it does not already exists
115 // uses exactly the same model as other meta tables to be able to use access functions provided by WP
116 global $wpdb;
117 $charset_collate = '';
118 if ( ! empty($wpdb->charset) )
119 $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
120 if ( ! empty($wpdb->collate) )
121 $charset_collate .= " COLLATE $wpdb->collate";
122
123 $table = $wpdb->prefix . 'termmeta';
124
125 $tables = $wpdb->get_results("show tables like '$table'");
126 if (!count($tables))
127 $wpdb->query("CREATE TABLE $table (
128 meta_id bigint(20) unsigned NOT NULL auto_increment,
129 term_id bigint(20) unsigned NOT NULL default '0',
130 meta_key varchar(255) default NULL,
131 meta_value longtext,
132 PRIMARY KEY (meta_id),
133 KEY term_id (term_id),
134 KEY meta_key (meta_key)
135 ) $charset_collate;");
136
137 // codex tells to use the init action to call register_taxonomy but I need it now for my rewrite rules
138 register_taxonomy('language', array('post', 'page'), array('label' => false, 'query_var'=>'lang'));
139
140 // defines default values for options in case this is the first installation
141 $options = get_option('polylang');
142 if (!$options) {
143 $options['browser'] = 1; // default language for the front page is set by browser preference
144 $options['rewrite'] = 0; // do not remove /language/ in permalinks
145 }
146 $options['version'] = POLYLANG_VERSION; // do not manage versions yet but prepare for it
147 update_option('polylang', $options);
148
149 // add our rewrite rules
150 global $wp_rewrite;
151 $wp_rewrite->flush_rules();
152 }
153
154 // plugin deactivation
155 function deactivate() {
156 // delete our rewrite rules
157 remove_filter('rewrite_rules_array', array(&$this,'rewrite_rules_array' ));
158 global $wp_rewrite;
159 $wp_rewrite->flush_rules();
160 }
161
162 // some initialization
163 function init() {
164 global $wpdb;
165 $wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
166
167 // registers the language taxonomy
168 // codex: use the init action to call this function
169 register_taxonomy('language', 'post', array(
170 'label' => false,
171 'query_var'=>'lang',
172 'update_count_callback' => '_update_post_term_count'));
173
174 // optionaly removes 'language' in permalinks so that we get http://www.myblog/en/ instead of http://www.myblog/language/en/
175 // the simple line of code is inspired by the WP No Category Base plugin : http://wordpresssupplies.com/wordpress-plugins/no-category-base/
176 $options = get_option('polylang');
177 if ($options['rewrite']) {
178 global $wp_rewrite;
179 $wp_rewrite->extra_permastructs['language'][0] = '%language%';
180 }
181
182 $this->default_locale = get_locale(); // save the default locale before we start any language manipulation
183 load_plugin_textdomain('polylang', false, dirname(plugin_basename( __FILE__ ))); // plugin i18n
184 }
185
186 // registers our widget
187 function widgets_init() {
188 register_widget('Polylang_Widget');
189 }
190
191 // rewrites rules if pretty permalinks are used
192 function rewrite_rules_array($rules) {
193 $options = get_option('polylang');
194 $newrules = array();
195 $listlanguages = $this->get_languages_list();
196
197 // modifies the rules created by WordPress when '/language/' is removed in permalinks
198 if ($options['rewrite']) {
199 foreach ($listlanguages as $language) {
200 $newrules[$language->slug.'/feed/(feed|rdf|rss|rss2|atom)/?$'] = 'index.php?lang='.$language->slug.'&feed=$matches[1]';
201 $newrules[$language->slug.'/(feed|rdf|rss|rss2|atom)/?$'] = 'index.php?lang='.$language->slug.'&feed=$matches[1]';
202 $newrules[$language->slug.'/page/?([0-9]{1,})/?$'] = 'index.php?lang='.$language->slug.'&paged=$matches[1]';
203 $newrules[$language->slug.'/?$'] = 'index.php?lang='.$language->slug;
204 }
205 unset($rules['([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$']); // => index.php?lang=$matches[1]&feed=$matches[2]
206 unset($rules['([^/]+)/(feed|rdf|rss|rss2|atom)/?$']); // => index.php?lang=$matches[1]&feed=$matches[2]
207 unset($rules['([^/]+)/page/?([0-9]{1,})/?$']); // => index.php?lang=$matches[1]&paged=$matches[2]
208 unset($rules['([^/]+)/?$']); // => index.php?lang=$matches[1]
209 }
210
211 $options['rewrite'] ? $base = '' : $base = 'language/';
212
213 // rewrite rules for comments feed filtered by language
214 foreach ($listlanguages as $language) {
215 $newrules[$base.$language->slug.'/comments/feed/(feed|rdf|rss|rss2|atom)/?$'] = 'index.php?lang='.$language->slug.'&feed=$matches[1]&withcomments=1';
216 $newrules[$base.$language->slug.'/comments/(feed|rdf|rss|rss2|atom)/?$'] = 'index.php?lang='.$language->slug.'&feed=$matches[1]&withcomments=1';
217 }
218 unset($rules['comments/feed/(feed|rdf|rss|rss2|atom)/?$']); // => index.php?&feed=$matches[1]&withcomments=1
219 unset($rules['comments/(feed|rdf|rss|rss2|atom)/?$']); // => index.php?&feed=$matches[1]&withcomments=1
220
221 // rewrite rules for archives filtered by language
222 foreach ($rules as $key => $rule) {
223 $is_archive = strpos($rule, 'year=') && !(
224 strpos($rule, 'p=') ||
225 strpos($rule, 'name=') ||
226 strpos($rule, 'page=') ||
227 strpos($rule, 'cpage=') );
228
229 if ($is_archive) {
230 foreach ($listlanguages as $language)
231 $newrules[$base.$language->slug.'/'.$key] = str_replace('?', '?lang='.$language->slug.'&', $rule);
232
233 unset($rules[$key]); // now useless
234 }
235 }
236
237 return $newrules + $rules;
238 }
239
240 // filters categories and post tags by language when needed (both in admin panels and frontend)
241 function terms_clauses($clauses, $taxonomies, $args) {
242 // does nothing except on categories and post tags
243 if ( !in_array('category', $taxonomies) && !in_array('post_tag', $taxonomies) )
244 return $clauses;
245
246 if (is_admin()) {
247 $screen = get_current_screen(); //FIXME breaks a user's admin -> use pagenow instead ? Or simply test the function.
248
249 // NOTE: $screen is not defined in the tag cloud of the Edit Post panel ($pagenow set to admin-ajax.php)
250 if (isset($screen))
251 // does nothing in the Categories, Post tags, Languages an Posts* admin panels
252 if ($screen->base == 'edit-tags' || $screen->base == 'toplevel_page_mlang' || $screen->base == 'edit')
253 return $clauses;
254
255 // *FIXME I want all categories in the dropdown list and only the ones in the right language in the inline edit
256 // It seems that I need javascript to get the post_id as inline edit data are manipulated in inline-edit-post.js
257
258 $this->curlang = $this->get_current_language();
259 }
260
261 // adds our clauses to filter by current language
262 if ($this->curlang) {
263 global $wpdb;
264 $clauses['join'] .= " INNER JOIN $wpdb->termmeta AS tm ON t.term_id = tm.term_id";
265 $clauses['where'] .= $wpdb->prepare(" AND tm.meta_key = '_language' AND tm.meta_value = %d", $this->curlang->term_id);
266 }
267 return $clauses;
268 }
269
270 // returns the language according to browser preference or the default language
271 function get_preferred_language() {
272 // check first is the user was already browsing this site
273 if (isset($_COOKIE['wordpress_polylang']))
274 return $this->get_language($_COOKIE['wordpress_polylang']);
275
276 // sets the browsing language according to the browser preferences
277 // code adapted from http://www.thefutureoftheweb.com/blog/use-accept-language-header
278 $options = get_option('polylang');
279 if ($options['browser']) {
280 $accept_langs = array();
281
282 if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
283 // break up string into pieces (languages and q factors)
284 preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $lang_parse);
285
286 if (count($lang_parse[1])) {
287 // NOTE: array_combine => PHP5
288 $accept_langs = array_combine($lang_parse[1], $lang_parse[4]); // create a list like "en" => 0.8
289 // set default to 1 for any without q factor
290 foreach ($accept_langs as $accept_lang => $val) {
291 if ($val === '') $accept_langs[$accept_lang] = 1;
292 }
293 arsort($accept_langs, SORT_NUMERIC); // sort list based on value
294 }
295 }
296
297 // looks through sorted list and use first one that matches our language list
298 $listlanguages = $this->get_languages_list(true); // hides languages with no post
299 foreach ($accept_langs as $accept_lang => $val) {
300 foreach ($listlanguages as $language) {
301 if (strpos($accept_lang, $language->slug) === 0 && !isset($pref_lang)) {
302 $pref_lang = $language;
303 }
304 }
305 }
306 } // options['browser']
307
308 // either there is no preference in the browser or preferences does not match our language list or it is requested not to use the browser preference
309 if (!isset($pref_lang))
310 $pref_lang = $this->get_language($options['default_lang']);
311
312 return $pref_lang;
313 }
314
315 // returns the current language
316 function get_current_language() {
317 global $post_ID;
318
319 if($this->curlang)
320 return $this->curlang;
321
322 if (is_404())
323 return $this->get_preferred_language();
324
325 if (is_admin()) {
326 if (isset($post_ID))
327 $lang = $this->get_post_language($post_ID);
328
329 // trick to get the post number in the Post Tags metabox in the Edit Post screen (as $post_ID not defined)
330 $qvars = $this->get_referer_vars();
331 if (isset($qvars['post']))
332 $lang = $this->get_post_language($qvars['post']);
333 }
334 else {
335 $var = get_query_var('lang');
336 if ($var)
337 $lang = $this->get_language($var);
338 else {
339 $var = get_queried_object_id();
340 if ($var && is_single() || is_page())
341 $lang = $this->get_post_language($var);
342 else {
343 $var = get_query_var('cat');
344 if ($var)
345 $lang = $this->get_term_language($var);
346 else {
347 $var = get_query_var('tag_id');
348 if ($var)
349 $lang = $this->get_term_language($var);
350 }
351 }
352 }
353 }
354
355 return (isset($lang)) ? $lang : NULL;
356 }
357
358 // returns the locale based on current language
359 function get_locale($locale) {
360 if ($this->curlang)
361 $locale = $this->curlang->description;
362 return $locale;
363 }
364
365 // saves all text domains in a table for later usage
366 function mofile( $bool, $domain, $mofile) {
367 $this->list_textdomains[] = array ('mo' => $mofile, 'domain' => $domain);
368 return true; // prevents WP loading text domains as we will load them all later
369 }
370
371 // NOTE: I believe there are two ways for a plugin to force the WP language
372 // as done by xili_language and here : load text domains and reinitialize wp_locale with the action 'wp'
373 // as done by qtranslate : define the locale with the action 'plugins_loaded', but in this case, the language must be specified in the url.
374 function load_textdomains() {
375 // sets the current language and set a cookie to remember it
376 if ($this->curlang = $this->get_current_language())
377 setcookie('wordpress_polylang', $this->curlang->slug, time() + 31536000 /* 1 year */, COOKIEPATH, COOKIE_DOMAIN);
378
379 // our override_load_textdomain has done its job. let's remove it before calling load_textdomain
380 remove_filter('override_load_textdomain', array(&$this, 'mofile'));
381
382 // now we can load text domains with the right language
383 $new_locale = get_locale();
384 foreach ($this->list_textdomains as $textdomain)
385 load_textdomain( $textdomain['domain'], str_replace($this->default_locale, $new_locale, $textdomain['mo']));
386
387 global $wp_locale;
388 $wp_locale->init(); // reinitializes wp_locale for weekdays and months
389 }
390
391 // filters posts according to the language
392 function pre_get_posts($query) {
393
394 if (empty($query->query)) {
395
396 // sets the language according to browser preference or default language
397 $this->curlang = $this->get_preferred_language();
398
399 // redirect to the right translated page in case a static page is used as front page
400 $post_id = get_option('page_on_front');
401 if (isset($this->curlang) && $post_id) {
402 // a static page is used as front page
403
404 $language = $this->get_post_language($post_id);
405 if ($language->slug != $this->curlang->slug) {
406 // but the one defined in the "Reading Settings" panel is not in the right language, so let's redirect to the right one
407 $link_id = $this->get_translated_post($post_id, $this->curlang);
408 if ($link_id) {
409 $url = _get_page_link($link_id);
410 wp_redirect($url);
411 exit;
412 }
413 }
414 }
415 }
416 $qvars = $query->query_vars;
417
418 // filters recent posts to the current language
419 // FIXME if $qvars['post_type'] == 'nav_menu_item', setting lang breaks custom menus.
420 // since to get nav_menu_items, get_post is used and no language is linked to nav_menu_items
421 if ($query->is_home && $this->curlang && !isset($qvars['post_type']))
422 $query->set('lang', $this->curlang->slug);
423
424 // remove pages query when the language is set
425 if (isset($qvars['lang']) && $qvars['lang'] && !isset($qvars['post_type']))
426 $query->set('post_type', 'post');
427 }
428
429 function wp_head() {
430 // modifies the canonical link to the homepage
431 if (is_singular()) {
432 global $wp_the_query;
433 if ($id = $wp_the_query->get_queried_object_id()) {
434 if (is_page())
435 $link = _get_page_link($id); // ignores page_on_front unlike get_permalink
436 else
437 $link = get_permalink ($id);
438 echo "<link rel='canonical' href='$link' />\n";
439 }
440 }
441
442 // outputs references to translated pages (if exists) in the html head section
443 // FIXME improve this to make only one db query
444 $listlanguages = $this->get_languages_list();
445 foreach ($listlanguages as $language) {
446 if ($language->slug != $this->curlang->slug) {
447 $url = $this->get_translation_url($language);
448 if ($url)
449 printf("<link hreflang='%s' href='%s' rel='alternate' />\n", esc_attr($language->slug), $url);
450 }
451 }
452 }
453
454 // prevents redirection of the homepage
455 function redirect_canonical($redirect_url, $requested_url) {
456 if($requested_url == _get_page_link(get_option('page_on_front')))
457 return false;
458 return $redirect_url;
459 }
460
461 // adds some javascript workaround knowing it's not perfect...
462 function wp_print_footer_scripts() {
463 if ($this->curlang) {
464 $js = "<script type='text/javascript'>";
465
466 // modifies links to the homepage to filter by the right language
467 // since filtering home_url breaks things in the core and filtering bloginfo_url is not enough if the template uses home_url()
468 $url = rtrim(home_url(), '/');
469
470 if ($page = get_option('page_on_front'))
471 $newurl = _get_page_link($this->get_post($page, $this->curlang));
472 else
473 $newurl = get_term_link($this->curlang->slug, 'language');
474
475 $js .= "var e = document.getElementsByTagName('a');
476 for (var i = 0; i < e.length; i++) {
477 var href = e[i].href;
478 if (href == '$url' || href == '$url/') {
479 e[i].href = '$newurl';
480 }
481 }";
482
483 // modifies the search form since filtering get_search_form won't work if the template uses searchform.php
484 // don't use directly e[0] just in case there is somewhere else an element named 's'
485 // check before if the hidden input has not already been introduced by get_search_form
486 if (!$this->search_form_filter) {
487 $lang = esc_js($this->curlang->slug);
488 $js .= "e = document.getElementsByName('s');
489 for (i = 0; i < e.length; i++) {
490 if (e[i] == '[object HTMLInputElement]') {
491 var ih = document.createElement('input');
492 ih.type = 'hidden';
493 ih.name = 'lang';
494 ih.value = '$lang';
495 e[i].parentNode.appendChild(ih);
496 }
497 }";
498 }
499
500 $js .= "</script>";
501 echo $js;
502 }
503 }
504
505 // adds the language information in the search form
506 // FIXME does not work if searchform.php is used
507 function get_search_form($form) {
508 if ($form) {
509 $this->search_form_filter = true;
510 $form = str_replace('</form>', '<input type="hidden" name="lang" value="'.esc_attr($this->curlang->slug).'" /></form>', $form);
511 }
512 return $form;
513 }
514
515 // filters the list of pages according to the current language
516 // it seems that there is currently no way to filter before the database query (3.2)
517 // cannot play with widget_pages_args filter either as it seems that get_pages does not query taxonomies :(
518 // so redo the query with get_posts and the 'lang' parameter seems to be be the current best way (rather than trying to manipulate $pages)
519 function get_pages($pages, $r) {
520 if (isset($this->curlang)) {
521 $r['lang'] = $this->curlang->slug;
522 $pages = get_posts($r);
523 }
524 return $pages;
525 }
526
527 // filters the comments according to the current language
528 function comments_clauses($clauses) {
529 if ($this->curlang) {
530 global $wpdb;
531 $clauses['join'] .= " INNER JOIN $wpdb->term_relationships AS tr ON tr.object_id = ID";
532 $clauses['join'] .= " INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id";
533 $clauses['where'] .= $wpdb->prepare(" AND tt.term_id = %d", $this->curlang->term_id);
534 }
535 return $clauses;
536 }
537
538 // Modifies the feed link to add the language parameter
539 // FIXME should be an option to do this ?
540 function feed_link($url, $feed) {
541 global $wp_rewrite;
542 $options = get_option('polylang');
543
544 if ($this->curlang) {
545 if ($wp_rewrite->using_permalinks()) {
546 $home = home_url();
547 $options['rewrite'] ? $base = '/' : $base = '/language/';
548 $url = esc_url(str_replace($home, $home.$base.$this->curlang->slug, $url));
549 }
550 else {
551 if ($feed)
552 $url = esc_url(home_url('?lang='.$this->curlang->slug.'&feed='.$feed));
553 }
554 }
555 return $url;
556 }
557
558 // modifies the sql request for wp_get_archives an get_adjacent_post to filter by the current language
559 function posts_join($sql) {
560 if ($this->curlang) {
561 global $wpdb;
562 $sql .= " INNER JOIN $wpdb->term_relationships ON object_id = ID";
563 }
564 return $sql;
565 }
566
567 // modifies the sql request for wp_get_archives and get_adjacent_post to filter by the current language
568 function posts_where($sql) {
569 if ($this->curlang) {
570 global $wpdb;
571 $sql .= $wpdb->prepare(" AND term_taxonomy_id = %d", $this->curlang->term_id);
572 }
573 return $sql;
574 }
575
576 // modifies the archives link to add the language parameter
577 function get_archives_link($link_html) {
578 if ($this->curlang) {
579 global $wp_rewrite;
580 $options = get_option('polylang');
581 $home = home_url();
582 if ($wp_rewrite->using_permalinks()) {
583 $options['rewrite'] ? $base = '/' : $base = '/language/';
584 $link_html = str_replace($home, esc_attr($home.$base.$this->curlang->slug), $link_html);
585 }
586 else
587 $link_html = str_replace($home.'/?', esc_attr($home.'/?lang='.$this->curlang->slug).'&amp;', $link_html);
588 }
589 return $link_html;
590 }
591
592 // returns the url of the translation (if exists) of the current page
593 function get_translation_url($language) {
594
595 if ( is_single()) {
596 $id = $this->get_post(get_the_ID(), $language);
597 if ($id)
598 $url = get_permalink($id);
599 }
600
601 elseif ( is_page() ) {
602 $id = $this->get_post(get_the_ID(), $language);
603 if ($id)
604 $url = _get_page_link($id);
605 }
606
607 elseif ( is_category() || is_tag() ) {
608 $term = get_queried_object();
609 $term_id = $term->term_id;
610 $taxonomy = $term->taxonomy;
611 $lang = $this->get_term_language($term_id);
612
613 if ($language->slug == $lang->slug)
614 $url = get_term_link($term->slug, $taxonomy); // self link
615 else {
616 $link_id = $this->get_translated_term($term_id, $language);
617 if ($link_id) {
618 $term = get_term($link_id,$taxonomy); // We need the slug for get_term_link
619 $url = get_term_link($term->slug, $taxonomy);
620 }
621 }
622 }
623
624 // FIXME for date links, if I simply modify the lang query, there is a risk that there is no posts (if all are not translated at this date)
625 // do nothing for now
626 elseif ( is_year() ) {
627 }
628
629 elseif ( is_month() ) {
630 }
631
632 elseif (is_home() || is_tax('language') )
633 $url = get_term_link($language->slug, 'language');
634
635 return isset($url) ? $url : null;
636 }
637
638 // filters the nav menus according to the current language
639 function wp_nav_menu_args($args) {
640 if (!$args['menu'] && $args['theme_location'] && $this->curlang) {
641 $menu_lang = get_option('polylang_nav_menus');
642 $args['menu'] = $menu_lang[$args['theme_location']][$this->curlang->slug];
643 }
644 return $args;
645 }
646
647 // filters the widgets according to the current language
648 function widget_display_callback($instance, $widget, $args) {
649 $widget_lang = get_option('polylang_widgets');
650 // don't display if a language filter is set and this is not the current one
651 if (isset($this->curlang) && isset($widget_lang[$widget->id]) && $widget_lang[$widget->id] && $widget_lang[$widget->id] != $this->curlang->slug)
652 return false;
653
654 return $instance;
655 }
656
657 // returns the home url in the right language
658 function get_home_url($language) {
659 $post_id = get_option('page_on_front');
660 if ($post_id) {
661 // a static page is used as front page
662 $id = $this->get_post($post_id, $language);
663 if($id)
664 $url = _get_page_link($id);
665 }
666 return isset($url) ? $url : get_term_link($language->slug, 'language');
667 }
668
669 // adds 'lang_url' as possible value to the 'show' parameter of bloginfo to display the home url in the correct language
670 // FIXME not tested
671 function bloginfo_url($output, $show) {
672 if ($show == 'lang_url' && $this->curlang) {
673 $url = $this->get_home_url($this->curlang);
674 $output = isset($url) ? $url : home_url('/');
675 }
676 return $output;
677 }
678
679 // Template tag : Displays links to the current page in other languages
680 // Usage : do_action('the_languages');
681 function the_languages() {
682 $listlanguages = $this->get_languages_list(true); // hides languages with no posts
683 $output = "<ul>\n";
684 foreach ($listlanguages as $language) {
685 $url = $this->get_translation_url($language);
686 if (!isset($url))
687 $url = $this->get_home_url($language); // if the page is not translated, link to the home page
688 $output .= "<li><a href='$url'>".esc_attr($language->name)."</a></li>\n";
689 }
690 $output .= "</ul>\n";
691 echo $output;
692 }
693
694 } // class Polylang
695
696 if (class_exists("Polylang"))
697 new Polylang();
698
699 ?>
700