PluginProbe
Polylang / 0.5
Polylang v0.5
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 / include / core.php

core.php in Polylang 0.5, at include/core.php

708 lines 26.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // filters posts and terms by language, rewrites links to include the language, etc...
3 class Polylang_Core extends Polylang_base {
4 private $curlang; // current language
5 private $default_locale;
6 private $list_textdomains = array(); // all text domains
7 private $search_form_filter = false; // did we pass our get_search_form filter ?
8
9 // options often needed
10 private $home;
11 private $options;
12 private $page_for_posts;
13 private $page_on_front;
14
15 function __construct() {
16
17 // options often needed
18 $this->options = get_option('polylang');
19 $this->home = get_option('home');
20 $this->page_for_posts = get_option('page_for_posts');
21 $this->page_on_front = get_option('page_on_front');
22
23 // text domain management
24 add_action('init', array(&$this, 'init'));
25 add_filter('locale', array(&$this, 'get_locale'));
26 add_filter('override_load_textdomain', array(&$this, 'mofile'), 10, 3);
27 add_action('wp', array(&$this, 'load_textdomains'));
28
29 // filters posts according to the language
30 add_filter('pre_get_posts', array(&$this, 'pre_get_posts'));
31
32 // filters categories and post tags by language
33 add_filter('terms_clauses', array(&$this, 'terms_clauses'), 10, 3);
34
35 // meta in the html head section
36 remove_action('wp_head', 'rel_canonical');
37 add_action('wp_head', array(&$this, 'wp_head'));
38
39 // prevents redirection of the homepage
40 add_filter('redirect_canonical', array(&$this, 'redirect_canonical'), 10, 2);
41
42 // adds javascript at the end of the document
43 add_action('wp_print_footer_scripts', array(&$this, 'wp_print_footer_scripts'));
44
45 // adds the language information in the search form
46 // low priority in case the search form is created using the same filter as described in http://codex.wordpress.org/Function_Reference/get_search_form
47 add_filter('get_search_form', array(&$this, 'get_search_form'), 99);
48
49 // filters the pages according to the current language in wp_list_pages
50 add_filter('wp_list_pages_excludes', array(&$this, 'wp_list_pages_excludes'));
51
52 // filters the comments according to the current language
53 add_filter('comments_clauses', array(&$this, 'comments_clauses'), 10, 2);
54
55 // rewrites feed links to filter them by language
56 add_filter('feed_link', array(&$this, 'feed_link'), 10, 2);
57
58 // rewrites archives links to filter them by language
59 add_filter('getarchives_join', array(&$this, 'posts_join'));
60 add_filter('getarchives_where', array(&$this, 'posts_where'));
61
62 // rewrites author and date links to filter them by language
63 add_filter('author_link', array(&$this, 'archive_link'));
64 add_filter('year_link', array(&$this, 'archive_link'));
65 add_filter('month_link', array(&$this, 'archive_link'));
66 add_filter('day_link', array(&$this, 'archive_link'));
67
68 // rewrites next and previous post links to filter them by language
69 add_filter('get_previous_post_join', array(&$this, 'posts_join'));
70 add_filter('get_next_post_join', array(&$this, 'posts_join'));
71 add_filter('get_previous_post_where', array(&$this, 'posts_where'));
72 add_filter('get_next_post_where', array(&$this, 'posts_where'));
73
74 // filters the nav menus according to the current language
75 add_filter('wp_nav_menu_args', array(&$this, 'wp_nav_menu_args'));
76 add_filter('wp_nav_menu_items', array(&$this, 'wp_nav_menu_items'), 10, 2);
77 add_filter('wp_nav_menu_objects', array(&$this, 'wp_nav_menu_objects'), 10, 2);
78 add_filter('wp_page_menu', array(&$this, 'wp_page_menu'), 10, 2);
79
80 // filters the widgets according to the current language
81 add_filter('widget_display_callback', array(&$this, 'widget_display_callback'), 10, 3);
82
83 // modifies the home url
84 add_filter('home_url', array(&$this, 'home_url'));
85
86 // allows a new value for the 'show' parameter to display the homepage url according to the current language
87 // FIXME Backward compatibily for versions < 0.5 -> replaced by a filter on home_url
88 add_filter('bloginfo_url', array(&$this, 'bloginfo_url'), 10, 2);
89
90 // Template tag: displays the language switcher
91 // FIXME Backward compatibily for versions < 0.5 -> replaced by pll_the_languages
92 add_action('the_languages', array(&$this, 'the_languages'));
93 }
94
95 // returns the language according to browser preference or the default language
96 function get_preferred_language() {
97 // check first is the user was already browsing this site
98 if (isset($_COOKIE['wordpress_polylang']))
99 return $this->get_language($_COOKIE['wordpress_polylang']);
100
101 // sets the browsing language according to the browser preferences
102 // code adapted from http://www.thefutureoftheweb.com/blog/use-accept-language-header
103 if ($this->options['browser']) {
104 $accept_langs = array();
105
106 if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
107 // break up string into pieces (languages and q factors)
108 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);
109
110 if (count($lang_parse[1])) {
111 // NOTE: array_combine => PHP5
112 $accept_langs = array_combine($lang_parse[1], $lang_parse[4]); // create a list like "en" => 0.8
113 // set default to 1 for any without q factor
114 foreach ($accept_langs as $accept_lang => $val) {
115 if ($val === '') $accept_langs[$accept_lang] = 1;
116 }
117 arsort($accept_langs, SORT_NUMERIC); // sort list based on value
118 }
119 }
120
121 // looks through sorted list and use first one that matches our language list
122 $listlanguages = $this->get_languages_list(true); // hides languages with no post
123 foreach ($accept_langs as $accept_lang => $val) {
124 foreach ($listlanguages as $language) {
125 if (strpos($accept_lang, $language->slug) === 0 && !isset($pref_lang)) {
126 $pref_lang = $language;
127 }
128 }
129 }
130 } // options['browser']
131
132 // 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
133 if (!isset($pref_lang))
134 $pref_lang = $this->get_language($this->options['default_lang']);
135
136 return $pref_lang;
137 }
138
139 // returns the current language
140 function get_current_language() {
141 if($this->curlang)
142 return $this->curlang;
143
144 // no language set for 404 and attachment
145 if (is_404() || is_attachment())
146 return $this->get_preferred_language();
147
148 if ($var = get_query_var('lang'))
149 $lang = $this->get_language($var);
150
151 elseif (is_single() || is_page() && $var = get_queried_object_id())
152 $lang = $this->get_post_language($var);
153
154 else {
155 foreach (get_taxonomies(array('show_ui'=>true)) as $taxonomy) {
156 if ($var = get_query_var(get_taxonomy($taxonomy)->query_var))
157 $lang = $this->get_term_language($var, $taxonomy);
158 }
159 }
160
161 return (isset($lang)) ? $lang : NULL;
162 }
163
164 // save the default locale before we start any language manipulation
165 function init() {
166 $this->default_locale = get_locale();
167 }
168
169 // returns the locale based on current language
170 function get_locale($locale) {
171 if ($this->curlang)
172 $locale = $this->curlang->description;
173 return $locale;
174 }
175
176 // saves all text domains in a table for later usage
177 function mofile($bool, $domain, $mofile) {
178 $this->list_textdomains[] = array ('mo' => $mofile, 'domain' => $domain);
179 return true; // prevents WP loading text domains as we will load them all later
180 }
181
182 // NOTE: I believe there are two ways for a plugin to force the WP language
183 // as done by xili_language and here: load text domains and reinitialize wp_locale with the action 'wp'
184 // as done by qtranslate: define the locale with the action 'plugins_loaded', but in this case, the language must be specified in the url.
185 function load_textdomains() {
186 // sets the current language and set a cookie to remember it
187 if ($this->curlang = $this->get_current_language())
188 setcookie('wordpress_polylang', $this->curlang->slug, time() + 31536000 /* 1 year */, COOKIEPATH, COOKIE_DOMAIN);
189
190 // our override_load_textdomain filter has done its job. let's remove it before calling load_textdomain
191 remove_filter('override_load_textdomain', array(&$this, 'mofile'));
192
193 // now we can load text domains with the right language
194 $new_locale = get_locale();
195 foreach ($this->list_textdomains as $textdomain)
196 load_textdomain( $textdomain['domain'], str_replace($this->default_locale, $new_locale, $textdomain['mo']));
197
198 global $wp_locale;
199 $wp_locale->init(); // reinitializes wp_locale for weekdays and months
200 }
201
202 // filters posts according to the language
203 function pre_get_posts($query) {
204 global $wp_rewrite;
205 $qvars = $query->query_vars;
206
207 // detect our exclude pages query and returns to avoid conflicts
208 // this test should be sufficient
209 if (isset($qvars['tax_query'][0]) && isset($qvars['tax_query'][0]['taxonomy']) && isset($qvars['tax_query'][0]['operator']))
210 return;
211
212 if (empty($query->query)) {
213 if ( $this->options['hide_default'] && isset($_COOKIE['wordpress_polylang']) )
214 $this->curlang = $this->get_language($this->options['default_lang']);
215 else
216 $this->curlang = $this->get_preferred_language(); // sets the language according to browser preference or default language
217
218 if ($this->options['default_lang'] == $this->curlang->slug && $this->options['hide_default']) {
219 if ($this->page_on_front && $link_id = $this->get_post($this->page_on_front, $this->curlang))
220 $query->set('page_id', $link_id);
221 else
222 $query->set('lang', $this->curlang->slug);
223 }
224 else {
225 if ($this->page_on_front && $link_id = $this->get_post($this->page_on_front, $this->curlang))
226 $url = _get_page_link($link_id);
227 else
228 $url = home_url('?lang='.$this->curlang->slug);
229
230 wp_redirect($url);
231 exit;
232 }
233 }
234
235 // sets the language for posts page in case the front page displays a static page
236 if ($this->page_for_posts) {
237 // If permalinks are used, WordPress does set and use $query->queried_object_id and sets $query->query_vars['page_id'] to 0
238 // and does set and use $query->query_vars['page_id'] if permalinks are not used :(
239 if (isset($query->queried_object_id))
240 $page_id = $query->queried_object_id;
241 elseif (isset($qvars['page_id']))
242 $page_id = $qvars['page_id'];
243
244 if (isset($page_id) && $page_id && $this->get_post($page_id, $this->get_post_language($this->page_for_posts)) == $this->page_for_posts) {
245 $query->set('lang',$this->get_post_language($page_id)->slug);
246 $query->queried_object_id = $this->page_for_posts;
247 $query->query_vars['page_id'] = $this->page_for_posts; // FIXME the trick works but breaks .current-menu-item and .current_page_item
248 $query->is_page = false;
249 $query->is_home = true;
250 $query->is_posts_page = true;
251 $query->is_singular = false;
252 }
253 }
254
255 // FIXME to generalize as I probably forget things
256 // sets the language in case we hide the default language
257 if ( $this->options['hide_default'] && !isset($qvars['lang']) && (
258 (count($query->query) == 1 && isset($qvars['paged']) && $qvars['paged']) ||
259 isset($qvars['m']) && $qvars['m'] ||
260 isset($qvars['feed']) && $qvars['feed'] ||
261 isset($qvars['author']) && $qvars['author']))
262 $query->set('lang', $this->options['default_lang']);
263
264 // filters recent posts to the current language
265 // FIXME if $qvars['post_type'] == 'nav_menu_item', setting lang breaks custom menus.
266 // since to get nav_menu_items, get_post is used and no language is linked to nav_menu_items
267 if ($query->is_home && $this->curlang && !isset($qvars['post_type']))
268 $query->set('lang', $this->curlang->slug);
269
270 // remove pages query when the language is set unless we do a search
271 // FIXME is only search broken by this ?
272 if (isset($qvars['lang']) && $qvars['lang'] && !isset($qvars['post_type']) && !is_search())
273 $query->set('post_type', 'post');
274
275 // unset the is_archive flag for language pages to prevent loading the archive template
276 // keep archive flag for comment feed otherwise the language filter does not work
277 if (isset($qvars['lang']) && $qvars['lang'] && !is_post_type_archive() && !is_date() && !is_author() && !is_category() && !is_tag() && !is_comment_feed())
278 $query->is_archive = false;
279
280 // unset the is_tax flag for authors pages
281 // FIXME Probably I should do this for other cases
282 if (isset($qvars['lang']) && $qvars['lang'] && is_author())
283 $query->is_tax = false;
284
285 // sets a language for theme preview
286 if (isset($_GET['preview']))
287 $query->set('lang', $this->options['default_lang']);
288
289 if (PLL_DISPLAY_ALL) {
290 // add posts with no language set
291 $query->query_vars['tax_query'] = array(
292 'relation' => 'OR', array(
293 'taxonomy'=> 'language',
294 'terms'=> get_terms('language', array('fields'=>'ids')),
295 'operator'=>'NOT IN'));
296 }
297 }
298
299 // filters categories and post tags by language when needed
300 function terms_clauses($clauses, $taxonomies, $args) {
301 // does nothing except on taxonomies which have show_ui set to 1 (includes category and post_tags)
302 foreach ($taxonomies as $tax) {
303 if(!get_taxonomy($tax)->show_ui)
304 return $clauses;
305 }
306
307 // adds our clauses to filter by current language
308 return isset($this->curlang) ? $this->_terms_clauses($clauses, $this->curlang, PLL_DISPLAY_ALL) : $clauses;
309 }
310
311 // meta in the html head section
312 function wp_head() {
313 // modifies the canonical link to the homepage
314 if (is_singular()) {
315 global $wp_the_query;
316 if ($id = $wp_the_query->get_queried_object_id()) {
317 if (is_page())
318 $link = _get_page_link($id); // ignores page_on_front unlike get_permalink
319 else
320 $link = get_permalink ($id);
321 echo "<link rel='canonical' href='$link' />\n";
322 }
323 }
324
325 // outputs references to translated pages (if exists) in the html head section
326 foreach ($this->get_languages_list() as $language) {
327 if ($language->slug != $this->curlang->slug && $url = $this->get_translation_url($language))
328 printf("<link hreflang='%s' href='%s' rel='alternate' />\n", esc_attr($language->slug), esc_url($url));
329 }
330 }
331
332 // prevents redirection of the homepage
333 function redirect_canonical($redirect_url, $requested_url) {
334 if($requested_url == _get_page_link($this->page_on_front))
335 return false;
336 return $redirect_url;
337 }
338
339 // adds some javascript workaround knowing it's not perfect...
340 function wp_print_footer_scripts() {
341 if ($this->curlang) {
342 $js = '';
343
344 // modifies the search form since filtering get_search_form won't work if the template uses searchform.php
345 // don't use directly e[0] just in case there is somewhere else an element named 's'
346 // check before if the hidden input has not already been introduced by get_search_form
347 if (!$this->search_form_filter) {
348 $lang = esc_js($this->curlang->slug);
349 $js .= "e = document.getElementsByName('s');
350 for (i = 0; i < e.length; i++) {
351 if (e[i] == '[object HTMLInputElement]') {
352 var ih = document.createElement('input');
353 ih.type = 'hidden';
354 ih.name = 'lang';
355 ih.value = '$lang';
356 e[i].parentNode.appendChild(ih);
357 }
358 }";
359 }
360
361 if ($js)
362 echo "<script type='text/javascript'>" .$js. "</script>";
363 }
364 }
365
366 // adds the language information in the search form
367 // does not work if searchform.php is used
368 function get_search_form($form) {
369 if ($form) {
370 $this->search_form_filter = true;
371 $form = str_replace('</form>', '<input type="hidden" name="lang" value="'.esc_attr($this->curlang->slug).'" /></form>', $form);
372 }
373 return $form;
374 }
375
376 // excludes pages which are not in the current language for wp_list_pages
377 // useful for the pages widget
378 function wp_list_pages_excludes($pages) {
379 if (isset($this->curlang)) {
380 $q = array(
381 'numberposts'=>-1,
382 'post_type' => 'page',
383 'fields' => 'ids',
384 'tax_query' => array(array(
385 'taxonomy'=>'language',
386 'fields' => 'id',
387 'terms'=>$this->curlang->term_id,
388 'operator'=>'NOT IN'
389 ))
390 );
391 $pages = array_merge($pages, get_posts($q));
392 }
393 return $pages;
394 }
395
396 // filters the comments according to the current language mainly for the recent comments widget
397 function comments_clauses($clauses, $comment_query) {
398 // first test if wp_posts.ID already available in the query
399 if ($this->curlang && strpos($clauses['join'], '.ID')) {
400 global $wpdb;
401 $clauses['join'] .= " INNER JOIN $wpdb->term_relationships AS tr ON tr.object_id = ID";
402 $clauses['where'] .= $wpdb->prepare(" AND tr.term_taxonomy_id = %d", $this->curlang->term_taxonomy_id);
403 }
404 return $clauses;
405 }
406
407 // Modifies the feed link to add the language parameter
408 function feed_link($url, $feed) {
409 global $wp_rewrite;
410
411 if ($this->curlang) {
412 if ($wp_rewrite->using_permalinks()) {
413 $base = $this->options['rewrite'] ? '/' : '/language/';
414 $slug = $this->options['default_lang'] == $this->curlang->slug && $this->options['hide_default'] ? '' : $base.$this->curlang->slug;
415 $url = esc_url(str_replace($this->home, $this->home.$slug, $url));
416 }
417 elseif ($feed)
418 $url = esc_url(home_url('?lang='.$this->curlang->slug.'&feed='.$feed));
419
420 }
421 return $url;
422 }
423
424 // modifies the sql request for wp_get_archives an get_adjacent_post to filter by the current language
425 function posts_join($sql) {
426 if ($this->curlang) {
427 global $wpdb;
428 $sql .= " INNER JOIN $wpdb->term_relationships ON object_id = ID";
429 }
430 return $sql;
431 }
432
433 // modifies the sql request for wp_get_archives and get_adjacent_post to filter by the current language
434 function posts_where($sql) {
435 if ($this->curlang) {
436 global $wpdb;
437 $sql .= $wpdb->prepare(" AND term_taxonomy_id = %d", $this->curlang->term_taxonomy_id);
438 }
439 return $sql;
440 }
441
442 // modifies the author and date links to add the language parameter
443 function archive_link($link) {
444 if ($this->curlang) {
445 global $wp_rewrite;
446
447 if ($wp_rewrite->using_permalinks()) {
448 $base = $this->options['rewrite'] ? '/' : '/language/';
449 $slug = $this->options['default_lang'] == $this->curlang->slug && $this->options['hide_default'] ? '' : $base.$this->curlang->slug;
450 $link = esc_url(str_replace($this->home, $this->home.$slug, $link));
451 }
452 else
453 $link = esc_url(str_replace($this->home.'/?', $this->home.'/?lang='.$this->curlang->slug.'&amp;', $link));
454 }
455 return $link;
456 }
457
458 // returns the url of the translation (if exists) of the current page
459 function get_translation_url($language) {
460 global $wp_query, $wp_rewrite;
461 $qvars = $wp_query->query;
462 $hide = $this->options['default_lang'] == $language->slug && $this->options['hide_default'];
463
464 // is_single is set to 1 for attachment but no language is set
465 if (is_single() && !is_attachment() && $id = $this->get_post(get_the_ID(), $language))
466 $url = get_permalink($id);
467
468 // page for posts
469 elseif (get_option('show_on_front') == 'page' && // necessary for twentyeleven
470 isset($wp_query->queried_object_id) &&
471 $wp_query->queried_object_id == $this->page_for_posts
472 )
473 $url = get_permalink($this->get_post($this->page_for_posts, $language));
474
475 elseif (is_page() && $id = $this->get_post(get_the_ID(), $language))
476 $url = $hide && $id == $this->get_post($this->page_on_front, $language) ?
477 $this->home :
478 _get_page_link($id);
479
480 elseif ( !is_tax ('language') && (is_category() || is_tag() || is_tax () ) ) {
481 $term = get_queried_object();
482 $lang = $this->get_term_language($term->term_id);
483 $taxonomy = $term->taxonomy;
484
485 if ($language->slug == $lang->slug)
486 $url = get_term_link($term, $taxonomy); // self link
487 elseif ($link_id = $this->get_translation('term', $term->term_id, $language))
488 $url = get_term_link(get_term($link_id, $taxonomy), $taxonomy);
489 }
490
491 // don't test if there are existing translations before creating the url as it would be very expensive in sql queries
492 elseif(is_archive()) {
493 if ($wp_rewrite->using_permalinks()) {
494 $base = $this->options['rewrite'] ? '/' : '/language/';
495 $base = $hide ? '' : $base.$language->slug;
496 $base = $this->home.$base.'/';
497
498 if (is_author())
499 $url = esc_url($base.'author/'.$qvars['author_name'].'/');
500
501 if (is_year())
502 $url = esc_url($base.$qvars['year'].'/');
503
504 if (is_month())
505 $url = esc_url($base.$qvars['year'].'/'.$qvars['monthnum'].'/');
506
507 if (is_day())
508 $url = esc_url($base.$qvars['year'].'/'.$qvars['monthnum'].'/'.$qvars['day'].'/');
509 }
510 else
511 $url = $hide ? remove_query_arg('lang') : add_query_arg('lang', $language->slug);
512 }
513
514 elseif (is_home() || is_tax('language') )
515 $url = $hide ? $this->home : get_term_link($language, 'language');
516
517 return isset($url) ? $url : null;
518 }
519
520 // filters the nav menus according to the current language
521 function wp_nav_menu_args($args) {
522 if (!$args['menu'] && $args['theme_location'] && $this->curlang) {
523 $menu_lang = get_option('polylang_nav_menus');
524 $args['menu'] = $menu_lang[$args['theme_location']][$this->curlang->slug];
525 }
526 return $args;
527 }
528
529 // filters the widgets according to the current language
530 function widget_display_callback($instance, $widget, $args) {
531 $widget_lang = get_option('polylang_widgets');
532 // don't display if a language filter is set and this is not the current one
533 if (isset($this->curlang) && isset($widget_lang[$widget->id]) && $widget_lang[$widget->id] && $widget_lang[$widget->id] != $this->curlang->slug)
534 return false;
535
536 return $instance;
537 }
538
539 // adds the language switcher at the end of the menu
540 function wp_nav_menu_items($items, $args) {
541 $menu_lang = get_option('polylang_nav_menus');
542 return $menu_lang[$args->theme_location]['switcher'] ?
543 $items . $this->the_languages(array(
544 'menu' => 1,
545 'show_names' => $menu_lang[$args->theme_location]['show_names'],
546 'show_flags' => $menu_lang[$args->theme_location]['show_flags'],
547 'force_home' => $menu_lang[$args->theme_location]['force_home'],
548 'echo' => 0)) :
549 $items;
550 }
551
552 // corrects some issues on front page and post pages nav menus items
553 function wp_nav_menu_objects($menu_items, $args) {
554 global $wp_query;
555
556 // corrects classes in the menu for posts page
557 // FIXME check for child pages
558 if ($wp_query->is_posts_page) {
559 $classes = array('current-menu-item', 'current_page_item', 'current_page_parent');
560 foreach($menu_items as $item) {
561 $item->classes = array_diff($item->classes, $classes);
562 if ($item->object_id == $this->get_post($this->page_for_posts, $this->curlang))
563 $item->classes = array_merge($item->classes, $classes);
564 }
565 }
566
567 foreach($menu_items as $item) {
568 if ($item->object == 'page')
569 $item->url = _get_page_link($item->object_id); // avoids bad link on translated front page
570 }
571
572 return $menu_items;
573 }
574
575 // corrects the output of the function for translated home
576 function wp_page_menu($menu, $args) {
577 global $wp_query;
578
579 // add current_page_item class to posts page
580 if ($wp_query->is_posts_page) {
581 $id = $this->get_post($this->page_for_posts, $this->curlang);
582 $menu = str_replace('<li class="page_item page-item-'.$id.'">', '<li class="page_item page-item-'.$id.' current_page_item">', $menu);
583 }
584
585 // add current_page_item class to home page
586 // normally only the homepage has no class. note the space in <li >
587 if ($this->is_front_page() && !is_paged())
588 $menu = str_replace('<li >', '<li class="current_page_item">', $menu);
589
590 // remove the 2nd occurrence of homepage (when translated)
591 if ($this->page_on_front) {
592 $id = $this->get_post($this->page_on_front, $this->curlang);
593 $url = _get_page_link($id);
594 $title = apply_filters( 'the_title', get_page($id)->post_title);
595 $menu = str_replace('<li class="page_item page-item-'.$id.'"><a href="'.$url.'">'.$title.'</a></li>', '', $menu);
596 $menu = str_replace('<li class="page_item page-item-'.$id.' current_page_item"><a href="'.$url.'">'.$title.'</a></li>', '', $menu);
597 }
598 return $menu;
599 }
600
601 // acts as is_front_page but knows about translated front page
602 function is_front_page() {
603 if ('page' == get_option('show_on_front') &&
604 get_option('page_on_front') &&
605 is_page($this->get_post(get_option('page_on_front'), $this->get_current_language()))
606 )
607 return true;
608
609 elseif(is_tax('language'))
610 return true;
611
612 return is_front_page();
613 }
614
615 // filters the home url to get the right language
616 function home_url($url) {
617 if ( !(did_action('template_redirect') && rtrim($url,'/') == rtrim($this->home,'/') && $this->curlang) )
618 return $url;
619
620 // don't like this but at least for WP_Widget_Categories::widget, it seems to be the only solution
621 // FIXME are there other exceptions ?
622 foreach (debug_backtrace() as $trace) {
623 $exceptions = $trace['function'] == 'get_pagenum_link' ||
624 $trace['function'] == 'get_author_posts_url' ||
625 $trace['function'] == 'get_search_form' ||
626 (isset($trace['file']) && strpos($trace['file'], 'searchform.php')) ||
627 ($trace['function'] == 'widget' && $trace['class'] == 'WP_Widget_Categories');
628 if ($exceptions)
629 return $url;
630 }
631 return $this->get_home_url($this->curlang);
632 }
633
634 // returns the home url in the right language
635 function get_home_url($language) {
636 if ($this->options['default_lang'] == $language->slug && $this->options['hide_default'])
637 return trailingslashit($this->home);
638
639 // a static page is used as front page
640 if ($this->page_on_front && $id = $this->get_post($this->page_on_front, $language))
641 $url = _get_page_link($id);
642
643 return isset($url) ? $url : get_term_link($language, 'language');
644 }
645
646 // adds 'lang_url' as possible value to the 'show' parameter of bloginfo to display the home url in the correct language
647 // FIXME not tested
648 function bloginfo_url($output, $show) {
649 if ($show == 'lang_url' && $this->curlang) {
650 $url = $this->get_home_url($this->curlang);
651 $output = isset($url) ? $url : $this->home;
652 }
653 return $output;
654 }
655
656 // displays the language switcher
657 function the_languages($args = '') {
658 $defaults = array(
659 'dropdown' => 0, // display as list and not as dropdown
660 'echo' => 1, // echoes the list
661 'hide_if_empty' => 1, // hides languages with no posts (or pages)
662 'menu' => '0', // not for nav menu
663 'show_flags' => 0, // don't show flags
664 'show_names' => 1, // show language names
665 'force_home' => 0, // tries to find a translation (available only if display != dropdown)
666 );
667 extract(wp_parse_args($args, $defaults));
668
669 $output = '';
670 $listlanguages = $this->get_languages_list($hide_if_empty);
671
672 foreach ($listlanguages as $language) {
673 if ($dropdown) {
674 $output .= sprintf(
675 "<option value='%s'%s>%s</option>\n",
676 esc_attr($language->slug),
677 $language->term_id == $this->curlang->term_id ? ' selected="selected"' : '',
678 esc_html($language->name)
679 );
680 }
681 else {
682 $url = $force_home ? null : $this->get_translation_url($language);
683 $url = isset($url) ? $url : $this->get_home_url($language); // if the page is not translated, link to the home page
684
685 $class = 'lang-item lang-item-'.esc_attr($language->term_id);
686 $class .= $language->term_id == $this->curlang->term_id ? ' current-lang' : '';
687 $class .= $menu ? ' menu-item' : '';
688
689 $flag = $show_flags ? $this->get_flag($language) : '';
690 $name = $show_names || !$show_flags ? esc_html($language->name) : '';
691
692 $output .= '<li class="'.$class.'"><a href="'.esc_url($url).'">'.($show_flags && $show_names ? $flag.'&nbsp;'.$name : $flag.$name)."</a></li>\n";
693 }
694 }
695
696 if ($dropdown)
697 $output = "<select name='lang_choice' id='lang_choice'>\n" . $output . "</select>\n";
698 elseif (!$menu)
699 $output = "<ul>\n" . $output . "</ul>\n";
700
701 if ($echo)
702 echo $output;
703 else
704 return $output;
705 }
706 }
707 ?>
708