Polylang - Version 0.9.2

Version Description

(2102-09-30) =

  • Support new WordPress (WP 3.5+) convention for js and css files naming
  • Improve performance, mainly on frontend
  • Bug correction: the category language is not set when creating it in the post editor (introduced in 0.9)
  • Bug correction: unable to add a query string when using a static front page
  • Bug correction: ajax tag suggestion in "edit post" conflicts with the admin content language filter
  • Bug correction: ugly notices when trying to access a static front page which has not been translated
  • Bug correction: the language code is added to custom post types and taxonomies permalinks even if they are not translatable
  • Bug correction: some arrays in wp_locale mix English and other language
  • Bug correction: the media language is not correctly set when uploading from post if the post has not been saved after choosing the language
Download this release

Release Info

Developer Chouby
Plugin Icon 128x128 Polylang
Version 0.9.2
Comparing to
See all releases

Code changes from version 0.9.1 to 0.9.2

css/admin.css CHANGED
@@ -1 +1,108 @@
1
- .column-term_group,.column-flag,.column-count{width:10%}.form-field input.tog{width:auto;margin-right:2px}#pll_about_box p{text-align:justify}#pll_about_box input{margin:0;padding:0;float:right}.stringstranslations .column-name{width:10%}.stringstranslations .column-string{width:36%}.translation label{display:inline-block;width:23%;vertical-align:top}.translation input,.translation textarea{width:72%}th[class*='column-language_']{width:2em}.pll_icon_edit,.pll_icon_add,.pll_icon_tick{display:block;width:16px;height:16px;background-image:url("icons.png")}.pll_icon_edit{background-position:0 -24px}.pll_icon_add{background-position:-16px -24px}.pll_icon_tick{background-position:-32px -24px}.pll_icon_edit:hover{background-position:0 -40px}.pll_icon_add:hover{background-position:-16px -40px}.pll_icon_tick:hover{background-position:-32px -40px}#post-translations table{width:100%;text-align:left;font-size:11px;margin:0 6px}#post-translations td{font-size:11px}#term-translations table{width:97%}#term-translations th,.media-item .describe .media-translations th{padding:8px 10px}#term-translations td,.media-item .describe .media-translations td{font-size:12px;line-height:26px;margin-bottom:9px;padding:4px 10px}.tr-language-column{width:35%}div#term-translations select[id*='tr_lang_']{width:95%}tr#term-translations select[id*='tr_lang_']{width:65%}.tr-edit-column{width:15%}.media-translations{width:460px}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* languages admin panel */
2
+ .column-term_group, .column-flag, .column-count {
3
+ width : 10%;
4
+ }
5
+
6
+ .form-field input.tog {
7
+ width: auto;
8
+ margin-right: 2px;
9
+ }
10
+
11
+ /* about Polylang metabox */
12
+ #pll_about_box p {
13
+ text-align: justify;
14
+ }
15
+
16
+ #pll_about_box input {
17
+ margin: 0;
18
+ padding: 0;
19
+ float: right;
20
+ }
21
+
22
+ /* strings translation table */
23
+ .stringstranslations .column-name {
24
+ width: 10%;
25
+ }
26
+
27
+ .stringstranslations .column-string {
28
+ width: 36%;
29
+ }
30
+
31
+ .translation label {
32
+ display: inline-block;
33
+ width: 23%;
34
+ vertical-align: top;
35
+ }
36
+
37
+ .translation input, .translation textarea {
38
+ width: 72%;
39
+ }
40
+
41
+ /* language columns in edit.php and edit-tags.php */
42
+ th[class*='column-language_'] {
43
+ width: 2em;
44
+ }
45
+
46
+ .pll_icon_edit, .pll_icon_add, .pll_icon_tick {
47
+ display: block;
48
+ width: 16px;
49
+ height: 16px;
50
+ background-image: url("icons.png");
51
+ }
52
+
53
+ .pll_icon_edit {background-position: 0px -24px;}
54
+ .pll_icon_add {background-position: -16px -24px;}
55
+ .pll_icon_tick {background-position: -32px -24px;}
56
+
57
+ .pll_icon_edit:hover {background-position: 0px -40px;}
58
+ .pll_icon_add:hover {background-position: -16px -40px;}
59
+ .pll_icon_tick:hover {background-position: -32px -40px;}
60
+
61
+ /* languages metabox in post.php */
62
+ #post-translations table {
63
+ width: 100%;
64
+ text-align: left;
65
+ font-size: 11px;
66
+ margin: 0 6px;
67
+ }
68
+
69
+ #post-translations td {
70
+ font-size: 11px;
71
+ }
72
+
73
+ /* language and translations in edit-tags.php as well as media translations in upload.php */
74
+ #term-translations table {
75
+ width: 97%;
76
+ }
77
+
78
+ #term-translations th, .media-item .describe .media-translations th {
79
+ padding: 8px 10px;
80
+ }
81
+
82
+ #term-translations td, .media-item .describe .media-translations td {
83
+ font-size: 12px;
84
+ line-height: 26px;
85
+ margin-bottom: 9px;
86
+ padding: 4px 10px;
87
+ }
88
+
89
+ .tr-language-column {
90
+ width: 35%;
91
+ }
92
+
93
+ div#term-translations select[id*='tr_lang_'] {
94
+ width: 95%;
95
+ }
96
+
97
+ tr#term-translations select[id*='tr_lang_'] {
98
+ width: 65%;
99
+ }
100
+
101
+ .tr-edit-column {
102
+ width: 15%;
103
+ }
104
+
105
+ /* media translations in upload.php */
106
+ .media-translations {
107
+ width: 460px;
108
+ }
css/admin.dev.css DELETED
@@ -1,108 +0,0 @@
1
- /* languages admin panel */
2
- .column-term_group, .column-flag, .column-count {
3
- width : 10%;
4
- }
5
-
6
- .form-field input.tog {
7
- width: auto;
8
- margin-right: 2px;
9
- }
10
-
11
- /* about Polylang metabox */
12
- #pll_about_box p {
13
- text-align: justify;
14
- }
15
-
16
- #pll_about_box input {
17
- margin: 0;
18
- padding: 0;
19
- float: right;
20
- }
21
-
22
- /* strings translation table */
23
- .stringstranslations .column-name {
24
- width: 10%;
25
- }
26
-
27
- .stringstranslations .column-string {
28
- width: 36%;
29
- }
30
-
31
- .translation label {
32
- display: inline-block;
33
- width: 23%;
34
- vertical-align: top;
35
- }
36
-
37
- .translation input, .translation textarea {
38
- width: 72%;
39
- }
40
-
41
- /* language columns in edit.php and edit-tags.php */
42
- th[class*='column-language_'] {
43
- width: 2em;
44
- }
45
-
46
- .pll_icon_edit, .pll_icon_add, .pll_icon_tick {
47
- display: block;
48
- width: 16px;
49
- height: 16px;
50
- background-image: url("icons.png");
51
- }
52
-
53
- .pll_icon_edit {background-position: 0px -24px;}
54
- .pll_icon_add {background-position: -16px -24px;}
55
- .pll_icon_tick {background-position: -32px -24px;}
56
-
57
- .pll_icon_edit:hover {background-position: 0px -40px;}
58
- .pll_icon_add:hover {background-position: -16px -40px;}
59
- .pll_icon_tick:hover {background-position: -32px -40px;}
60
-
61
- /* languages metabox in post.php */
62
- #post-translations table {
63
- width: 100%;
64
- text-align: left;
65
- font-size: 11px;
66
- margin: 0 6px;
67
- }
68
-
69
- #post-translations td {
70
- font-size: 11px;
71
- }
72
-
73
- /* language and translations in edit-tags.php as well as media translations in upload.php */
74
- #term-translations table {
75
- width: 97%;
76
- }
77
-
78
- #term-translations th, .media-item .describe .media-translations th {
79
- padding: 8px 10px;
80
- }
81
-
82
- #term-translations td, .media-item .describe .media-translations td {
83
- font-size: 12px;
84
- line-height: 26px;
85
- margin-bottom: 9px;
86
- padding: 4px 10px;
87
- }
88
-
89
- .tr-language-column {
90
- width: 35%;
91
- }
92
-
93
- div#term-translations select[id*='tr_lang_'] {
94
- width: 95%;
95
- }
96
-
97
- tr#term-translations select[id*='tr_lang_'] {
98
- width: 65%;
99
- }
100
-
101
- .tr-edit-column {
102
- width: 15%;
103
- }
104
-
105
- /* media translations in upload.php */
106
- .media-translations {
107
- width: 460px;
108
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
css/admin.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .column-term_group,.column-flag,.column-count{width:10%}.form-field input.tog{width:auto;margin-right:2px}#pll_about_box p{text-align:justify}#pll_about_box input{margin:0;padding:0;float:right}.stringstranslations .column-name{width:10%}.stringstranslations .column-string{width:36%}.translation label{display:inline-block;width:23%;vertical-align:top}.translation input,.translation textarea{width:72%}th[class*='column-language_']{width:2em}.pll_icon_edit,.pll_icon_add,.pll_icon_tick{display:block;width:16px;height:16px;background-image:url("icons.png")}.pll_icon_edit{background-position:0 -24px}.pll_icon_add{background-position:-16px -24px}.pll_icon_tick{background-position:-32px -24px}.pll_icon_edit:hover{background-position:0 -40px}.pll_icon_add:hover{background-position:-16px -40px}.pll_icon_tick:hover{background-position:-32px -40px}#post-translations table{width:100%;text-align:left;font-size:11px;margin:0 6px}#post-translations td{font-size:11px}#term-translations table{width:97%}#term-translations th,.media-item .describe .media-translations th{padding:8px 10px}#term-translations td,.media-item .describe .media-translations td{font-size:12px;line-height:26px;margin-bottom:9px;padding:4px 10px}.tr-language-column{width:35%}div#term-translations select[id*='tr_lang_']{width:95%}tr#term-translations select[id*='tr_lang_']{width:65%}.tr-edit-column{width:15%}.media-translations{width:460px}
include/admin-base.php CHANGED
@@ -26,6 +26,9 @@ class Polylang_Admin_Base extends Polylang_Base {
26
 
27
  // set user preferences
28
  function admin_init_base() {
 
 
 
29
  // set text direction if the user set its own language
30
  global $wpdb, $wp_locale;
31
  $lang_id = $wpdb->get_var($wpdb->prepare("SELECT t.term_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id
@@ -34,12 +37,10 @@ class Polylang_Admin_Base extends Polylang_Base {
34
  $wp_locale->text_direction = get_metadata('term', $lang_id, '_rtl', true) ? 'rtl' : 'ltr';
35
 
36
  // set user meta when choosing to filter content by language
37
- if (isset($_GET['lang']) && $_GET['lang'] && !is_numeric($_GET['lang'])) // numeric when editing a language
 
38
  update_user_meta(get_current_user_id(), 'pll_filter_content', ($lang = $this->get_language($_GET['lang'])) ? $lang->slug : '');
39
 
40
- if (!$this->get_languages_list())
41
- return;
42
-
43
  // adds the languages in admin bar
44
  // FIXME: OK for WP 3.2 and newer (the admin bar is not displayed on admin side for WP 3.1)
45
  add_action('admin_bar_menu', array(&$this, 'admin_bar_menu'), 100); // 100 determines the position
@@ -48,30 +49,30 @@ class Polylang_Admin_Base extends Polylang_Base {
48
  // adds the link to the languages panel in the wordpress admin menu
49
  function add_menus() {
50
  add_submenu_page('options-general.php', __('Languages', 'polylang'), __('Languages', 'polylang'), 'manage_options', 'mlang', array(&$this, 'languages_page'));
51
-
52
- // adds the about box the languages admin panel
53
- // test of $_GET['tab'] avoids displaying the automatically generated screen options on other tabs
54
- if (PLL_DISPLAY_ABOUT && isset($_GET['page']) && $_GET['page'] == 'mlang' && (!isset($_GET['tab']) || $_GET['tab'] == 'lang'))
55
- add_meta_box('pll_about_box', __('About Polylang', 'polylang'), array(&$this,'about'), 'settings_page_mlang', 'normal', 'high');
56
  }
57
 
58
  // setup js scripts & css styles (only on the relevant pages)
59
  function admin_enqueue_scripts() {
60
  $screen = get_current_screen();
 
61
 
 
 
 
 
62
  $scripts = array(
63
- 'admin' => array( array('settings_page_mlang'), array('jquery', 'wp-ajax-response', 'postbox') ),
64
- 'post' => array( array('post', 'media', 'async-upload', 'edit'), array('jquery', 'wp-ajax-response') ),
65
- 'term' => array( array('edit-tags'), array('jquery', 'wp-ajax-response') ),
66
- 'user' => array( array('profile', 'user-edit'), array('jquery') ),
67
  );
68
 
69
  foreach ($scripts as $script => $v)
70
- if (in_array($screen->base, $v[0]))
71
- wp_enqueue_script('pll_'.$script, POLYLANG_URL .'/js/'.$script.'.js', $v[1], POLYLANG_VERSION);
72
 
73
  if (in_array($screen->base, array('settings_page_mlang', 'post', 'edit-tags', 'edit', 'upload', 'media')))
74
- wp_enqueue_style('polylang_admin', POLYLANG_URL .'/css/admin.css', array(), POLYLANG_VERSION);
75
  }
76
 
77
  // downloads mofiles
@@ -145,7 +146,7 @@ class Polylang_Admin_Base extends Polylang_Base {
145
  // returns options available for the language switcher (menu or widget)
146
  // FIXME do not include the dropdown in menu yet since I need to work on js
147
  function get_switcher_options($type = 'widget', $key ='string') {
148
- $options = array (
149
  'show_names' => array('string' => __('Displays language names', 'polylang'), 'default' => 1),
150
  'show_flags' => array('string' => __('Displays flags', 'polylang'), 'default' => 0),
151
  'force_home' => array('string' => __('Forces link to front page', 'polylang'), 'default' => 0),
26
 
27
  // set user preferences
28
  function admin_init_base() {
29
+ if (!$this->get_languages_list())
30
+ return;
31
+
32
  // set text direction if the user set its own language
33
  global $wpdb, $wp_locale;
34
  $lang_id = $wpdb->get_var($wpdb->prepare("SELECT t.term_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id
37
  $wp_locale->text_direction = get_metadata('term', $lang_id, '_rtl', true) ? 'rtl' : 'ltr';
38
 
39
  // set user meta when choosing to filter content by language
40
+ // $_GET[lang] is used in ajax 'tag suggest' and is numeric when editing a language
41
+ if (!defined('DOING_AJAX') && isset($_GET['lang']) && $_GET['lang'] && !is_numeric($_GET['lang']))
42
  update_user_meta(get_current_user_id(), 'pll_filter_content', ($lang = $this->get_language($_GET['lang'])) ? $lang->slug : '');
43
 
 
 
 
44
  // adds the languages in admin bar
45
  // FIXME: OK for WP 3.2 and newer (the admin bar is not displayed on admin side for WP 3.1)
46
  add_action('admin_bar_menu', array(&$this, 'admin_bar_menu'), 100); // 100 determines the position
49
  // adds the link to the languages panel in the wordpress admin menu
50
  function add_menus() {
51
  add_submenu_page('options-general.php', __('Languages', 'polylang'), __('Languages', 'polylang'), 'manage_options', 'mlang', array(&$this, 'languages_page'));
 
 
 
 
 
52
  }
53
 
54
  // setup js scripts & css styles (only on the relevant pages)
55
  function admin_enqueue_scripts() {
56
  $screen = get_current_screen();
57
+ $suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min';
58
 
59
+ // for each script:
60
+ // 0 => the pages on which to load the script
61
+ // 1 => the scripts it needs to work
62
+ // 2 => 1 if loaded even if languages have not been defined yet, 0 otherwise
63
  $scripts = array(
64
+ 'admin' => array( array('settings_page_mlang'), array('jquery', 'wp-ajax-response', 'postbox'), 1 ),
65
+ 'post' => array( array('post', 'media', 'async-upload', 'edit'), array('jquery', 'wp-ajax-response'), 0 ),
66
+ 'term' => array( array('edit-tags'), array('jquery', 'wp-ajax-response'), 0 ),
67
+ 'user' => array( array('profile', 'user-edit'), array('jquery'), 0 ),
68
  );
69
 
70
  foreach ($scripts as $script => $v)
71
+ if (in_array($screen->base, $v[0]) && ($v[2] || $this->get_languages_list()))
72
+ wp_enqueue_script('pll_'.$script, POLYLANG_URL .'/js/'.$script.$suffix.'.js', $v[1], POLYLANG_VERSION);
73
 
74
  if (in_array($screen->base, array('settings_page_mlang', 'post', 'edit-tags', 'edit', 'upload', 'media')))
75
+ wp_enqueue_style('polylang_admin', POLYLANG_URL .'/css/admin'.$suffix.'.css', array(), POLYLANG_VERSION);
76
  }
77
 
78
  // downloads mofiles
146
  // returns options available for the language switcher (menu or widget)
147
  // FIXME do not include the dropdown in menu yet since I need to work on js
148
  function get_switcher_options($type = 'widget', $key ='string') {
149
+ $options = array(
150
  'show_names' => array('string' => __('Displays language names', 'polylang'), 'default' => 1),
151
  'show_flags' => array('string' => __('Displays flags', 'polylang'), 'default' => 0),
152
  'force_home' => array('string' => __('Forces link to front page', 'polylang'), 'default' => 0),
include/admin-filters.php CHANGED
@@ -2,7 +2,6 @@
2
 
3
  // all modifications of the WordPress admin ui
4
  class Polylang_Admin_Filters extends Polylang_Admin_Base {
5
-
6
  function __construct() {
7
  parent::__construct();
8
 
@@ -264,6 +263,8 @@ class Polylang_Admin_Filters extends Polylang_Admin_Base {
264
  $post_type = get_post_type($post_ID);
265
  $lang = $this->get_language($_POST['lang']);
266
 
 
 
267
  ob_start();
268
  if ($lang)
269
  include(PLL_INC.'/post-translations.php');
@@ -392,7 +393,6 @@ class Polylang_Admin_Filters extends Polylang_Admin_Base {
392
 
393
  // copy or synchronize terms and metas
394
  function copy_post_metas($from, $to, $lang, $sync = false) {
395
-
396
  // copy or synchronize terms
397
  foreach ($this->taxonomies as $tax) {
398
  $newterms = array();
@@ -449,7 +449,7 @@ class Polylang_Admin_Filters extends Polylang_Admin_Base {
449
 
450
  // save language
451
  if (isset($_REQUEST['post_lang_choice'])) {
452
- if ($this->get_post_language($post_id)->slug != $_REQUEST['post_lang_choice'])
453
  $this->delete_translation('post', $post_id); // in case the language is modified using inline edit
454
  $this->set_post_language($post_id, $_REQUEST['post_lang_choice']);
455
  }
@@ -1017,9 +1017,8 @@ class Polylang_Admin_Filters extends Polylang_Admin_Base {
1017
 
1018
  // returns either the user preferred language or the default language
1019
  function get_default_language() {
1020
- return apply_filters('pll_get_default_language', ($lg = get_user_meta(get_current_user_id(), 'pll_filter_content', true)) ?
1021
- $this->get_language($lg) :
1022
- $this->get_language($this->options['default_lang']));
1023
  }
1024
 
1025
  } // class Polylang_Admin_Filters
2
 
3
  // all modifications of the WordPress admin ui
4
  class Polylang_Admin_Filters extends Polylang_Admin_Base {
 
5
  function __construct() {
6
  parent::__construct();
7
 
263
  $post_type = get_post_type($post_ID);
264
  $lang = $this->get_language($_POST['lang']);
265
 
266
+ $this->set_post_language($post_ID, $lang); // save language, useful to set the language when uploading media from post
267
+
268
  ob_start();
269
  if ($lang)
270
  include(PLL_INC.'/post-translations.php');
393
 
394
  // copy or synchronize terms and metas
395
  function copy_post_metas($from, $to, $lang, $sync = false) {
 
396
  // copy or synchronize terms
397
  foreach ($this->taxonomies as $tax) {
398
  $newterms = array();
449
 
450
  // save language
451
  if (isset($_REQUEST['post_lang_choice'])) {
452
+ if (($lang = $this->get_post_language($post_id)) && $lang->slug != $_REQUEST['post_lang_choice'])
453
  $this->delete_translation('post', $post_id); // in case the language is modified using inline edit
454
  $this->set_post_language($post_id, $_REQUEST['post_lang_choice']);
455
  }
1017
 
1018
  // returns either the user preferred language or the default language
1019
  function get_default_language() {
1020
+ $default_language = $this->get_language(($lg = get_user_meta(get_current_user_id(), 'pll_filter_content', true)) ? $lg : $this->options['default_lang']);
1021
+ return apply_filters('pll_get_default_language', $default_language);
 
1022
  }
1023
 
1024
  } // class Polylang_Admin_Filters
include/admin.php CHANGED
@@ -7,6 +7,16 @@ class Polylang_Admin extends Polylang_Admin_Base {
7
 
8
  function __construct() {
9
  parent::__construct();
 
 
 
 
 
 
 
 
 
 
10
  }
11
 
12
  // displays the about metabox
@@ -17,12 +27,11 @@ class Polylang_Admin extends Polylang_Admin_Base {
17
  // used to update the translation when a language slug has been modified
18
  function update_translations($type, $ids, $old_slug) {
19
  foreach ($ids as $id) {
20
- $tr = get_metadata($type, $id, '_translations', true);
21
  if ($tr) {
22
- $tr = unserialize($tr);
23
  $tr[$_POST['slug']] = $tr[$old_slug];
24
  unset($tr[$old_slug]);
25
- update_metadata($type, $id, '_translations', serialize($tr));
26
  }
27
  }
28
  }
@@ -30,11 +39,10 @@ class Polylang_Admin extends Polylang_Admin_Base {
30
  // used to delete the translation when a language is deleted
31
  function delete_translations($type, $ids, $old_slug) {
32
  foreach ($ids as $id) {
33
- $tr = get_metadata($type, $id, '_translations', true);
34
  if ($tr) {
35
- $tr = unserialize($tr);
36
  unset($tr[$old_slug]);
37
- update_metadata($type, $id, '_translations', serialize($tr));
38
  }
39
  }
40
  }
@@ -133,9 +141,9 @@ class Polylang_Admin extends Polylang_Admin_Base {
133
  else
134
  unset($options['default_lang']);
135
  update_option('polylang', $options);
136
-
137
- flush_rewrite_rules(); // refresh rewrite rules
138
  }
 
 
139
  }
140
  wp_redirect('admin.php?page=mlang'); // to refresh the page (possible thanks to the $_GET['noheader']=true)
141
  exit;
7
 
8
  function __construct() {
9
  parent::__construct();
10
+
11
+ // adds the about box the languages admin panel
12
+ add_action('admin_init', array(&$this, 'admin_init'));
13
+ }
14
+
15
+ // adds the about box the languages admin panel
16
+ function admin_init() {
17
+ // test of $_GET['tab'] avoids displaying the automatically generated screen options on other tabs
18
+ if (PLL_DISPLAY_ABOUT && (!isset($_GET['tab']) || $_GET['tab'] == 'lang'))
19
+ add_meta_box('pll_about_box', __('About Polylang', 'polylang'), array(&$this, 'about'), 'settings_page_mlang', 'normal', 'high');
20
  }
21
 
22
  // displays the about metabox
27
  // used to update the translation when a language slug has been modified
28
  function update_translations($type, $ids, $old_slug) {
29
  foreach ($ids as $id) {
30
+ $tr = $this->get_translations($type, $id);
31
  if ($tr) {
 
32
  $tr[$_POST['slug']] = $tr[$old_slug];
33
  unset($tr[$old_slug]);
34
+ update_metadata($type, (int) $id, '_translations', $tr);
35
  }
36
  }
37
  }
39
  // used to delete the translation when a language is deleted
40
  function delete_translations($type, $ids, $old_slug) {
41
  foreach ($ids as $id) {
42
+ $tr = $this->get_translations($type, $id);
43
  if ($tr) {
 
44
  unset($tr[$old_slug]);
45
+ update_metadata($type, (int) $id, '_translations', $tr);
46
  }
47
  }
48
  }
141
  else
142
  unset($options['default_lang']);
143
  update_option('polylang', $options);
 
 
144
  }
145
+
146
+ flush_rewrite_rules(); // refresh rewrite rules
147
  }
148
  wp_redirect('admin.php?page=mlang'); // to refresh the page (possible thanks to the $_GET['noheader']=true)
149
  exit;
include/base.php CHANGED
@@ -8,6 +8,10 @@ abstract class Polylang_Base {
8
  protected $post_types; // post types to filter by language
9
  protected $taxonomies; // taxonomies to filter by language
10
 
 
 
 
 
11
  function __construct() {
12
  // init options often needed
13
  $this->options = get_option('polylang');
@@ -18,15 +22,20 @@ abstract class Polylang_Base {
18
 
19
  // init post types and taxonomies to filter by language
20
  function add_post_types_taxonomies() {
21
- $this->post_types = apply_filters('pll_get_post_types', array_merge(PLL_MEDIA_SUPPORT ? array('attachment' => 'attachment') : array(), get_post_types(array('show_ui' => true))));
 
22
  $this->taxonomies = apply_filters('pll_get_taxonomies', get_taxonomies(array('show_ui'=>true)));
23
  }
24
 
25
  // returns the list of available languages
26
  function get_languages_list($args = array()) {
 
 
 
 
27
  $defaults = array('hide_empty' => false, 'orderby'=> 'term_group');
28
- $args = wp_parse_args($args, $defaults);
29
- return get_terms('language', $args);
30
  }
31
 
32
  // retrieves the dropdown list of the languages
@@ -155,8 +164,8 @@ abstract class Polylang_Base {
155
 
156
  // adds language information to a link when using pretty permalinks
157
  function add_language_to_link($url, $lang) {
158
- if (!isset($lang) || !$lang) // FIXME avoid notice when adding a page to a custom menu
159
- return false;
160
 
161
  global $wp_rewrite;
162
  if ($wp_rewrite->using_permalinks()) {
@@ -185,13 +194,20 @@ abstract class Polylang_Base {
185
 
186
  // modifies post & page links
187
  function post_link($link, $post) {
188
- return $this->add_language_to_link($link, $this->get_post_language('_get_page_link' == current_filter() ? $post : $post->ID));
 
 
 
 
189
  }
190
 
191
  // modifies term link
192
  function term_link($link, $term, $tax) {
193
- return $tax == 'post_format' || ($this->options['force_lang'] && $GLOBALS['wp_rewrite']->using_permalinks() && $tax != 'language') ?
194
- $this->add_language_to_link($link, $this->get_term_language($term->term_id)) : $link;
 
 
 
195
  }
196
 
197
  // returns the html link to the flag if exists
8
  protected $post_types; // post types to filter by language
9
  protected $taxonomies; // taxonomies to filter by language
10
 
11
+ // used to cache results
12
+ private $languages_list = array();
13
+ private $links = array();
14
+
15
  function __construct() {
16
  // init options often needed
17
  $this->options = get_option('polylang');
22
 
23
  // init post types and taxonomies to filter by language
24
  function add_post_types_taxonomies() {
25
+ $post_types = array_merge(PLL_MEDIA_SUPPORT ? array('attachment' => 'attachment') : array(), get_post_types(array('show_ui' => true)));
26
+ $this->post_types = apply_filters('pll_get_post_types', $post_types);
27
  $this->taxonomies = apply_filters('pll_get_taxonomies', get_taxonomies(array('show_ui'=>true)));
28
  }
29
 
30
  // returns the list of available languages
31
  function get_languages_list($args = array()) {
32
+ // although get_terms is cached, it is efficient to add our own cache
33
+ if (isset($this->languages_list[$cache_key = md5(serialize($args))]))
34
+ return $this->languages_list[$cache_key];
35
+
36
  $defaults = array('hide_empty' => false, 'orderby'=> 'term_group');
37
+ $args = wp_parse_args($args, $defaults);
38
+ return $this->languages_list[$cache_key] = get_terms('language', $args);
39
  }
40
 
41
  // retrieves the dropdown list of the languages
164
 
165
  // adds language information to a link when using pretty permalinks
166
  function add_language_to_link($url, $lang) {
167
+ if (!isset($lang) || !$lang)
168
+ return $url;
169
 
170
  global $wp_rewrite;
171
  if ($wp_rewrite->using_permalinks()) {
194
 
195
  // modifies post & page links
196
  function post_link($link, $post) {
197
+ if (isset($this->links[$link]))
198
+ return $this->links[$link];
199
+
200
+ return $this->links[$link] = ('post_type_link' == current_filter() && !in_array($post->post_type, $this->post_types)) ?
201
+ $link : $this->add_language_to_link($link, $this->get_post_language('_get_page_link' == current_filter() ? $post : $post->ID));
202
  }
203
 
204
  // modifies term link
205
  function term_link($link, $term, $tax) {
206
+ if (isset($this->links[$link]))
207
+ return $this->links[$link];
208
+
209
+ $ok = $tax == 'post_format' || ($this->options['force_lang'] && $GLOBALS['wp_rewrite']->using_permalinks() && in_array($tax, $this->taxonomies));
210
+ return $this->links[$link] = $ok ? $this->add_language_to_link($link, $this->get_term_language($term->term_id)) : $link;
211
  }
212
 
213
  // returns the html link to the flag if exists
include/core.php CHANGED
@@ -12,6 +12,11 @@ class Polylang_Core extends Polylang_base {
12
  private $page_for_posts;
13
  private $page_on_front;
14
 
 
 
 
 
 
15
  function __construct() {
16
  parent::__construct();
17
 
@@ -233,6 +238,9 @@ class Polylang_Core extends Polylang_base {
233
  preg_match($languages, trailingslashit($_SERVER['REQUEST_URI']), $matches);
234
 
235
  // home is resquested
 
 
 
236
  if (str_replace('www.', '', home_url('/')) == trailingslashit((is_ssl() ? 'https://' : 'http://').str_replace('www.', '', $_SERVER['HTTP_HOST']).str_replace(array('index.php', '?'.$_SERVER['QUERY_STRING']), array('', ''), $_SERVER['REQUEST_URI'])))
237
  $this->home_requested();
238
 
@@ -308,14 +316,15 @@ class Polylang_Core extends Polylang_base {
308
  // set all our language filters and actions
309
  $this->add_language_filters();
310
 
311
- if (!($this->options['force_lang'] && $wp_rewrite->using_permalinks() && PLL_LANG_EARLY)) {
312
  // now we can load text domains with the right language
313
  $new_locale = get_locale();
314
  foreach ($this->list_textdomains as $textdomain)
315
  load_textdomain( $textdomain['domain'], str_replace($this->default_locale, $new_locale, $textdomain['mo']));
316
 
317
- // reinitializes wp_locale for weekdays and months, as well as for text direction
318
- $wp_locale->init();
 
319
  $wp_locale->text_direction = get_metadata('term', $this->curlang->term_id, '_rtl', true) ? 'rtl' : 'ltr';
320
 
321
  // translate labels of post types and taxonomies
@@ -519,18 +528,27 @@ class Polylang_Core extends Polylang_base {
519
 
520
  // modifies the page link in case the front page is not in the default language
521
  function page_link($link, $id) {
522
- if ($this->options['redirect_lang'] && $this->page_on_front && $id == $this->get_post($this->page_on_front, $lang = $this->get_post_language($id)))
523
- return $this->options['hide_default'] && $lang->slug == $this->options['default_lang'] ? trailingslashit($this->home) : get_term_link($lang, 'language');
 
 
 
 
 
524
 
525
- if ($this->page_on_front && $this->options['hide_default'] && $id == $this->get_post($this->page_on_front, $this->options['default_lang']))
526
- return trailingslashit($this->home);
 
 
 
 
527
 
528
  return _get_page_link($id);
529
  }
530
 
531
  // prevents redirection of the homepage when using page on front
532
  function redirect_canonical($redirect_url, $requested_url) {
533
- return $requested_url == home_url('/') || $requested_url == $this->page_link('', get_option('page_on_front')) ? false : $redirect_url;
534
  }
535
 
536
  // adds some javascript workaround knowing it's not perfect...
@@ -628,6 +646,9 @@ class Polylang_Core extends Polylang_base {
628
 
629
  // returns the url of the translation (if exists) of the current page
630
  function get_translation_url($language) {
 
 
 
631
  global $wp_query, $wp_rewrite;
632
  $qvars = $wp_query->query;
633
  $hide = $this->options['default_lang'] == $language->slug && $this->options['hide_default'];
@@ -705,7 +726,7 @@ class Polylang_Core extends Polylang_base {
705
  elseif (is_home() || is_tax('language') )
706
  $url = $this->get_home_url($language);
707
 
708
- return isset($url) ? $url : null;
709
  }
710
 
711
  // filters the nav menus according to the current language when called from get_nav_menu_locations()
@@ -763,14 +784,14 @@ class Polylang_Core extends Polylang_base {
763
 
764
  // translates biography
765
  function get_user_metadata($null, $id, $meta_key, $single) {
766
- if ($meta_key == 'description')
767
- return get_user_meta($id, 'description_'.$this->curlang->slug, true);
768
- return $null;
769
  }
770
 
771
  // translates page for posts and page on front
772
- function translate_page($value) {
773
- return isset($this->curlang) && $value ? $this->get_post($value, $this->curlang) : $value;
 
 
774
  }
775
 
776
  // filters the home url to get the right language
@@ -779,7 +800,7 @@ class Polylang_Core extends Polylang_base {
779
  return $url;
780
 
781
  $theme = get_theme_root();
782
- foreach (debug_backtrace() as $trace) {
783
  // search form
784
  if (isset($trace['file']) && strpos($trace['file'], 'searchform.php'))
785
  return $GLOBALS['wp_rewrite']->using_permalinks() ? $this->get_home_url($this->curlang, true) : $url;
@@ -801,15 +822,18 @@ class Polylang_Core extends Polylang_base {
801
  if ($language == '')
802
  $language = $this->curlang;
803
 
 
 
 
804
  if ($this->options['default_lang'] == $language->slug && $this->options['hide_default'])
805
- return trailingslashit($this->home);
806
 
807
  // a static page is used as front page : /!\ don't use get_page_link to avoid infinite loop
808
  // don't use this for search form
809
  if (!$is_search && $this->page_on_front && $id = $this->get_post($this->page_on_front, $language))
810
- return $this->page_link('', $id);
811
 
812
- return get_term_link($language, 'language');
813
  }
814
 
815
  // displays (or returns) the language switcher
12
  private $page_for_posts;
13
  private $page_on_front;
14
 
15
+ // used to cache results
16
+ private $posts = array();
17
+ private $translation_url = array();
18
+ private $home_urls = array();
19
+
20
  function __construct() {
21
  parent::__construct();
22
 
238
  preg_match($languages, trailingslashit($_SERVER['REQUEST_URI']), $matches);
239
 
240
  // home is resquested
241
+ // some PHP setups turn requests for / into /index.php in REQUEST_URI
242
+ // thanks to Gonçalo Peres for pointing out the issue with queries unknown to WP
243
+ // http://wordpress.org/support/topic/plugin-polylang-language-homepage-redirection-problem-and-solution-but-incomplete?replies=4#post-2729566
244
  if (str_replace('www.', '', home_url('/')) == trailingslashit((is_ssl() ? 'https://' : 'http://').str_replace('www.', '', $_SERVER['HTTP_HOST']).str_replace(array('index.php', '?'.$_SERVER['QUERY_STRING']), array('', ''), $_SERVER['REQUEST_URI'])))
245
  $this->home_requested();
246
 
316
  // set all our language filters and actions
317
  $this->add_language_filters();
318
 
319
+ if (!($this->options['force_lang'] && $wp_rewrite->using_permalinks() && PLL_LANG_EARLY) && $this->curlang->description != 'en_US') {
320
  // now we can load text domains with the right language
321
  $new_locale = get_locale();
322
  foreach ($this->list_textdomains as $textdomain)
323
  load_textdomain( $textdomain['domain'], str_replace($this->default_locale, $new_locale, $textdomain['mo']));
324
 
325
+ // reinitializes wp_locale for weekdays and months, as well as for text direction
326
+ unset($wp_locale);
327
+ $wp_locale = new WP_Locale();
328
  $wp_locale->text_direction = get_metadata('term', $this->curlang->term_id, '_rtl', true) ? 'rtl' : 'ltr';
329
 
330
  // translate labels of post types and taxonomies
528
 
529
  // modifies the page link in case the front page is not in the default language
530
  function page_link($link, $id) {
531
+ if ($this->options['redirect_lang'] && $this->page_on_front) {
532
+ $lang = $lang = $this->get_post_language($id);
533
+ if (!isset($this->posts[$lang->slug][$this->page_on_front]))
534
+ $this->posts[$lang->slug][$this->page_on_front] = $this->get_post($this->page_on_front, $lang);
535
+ if ($id == $this->posts[$lang->slug][$this->page_on_front])
536
+ return $this->options['hide_default'] && $lang->slug == $this->options['default_lang'] ? trailingslashit($this->home) : get_term_link($lang, 'language');
537
+ }
538
 
539
+ if ($this->page_on_front && $this->options['hide_default']) {
540
+ if (!isset($this->posts[$this->options['default_lang']][$this->page_on_front]))
541
+ $this->posts[$this->options['default_lang']][$this->page_on_front] = $this->get_post($this->page_on_front, $this->options['default_lang']);
542
+ if ($id == $this->posts[$this->options['default_lang']][$this->page_on_front])
543
+ return trailingslashit($this->home);
544
+ }
545
 
546
  return _get_page_link($id);
547
  }
548
 
549
  // prevents redirection of the homepage when using page on front
550
  function redirect_canonical($redirect_url, $requested_url) {
551
+ return $requested_url == home_url('/') || strpos($requested_url, $this->page_link('', get_option('page_on_front'))) !== false ? false : $redirect_url;
552
  }
553
 
554
  // adds some javascript workaround knowing it's not perfect...
646
 
647
  // returns the url of the translation (if exists) of the current page
648
  function get_translation_url($language) {
649
+ if (isset($this->translation_url[$language->slug]))
650
+ return $this->translation_url[$language->slug];
651
+
652
  global $wp_query, $wp_rewrite;
653
  $qvars = $wp_query->query;
654
  $hide = $this->options['default_lang'] == $language->slug && $this->options['hide_default'];
726
  elseif (is_home() || is_tax('language') )
727
  $url = $this->get_home_url($language);
728
 
729
+ return $this->translation_url[$language->slug] = (isset($url) ? $url : null);
730
  }
731
 
732
  // filters the nav menus according to the current language when called from get_nav_menu_locations()
784
 
785
  // translates biography
786
  function get_user_metadata($null, $id, $meta_key, $single) {
787
+ return $meta_key == 'description' ? get_user_meta($id, 'description_'.$this->curlang->slug, true) : $null;
 
 
788
  }
789
 
790
  // translates page for posts and page on front
791
+ function translate_page($val) {
792
+ // returns the current page if there is no translation to avoid ugly notices
793
+ // the fonction is often called so let's store the result
794
+ return isset($this->curlang) && $val && (isset($this->posts[$val]) || $this->posts[$val] = $this->get_post($val, $this->curlang)) ? $this->posts[$val] : $val;
795
  }
796
 
797
  // filters the home url to get the right language
800
  return $url;
801
 
802
  $theme = get_theme_root();
803
+ foreach (debug_backtrace(/*!DEBUG_BACKTRACE_PROVIDE_OBJECT|DEBUG_BACKTRACE_IGNORE_ARGS*/) as $trace) {
804
  // search form
805
  if (isset($trace['file']) && strpos($trace['file'], 'searchform.php'))
806
  return $GLOBALS['wp_rewrite']->using_permalinks() ? $this->get_home_url($this->curlang, true) : $url;
822
  if ($language == '')
823
  $language = $this->curlang;
824
 
825
+ if (isset($this->home_urls[$language->slug]))
826
+ return $this->home_urls[$language->slug];
827
+
828
  if ($this->options['default_lang'] == $language->slug && $this->options['hide_default'])
829
+ return $this->home_urls[$language->slug] = trailingslashit($this->home);
830
 
831
  // a static page is used as front page : /!\ don't use get_page_link to avoid infinite loop
832
  // don't use this for search form
833
  if (!$is_search && $this->page_on_front && $id = $this->get_post($this->page_on_front, $language))
834
+ return $this->home_urls[$language->slug] = $this->page_link('', $id);
835
 
836
+ return $this->home_urls[$language->slug] = get_term_link($language, 'language');
837
  }
838
 
839
  // displays (or returns) the language switcher
include/list-table.php CHANGED
@@ -7,30 +7,29 @@ if(!class_exists('WP_List_Table')){
7
  }
8
 
9
  class Polylang_List_Table extends WP_List_Table {
10
- function __construct() {
11
- parent::__construct( array(
12
  'singular' => __('Language','polylang'),
13
  'plural' => __('Languages','polylang'),
14
  'ajax'=> false)
15
- );
16
  }
17
 
18
- function column_default( $item, $column_name){
19
  return $item[$column_name];
20
  }
21
 
22
- function column_name($item){
23
  $edit_link = esc_url(admin_url('admin.php?page=mlang&action=edit&lang='.$item['term_id']));
24
  $delete_link = wp_nonce_url('?page=mlang&action=delete&noheader=true&lang=' . $item['term_id'], 'delete-lang');
25
  $actions = array(
26
  'edit' => '<a href="' . $edit_link . '">' . __('Edit','polylang') . '</a>',
27
  'delete' => '<a href="' . $delete_link .'">' . __('Delete','polylang') .'</a>'
28
  );
29
-
30
  return $item['name'].$this->row_actions($actions);
31
  }
32
 
33
- function column_cb($item){
34
  return sprintf(
35
  '<input type="checkbox" name="%1$s[]" value="%2$s" />',
36
  /*$1%s*/ esc_attr($this->_args['singular']),
@@ -38,10 +37,10 @@ class Polylang_List_Table extends WP_List_Table {
38
  );
39
  }
40
 
41
- function get_columns(){
42
  $columns = array(
43
  // FIXME checkboxes are useles for now
44
- // 'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
45
  'name' => __('Full name', 'polylang'),
46
  'description' => __('Locale', 'polylang'),
47
  'slug' => __('Code', 'polylang'),
@@ -54,11 +53,11 @@ class Polylang_List_Table extends WP_List_Table {
54
 
55
  function get_sortable_columns() {
56
  $sortable_columns = array(
57
- 'name' => array('name',true), // sorted by name by default
58
- 'description' => array('description',false),
59
- 'slug' => array('slug',false),
60
- 'term_group' => array('term_group',false),
61
- 'count' => array('count',false)
62
  );
63
  return $sortable_columns;
64
  }
@@ -66,15 +65,14 @@ class Polylang_List_Table extends WP_List_Table {
66
  /*
67
  function get_bulk_actions() {
68
  return array('delete' => 'Delete');
69
- }
70
- */
71
-
72
  function prepare_items($data = array()) {
73
  $per_page = 10; // 10 languages per page
74
  $columns = $this->get_columns();
75
  $hidden = array();
76
  $sortable = $this->get_sortable_columns();
77
-
78
  $this->_column_headers = array($columns, $hidden, $sortable);
79
 
80
  function usort_reorder($a,$b){
@@ -84,34 +82,34 @@ class Polylang_List_Table extends WP_List_Table {
84
  return ($order==='asc') ? $result : -$result; // send final sort direction to usort
85
  }
86
  usort($data, 'usort_reorder');
87
-
88
  $current_page = $this->get_pagenum();
89
  $total_items = count($data);
90
  $data = array_slice($data,(($current_page-1)*$per_page),$per_page);
91
  $this->items = $data;
92
 
93
- $this->set_pagination_args( array(
94
  'total_items' => $total_items, //WE have to calculate the total number of items
95
  'per_page' => $per_page, //WE have to determine how many items to show on a page
96
  'total_pages' => ceil($total_items/$per_page) //WE have to calculate the total number of pages
97
  ) );
98
- }
99
- }
100
 
101
  class Polylang_String_Table extends WP_List_Table {
102
- function __construct() {
103
- parent::__construct( array(
104
  'singular' => __('Strings translation','polylang'),
105
  'plural' => __('Strings translations','polylang'),
106
  'ajax'=> false)
107
- );
108
  }
109
 
110
- function column_default($item, $column_name){
111
  return $item[$column_name];
112
  }
113
 
114
- function column_translations($item){
115
  $out = '';
116
  foreach($item['translations'] as $key=>$translation) {
117
  $input_type = $item['multiline'] ?
@@ -126,7 +124,7 @@ class Polylang_String_Table extends WP_List_Table {
126
  return $out;
127
  }
128
 
129
- function get_columns(){
130
  return array(
131
  'name' => __('Name', 'polylang'),
132
  'string' => __('String', 'polylang'),
@@ -136,24 +134,22 @@ class Polylang_String_Table extends WP_List_Table {
136
 
137
  function get_sortable_columns() {
138
  return array(
139
- 'name' => array('name',false),
140
- 'string' => array('string',false),
141
  );
142
  }
143
-
144
  function prepare_items($data = array()) {
145
  $per_page = 10; // 10 strings per page
146
  $columns = $this->get_columns();
147
  $hidden = array();
148
  $sortable = $this->get_sortable_columns();
149
-
150
  $this->_column_headers = array($columns, $hidden, $sortable);
151
 
152
  function usort_reorder($a,$b){
153
  $orderby = $_REQUEST['orderby'];
154
  $order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc'; // if no order, default to asc
155
  $result = strcmp($a[$orderby], $b[$orderby]); // determine sort order
156
-
157
  return ($order==='asc') ? $result : -$result; // send final sort direction to usort
158
  }
159
  if (!empty($_REQUEST['orderby'])) // no sort by default
@@ -169,6 +165,6 @@ class Polylang_String_Table extends WP_List_Table {
169
  'per_page' => $per_page,
170
  'total_pages' => ceil($total_items/$per_page)
171
  ) );
172
- }
173
- }
174
  ?>
7
  }
8
 
9
  class Polylang_List_Table extends WP_List_Table {
10
+ function __construct() {
11
+ parent::__construct(array(
12
  'singular' => __('Language','polylang'),
13
  'plural' => __('Languages','polylang'),
14
  'ajax'=> false)
15
+ );
16
  }
17
 
18
+ function column_default($item, $column_name) {
19
  return $item[$column_name];
20
  }
21
 
22
+ function column_name($item) {
23
  $edit_link = esc_url(admin_url('admin.php?page=mlang&amp;action=edit&amp;lang='.$item['term_id']));
24
  $delete_link = wp_nonce_url('?page=mlang&amp;action=delete&amp;noheader=true&amp;lang=' . $item['term_id'], 'delete-lang');
25
  $actions = array(
26
  'edit' => '<a href="' . $edit_link . '">' . __('Edit','polylang') . '</a>',
27
  'delete' => '<a href="' . $delete_link .'">' . __('Delete','polylang') .'</a>'
28
  );
 
29
  return $item['name'].$this->row_actions($actions);
30
  }
31
 
32
+ function column_cb($item) {
33
  return sprintf(
34
  '<input type="checkbox" name="%1$s[]" value="%2$s" />',
35
  /*$1%s*/ esc_attr($this->_args['singular']),
37
  );
38
  }
39
 
40
+ function get_columns() {
41
  $columns = array(
42
  // FIXME checkboxes are useles for now
43
+ // 'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
44
  'name' => __('Full name', 'polylang'),
45
  'description' => __('Locale', 'polylang'),
46
  'slug' => __('Code', 'polylang'),
53
 
54
  function get_sortable_columns() {
55
  $sortable_columns = array(
56
+ 'name' => array('name', true), // sorted by name by default
57
+ 'description' => array('description', false),
58
+ 'slug' => array('slug', false),
59
+ 'term_group' => array('term_group', false),
60
+ 'count' => array('count', false)
61
  );
62
  return $sortable_columns;
63
  }
65
  /*
66
  function get_bulk_actions() {
67
  return array('delete' => 'Delete');
68
+ }
69
+ */
70
+
71
  function prepare_items($data = array()) {
72
  $per_page = 10; // 10 languages per page
73
  $columns = $this->get_columns();
74
  $hidden = array();
75
  $sortable = $this->get_sortable_columns();
 
76
  $this->_column_headers = array($columns, $hidden, $sortable);
77
 
78
  function usort_reorder($a,$b){
82
  return ($order==='asc') ? $result : -$result; // send final sort direction to usort
83
  }
84
  usort($data, 'usort_reorder');
85
+
86
  $current_page = $this->get_pagenum();
87
  $total_items = count($data);
88
  $data = array_slice($data,(($current_page-1)*$per_page),$per_page);
89
  $this->items = $data;
90
 
91
+ $this->set_pagination_args(array(
92
  'total_items' => $total_items, //WE have to calculate the total number of items
93
  'per_page' => $per_page, //WE have to determine how many items to show on a page
94
  'total_pages' => ceil($total_items/$per_page) //WE have to calculate the total number of pages
95
  ) );
96
+ }
97
+ } // class Polylang_List_Table
98
 
99
  class Polylang_String_Table extends WP_List_Table {
100
+ function __construct() {
101
+ parent::__construct(array(
102
  'singular' => __('Strings translation','polylang'),
103
  'plural' => __('Strings translations','polylang'),
104
  'ajax'=> false)
105
+ );
106
  }
107
 
108
+ function column_default($item, $column_name) {
109
  return $item[$column_name];
110
  }
111
 
112
+ function column_translations($item) {
113
  $out = '';
114
  foreach($item['translations'] as $key=>$translation) {
115
  $input_type = $item['multiline'] ?
124
  return $out;
125
  }
126
 
127
+ function get_columns() {
128
  return array(
129
  'name' => __('Name', 'polylang'),
130
  'string' => __('String', 'polylang'),
134
 
135
  function get_sortable_columns() {
136
  return array(
137
+ 'name' => array('name', false),
138
+ 'string' => array('string', false),
139
  );
140
  }
141
+
142
  function prepare_items($data = array()) {
143
  $per_page = 10; // 10 strings per page
144
  $columns = $this->get_columns();
145
  $hidden = array();
146
  $sortable = $this->get_sortable_columns();
 
147
  $this->_column_headers = array($columns, $hidden, $sortable);
148
 
149
  function usort_reorder($a,$b){
150
  $orderby = $_REQUEST['orderby'];
151
  $order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc'; // if no order, default to asc
152
  $result = strcmp($a[$orderby], $b[$orderby]); // determine sort order
 
153
  return ($order==='asc') ? $result : -$result; // send final sort direction to usort
154
  }
155
  if (!empty($_REQUEST['orderby'])) // no sort by default
165
  'per_page' => $per_page,
166
  'total_pages' => ceil($total_items/$per_page)
167
  ) );
168
+ }
169
+ } // class Polylang_String_Table
170
  ?>
js/admin.dev.js DELETED
@@ -1,12 +0,0 @@
1
- jQuery(document).ready(function($) {
2
- // languages form
3
- // fills the fields based on the language dropdown list choice
4
- $('#lang_list').change(function() {
5
- value = $(this).attr('value').split('-');
6
- selected = $("select option:selected").text().split(' - ');
7
- $('input[name="slug"]').val(value[0]);
8
- $('input[name="description"]').val(value[1]);
9
- $('input[name="rtl"]').val([value[2]]);
10
- $('input[name="name"]').val(selected[0]);
11
- });
12
- });
 
 
 
 
 
 
 
 
 
 
 
 
js/admin.js CHANGED
@@ -1 +1,12 @@
1
- jQuery(document).ready(function(a){a("#lang_list").change(function(){value=a(this).attr("value").split("-");selected=a("select option:selected").text().split(" - ");a('input[name="slug"]').val(value[0]);a('input[name="description"]').val(value[1]);a('input[name="rtl"]').val([value[2]]);a('input[name="name"]').val(selected[0])})})
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($) {
2
+ // languages form
3
+ // fills the fields based on the language dropdown list choice
4
+ $('#lang_list').change(function() {
5
+ value = $(this).attr('value').split('-');
6
+ selected = $("select option:selected").text().split(' - ');
7
+ $('input[name="slug"]').val(value[0]);
8
+ $('input[name="description"]').val(value[1]);
9
+ $('input[name="rtl"]').val([value[2]]);
10
+ $('input[name="name"]').val(selected[0]);
11
+ });
12
+ });
js/admin.min.js ADDED
@@ -0,0 +1 @@
 
1
+ jQuery(document).ready(function(a){a("#lang_list").change(function(){value=a(this).attr("value").split("-");selected=a("select option:selected").text().split(" - ");a('input[name="slug"]').val(value[0]);a('input[name="description"]').val(value[1]);a('input[name="rtl"]').val([value[2]]);a('input[name="name"]').val(selected[0])})})
js/post.dev.js DELETED
@@ -1,260 +0,0 @@
1
- var pll_tagBox;
2
-
3
- // mainly copy paste of WP code
4
- (function($){
5
-
6
- pll_tagBox = {
7
- clean : function(tags) {
8
- return tags.replace(/\s*,\s*/g, ',').replace(/,+/g, ',').replace(/[,\s]+$/, '').replace(/^[,\s]+/, '');
9
- },
10
-
11
- parseTags : function(el) {
12
- var id = el.id, num = id.split('-check-num-')[1], taxbox = $(el).closest('.tagsdiv'), thetags = taxbox.find('.the-tags'), current_tags = thetags.val().split(','), new_tags = [];
13
- delete current_tags[num];
14
-
15
- $.each( current_tags, function(key, val) {
16
- val = $.trim(val);
17
- if ( val ) {
18
- new_tags.push(val);
19
- }
20
- });
21
-
22
- thetags.val( this.clean( new_tags.join(',') ) );
23
-
24
- this.quickClicks(taxbox);
25
- return false;
26
- },
27
-
28
- quickClicks : function(el) {
29
- var thetags = $('.the-tags', el),
30
- tagchecklist = $('.tagchecklist', el),
31
- id = $(el).attr('id'),
32
- current_tags, disabled;
33
-
34
- if ( !thetags.length )
35
- return;
36
-
37
- // FIXME: why this modification ?
38
- // disabled = thetags.prop('disabled'); // 3.3
39
- // disabled = thetags.attr('disabled'); // 3.1
40
- disabled = thetags.attr('disabled');
41
-
42
- current_tags = thetags.val().split(',');
43
- tagchecklist.empty();
44
-
45
- $.each( current_tags, function( key, val ) {
46
- var span, xbutton;
47
-
48
- val = $.trim( val );
49
-
50
- if ( ! val )
51
- return;
52
-
53
- // Create a new span, and ensure the text is properly escaped.
54
- span = $('<span />').text( val );
55
-
56
- // If tags editing isn't disabled, create the X button.
57
- if ( ! disabled ) {
58
- xbutton = $( '<a id="' + id + '-check-num-' + key + '" class="ntdelbutton">X</a>' );
59
- xbutton.click( function(){ pll_tagBox.parseTags(this); });
60
- span.prepend('&nbsp;').prepend( xbutton );
61
- }
62
-
63
- // Append the span to the tag list.
64
- tagchecklist.append( span );
65
- });
66
- },
67
-
68
- flushTags : function(el, a, f) {
69
- a = a || false;
70
- var text, tags = $('.the-tags', el), newtag = $('input.newtag', el), newtags;
71
-
72
- text = a ? $(a).text() : newtag.val();
73
- tagsval = tags.val();
74
- newtags = tagsval ? tagsval + ',' + text : text;
75
-
76
- newtags = this.clean( newtags );
77
- newtags = array_unique_noempty( newtags.split(',') ).join(',');
78
- tags.val(newtags);
79
- this.quickClicks(el);
80
-
81
- if ( !a )
82
- newtag.val('');
83
- if ( 'undefined' == typeof(f) )
84
- newtag.focus();
85
-
86
- return false;
87
- },
88
-
89
- get : function(id, a) {
90
- var tax = id.substr(id.indexOf('-')+1);
91
-
92
- // add the language in the $_POST variable
93
- var data = {
94
- action: 'get-tagcloud',
95
- lang: $('#post_lang_choice').attr('value'),
96
- tax: tax
97
- }
98
-
99
- $.post(ajaxurl, data, function(r, stat) {
100
- if ( 0 == r || 'success' != stat )
101
- r = wpAjax.broken;
102
-
103
- r = $('<p id="tagcloud-'+tax+'" class="the-tagcloud">'+r+'</p>');
104
- $('a', r).click(function(){
105
- pll_tagBox.flushTags( $(this).closest('.inside').children('.tagsdiv'), this);
106
- return false;
107
- });
108
-
109
- // add an if else condition to allow modifying the tags outputed when switching the language
110
- if (a == 1)
111
- $('#'+id).after(r);
112
- else {
113
- v = $('.the-tagcloud').css('display');
114
- $('.the-tagcloud').replaceWith(r);
115
- $('.the-tagcloud').css('display', v);
116
- }
117
- });
118
- },
119
-
120
- suggest : function() {
121
- ajaxtag = $('div.ajaxtag');
122
- // add the unbind function to allow calling the function when the language is modified
123
- $('input.newtag', ajaxtag).unbind().blur(function() {
124
- if ( this.value == '' )
125
- $(this).parent().siblings('.taghint').css('visibility', '');
126
- }).focus(function(){
127
- $(this).parent().siblings('.taghint').css('visibility', 'hidden');
128
- }).keyup(function(e){
129
- if ( 13 == e.which ) {
130
- pll_tagBox.flushTags( $(this).closest('.tagsdiv') );
131
- return false;
132
- }
133
- }).keypress(function(e){
134
- if ( 13 == e.which ) {
135
- e.preventDefault();
136
- return false;
137
- }
138
- }).each(function(){
139
- // add the language in the $_GET variable
140
- var lang = $('#post_lang_choice').attr('value');
141
- var tax = $(this).closest('div.tagsdiv').attr('id');
142
- $(this).suggest( ajaxurl + '?action=polylang-ajax-tag-search&lang=' + lang + '&tax=' + tax, { delay: 500, minchars: 2, multiple: true, multipleSep: "," } );
143
- });
144
- },
145
-
146
- init : function() {
147
- var t = this, ajaxtag = $('div.ajaxtag');
148
-
149
- $('.tagsdiv').each( function() {
150
- pll_tagBox.quickClicks(this);
151
- });
152
-
153
- $('input.tagadd', ajaxtag).click(function(){
154
- t.flushTags( $(this).closest('.tagsdiv') );
155
- });
156
-
157
- $('div.taghint', ajaxtag).click(function(){
158
- $(this).css('visibility', 'hidden').parent().siblings('.newtag').focus();
159
- });
160
-
161
- pll_tagBox.suggest();
162
-
163
- // save tags on post save/publish
164
- $('#post').submit(function(){
165
- $('div.tagsdiv').each( function() {
166
- pll_tagBox.flushTags(this, false, 1);
167
- });
168
- });
169
-
170
- // tag cloud
171
- $('a.tagcloud-link').click(function(){
172
- pll_tagBox.get( $(this).attr('id'), 1 );
173
- $(this).unbind().click(function(){
174
- $(this).siblings('.the-tagcloud').toggle();
175
- return false;
176
- });
177
- return false;
178
- });
179
- }
180
- };
181
-
182
- })(jQuery);
183
-
184
- jQuery(document).ready(function($) {
185
- // collect taxonomies - code partly copied from WordPress
186
- var taxonomies = new Array();
187
- $('.categorydiv').each( function(){
188
- var this_id = $(this).attr('id'), taxonomyParts, taxonomy;
189
-
190
- taxonomyParts = this_id.split('-');
191
- taxonomyParts.shift();
192
- taxonomy = taxonomyParts.join('-');
193
- taxonomies.push(taxonomy); // store the taxonomy for future use
194
- });
195
-
196
- // ajax for changing the post's language in the languages metabox
197
- $('#post_lang_choice').change( function() {
198
- var data = {
199
- action: 'post_lang_choice',
200
- lang: $(this).attr('value'),
201
- taxonomies: taxonomies,
202
- post_id: $('#post_ID').attr('value')
203
- }
204
-
205
- $.post(ajaxurl, data , function(response) {
206
- var res = wpAjax.parseAjaxResponse(response, 'ajax-response');
207
- $.each(res.responses, function() {
208
- switch (this.what) {
209
- case 'translations': // translations fields
210
- $('#post-translations').html(this.data);
211
- break;
212
- case 'taxonomy': // categories metabox for posts
213
- var tax = this.data;
214
- $('#' + tax + 'checklist').html(this.supplemental.all);
215
- $('#' + tax + 'checklist-pop').html(this.supplemental.populars);
216
- $('#new' + tax + '_parent').replaceWith(this.supplemental.dropdown);
217
- $('#' + tax + '-lang').val($('#post_lang_choice').attr('value')); // hidden field
218
- break;
219
- case 'pages': // parent dropdown list for pages
220
- $('#parent_id').replaceWith(this.data);
221
- break;
222
- default:
223
- break;
224
- }
225
- });
226
-
227
- // modifies the language in the tag cloud
228
- $('.tagcloud-link').each(function() {
229
- var id = $(this).attr('id');
230
- pll_tagBox.get(id, 0);
231
- });
232
-
233
- // modifies the language in the tags suggestion input
234
- pll_tagBox.suggest();
235
- });
236
- });
237
-
238
- // Tag box
239
- // copy paste WP code
240
- // replacing tagsdiv by pll-tagsdiv and tagBox by pll_tagBox
241
- if ( $('#pll-tagsdiv-post_tag').length ) {
242
- pll_tagBox.init();
243
- } else {
244
- $('#side-sortables, #normal-sortables, #advanced-sortables').children('div.postbox').each(function(){
245
- if ( this.id.indexOf('pll-tagsdiv-') === 0 ) {
246
- pll_tagBox.init();
247
- return false;
248
- }
249
- });
250
- }
251
-
252
- // quick edit
253
- jQuery("a.editinline").live("click", function() {
254
- inlineEditPost.revert();
255
- var post_id = inlineEditPost.getId(this);
256
- var lang = $("input[name='lang_"+post_id+"']").attr('value');
257
- $('#post_lang_choice option:selected').removeAttr('selected');
258
- $('#post_lang_choice option[value="'+lang+'"]').attr('selected', 'selected');
259
- });
260
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/post.js CHANGED
@@ -1 +1,269 @@
1
- var pll_tagBox;(function(a){pll_tagBox={clean:function(a){return a.replace(/\s*,\s*/g,",").replace(/,+/g,",").replace(/[,\s]+$/,"").replace(/^[,\s]+/,"")},parseTags:function(b){var c=b.id,d=c.split("-check-num-")[1],e=a(b).closest(".tagsdiv"),f=e.find(".the-tags"),g=f.val().split(","),h=[];delete g[d];a.each(g,function(b,c){c=a.trim(c);if(c){h.push(c)}});f.val(this.clean(h.join(",")));this.quickClicks(e);return false},quickClicks:function(b){var c=a(".the-tags",b),d=a(".tagchecklist",b),e=a(b).attr("id"),f,g;if(!c.length)return;g=c.attr("disabled");f=c.val().split(",");d.empty();a.each(f,function(b,c){var f,h;c=a.trim(c);if(!c)return;f=a("<span />").text(c);if(!g){h=a('<a id="'+e+"-check-num-"+b+'" class="ntdelbutton">X</a>');h.click(function(){pll_tagBox.parseTags(this)});f.prepend(" ").prepend(h)}d.append(f)})},flushTags:function(b,c,d){c=c||false;var e,f=a(".the-tags",b),g=a("input.newtag",b),h;e=c?a(c).text():g.val();tagsval=f.val();h=tagsval?tagsval+","+e:e;h=this.clean(h);h=array_unique_noempty(h.split(",")).join(",");f.val(h);this.quickClicks(b);if(!c)g.val("");if("undefined"==typeof d)g.focus();return false},get:function(b,c){var d=b.substr(b.indexOf("-")+1);var e={action:"get-tagcloud",lang:a("#post_lang_choice").attr("value"),tax:d};a.post(ajaxurl,e,function(e,f){if(0==e||"success"!=f)e=wpAjax.broken;e=a('<p id="tagcloud-'+d+'" class="the-tagcloud">'+e+"</p>");a("a",e).click(function(){pll_tagBox.flushTags(a(this).closest(".inside").children(".tagsdiv"),this);return false});if(c==1)a("#"+b).after(e);else{v=a(".the-tagcloud").css("display");a(".the-tagcloud").replaceWith(e);a(".the-tagcloud").css("display",v)}})},suggest:function(){ajaxtag=a("div.ajaxtag");a("input.newtag",ajaxtag).unbind().blur(function(){if(this.value=="")a(this).parent().siblings(".taghint").css("visibility","")}).focus(function(){a(this).parent().siblings(".taghint").css("visibility","hidden")}).keyup(function(b){if(13==b.which){pll_tagBox.flushTags(a(this).closest(".tagsdiv"));return false}}).keypress(function(a){if(13==a.which){a.preventDefault();return false}}).each(function(){var b=a("#post_lang_choice").attr("value");var c=a(this).closest("div.tagsdiv").attr("id");a(this).suggest(ajaxurl+"?action=polylang-ajax-tag-search&lang="+b+"&tax="+c,{delay:500,minchars:2,multiple:true,multipleSep:","})})},init:function(){var b=this,c=a("div.ajaxtag");a(".tagsdiv").each(function(){pll_tagBox.quickClicks(this)});a("input.tagadd",c).click(function(){b.flushTags(a(this).closest(".tagsdiv"))});a("div.taghint",c).click(function(){a(this).css("visibility","hidden").parent().siblings(".newtag").focus()});pll_tagBox.suggest();a("#post").submit(function(){a("div.tagsdiv").each(function(){pll_tagBox.flushTags(this,false,1)})});a("a.tagcloud-link").click(function(){pll_tagBox.get(a(this).attr("id"),1);a(this).unbind().click(function(){a(this).siblings(".the-tagcloud").toggle();return false});return false})}}})(jQuery);jQuery(document).ready(function(a){var b=new Array;a(".categorydiv").each(function(){var c=a(this).attr("id"),d,e;d=c.split("-");d.shift();e=d.join("-");b.push(e)});a("#post_lang_choice").change(function(){var c={action:"post_lang_choice",lang:a(this).attr("value"),taxonomies:b,post_id:a("#post_ID").attr("value")};a.post(ajaxurl,c,function(b){var c=wpAjax.parseAjaxResponse(b,"ajax-response");a.each(c.responses,function(){switch(this.what){case"translations":a("#post-translations").html(this.data);break;case"taxonomy":var b=this.data;a("#"+b+"checklist").html(this.supplemental.all);a("#"+b+"checklist-pop").html(this.supplemental.populars);a("#new"+b+"_parent").replaceWith(this.supplemental.dropdown);a("#"+b+"-lang").val(a("#post_lang_choice").attr("value"));break;case"pages":a("#parent_id").replaceWith(this.data);break;default:break}});a(".tagcloud-link").each(function(){var b=a(this).attr("id");pll_tagBox.get(b,0)});pll_tagBox.suggest()})});if(a("#pll-tagsdiv-post_tag").length){pll_tagBox.init()}else{a("#side-sortables, #normal-sortables, #advanced-sortables").children("div.postbox").each(function(){if(this.id.indexOf("pll-tagsdiv-")===0){pll_tagBox.init();return false}})}jQuery("a.editinline").live("click",function(){inlineEditPost.revert();var b=inlineEditPost.getId(this);var c=a("input[name='lang_"+b+"']").attr("value");a("#post_lang_choice option:selected").removeAttr("selected");a('#post_lang_choice option[value="'+c+'"]').attr("selected","selected")})})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var pll_tagBox;
2
+
3
+ // mainly copy paste of WP code
4
+ (function($){
5
+
6
+ pll_tagBox = {
7
+ clean : function(tags) {
8
+ return tags.replace(/\s*,\s*/g, ',').replace(/,+/g, ',').replace(/[,\s]+$/, '').replace(/^[,\s]+/, '');
9
+ },
10
+
11
+ parseTags : function(el) {
12
+ var id = el.id, num = id.split('-check-num-')[1], taxbox = $(el).closest('.tagsdiv'), thetags = taxbox.find('.the-tags'), current_tags = thetags.val().split(','), new_tags = [];
13
+ delete current_tags[num];
14
+
15
+ $.each( current_tags, function(key, val) {
16
+ val = $.trim(val);
17
+ if ( val ) {
18
+ new_tags.push(val);
19
+ }
20
+ });
21
+
22
+ thetags.val( this.clean( new_tags.join(',') ) );
23
+
24
+ this.quickClicks(taxbox);
25
+ return false;
26
+ },
27
+
28
+ quickClicks : function(el) {
29
+ var thetags = $('.the-tags', el),
30
+ tagchecklist = $('.tagchecklist', el),
31
+ id = $(el).attr('id'),
32
+ current_tags, disabled;
33
+
34
+ if ( !thetags.length )
35
+ return;
36
+
37
+ // FIXME: why this modification ?
38
+ // disabled = thetags.prop('disabled'); // 3.3
39
+ // disabled = thetags.attr('disabled'); // 3.1
40
+ disabled = thetags.attr('disabled');
41
+
42
+ current_tags = thetags.val().split(',');
43
+ tagchecklist.empty();
44
+
45
+ $.each( current_tags, function( key, val ) {
46
+ var span, xbutton;
47
+
48
+ val = $.trim( val );
49
+
50
+ if ( ! val )
51
+ return;
52
+
53
+ // Create a new span, and ensure the text is properly escaped.
54
+ span = $('<span />').text( val );
55
+
56
+ // If tags editing isn't disabled, create the X button.
57
+ if ( ! disabled ) {
58
+ xbutton = $( '<a id="' + id + '-check-num-' + key + '" class="ntdelbutton">X</a>' );
59
+ xbutton.click( function(){ pll_tagBox.parseTags(this); });
60
+ span.prepend('&nbsp;').prepend( xbutton );
61
+ }
62
+
63
+ // Append the span to the tag list.
64
+ tagchecklist.append( span );
65
+ });
66
+ },
67
+
68
+ flushTags : function(el, a, f) {
69
+ a = a || false;
70
+ var text, tags = $('.the-tags', el), newtag = $('input.newtag', el), newtags;
71
+
72
+ text = a ? $(a).text() : newtag.val();
73
+ tagsval = tags.val();
74
+ newtags = tagsval ? tagsval + ',' + text : text;
75
+
76
+ newtags = this.clean( newtags );
77
+ newtags = array_unique_noempty( newtags.split(',') ).join(',');
78
+ tags.val(newtags);
79
+ this.quickClicks(el);
80
+
81
+ if ( !a )
82
+ newtag.val('');
83
+ if ( 'undefined' == typeof(f) )
84
+ newtag.focus();
85
+
86
+ return false;
87
+ },
88
+
89
+ get : function(id, a) {
90
+ var tax = id.substr(id.indexOf('-')+1);
91
+
92
+ // add the language in the $_POST variable
93
+ var data = {
94
+ action: 'get-tagcloud',
95
+ lang: $('#post_lang_choice').attr('value'),
96
+ tax: tax
97
+ }
98
+
99
+ $.post(ajaxurl, data, function(r, stat) {
100
+ if ( 0 == r || 'success' != stat )
101
+ r = wpAjax.broken;
102
+
103
+ r = $('<p id="tagcloud-'+tax+'" class="the-tagcloud">'+r+'</p>');
104
+ $('a', r).click(function(){
105
+ pll_tagBox.flushTags( $(this).closest('.inside').children('.tagsdiv'), this);
106
+ return false;
107
+ });
108
+
109
+ // add an if else condition to allow modifying the tags outputed when switching the language
110
+ if (a == 1)
111
+ $('#'+id).after(r);
112
+ else {
113
+ v = $('.the-tagcloud').css('display');
114
+ $('.the-tagcloud').replaceWith(r);
115
+ $('.the-tagcloud').css('display', v);
116
+ }
117
+ });
118
+ },
119
+
120
+ suggest : function() {
121
+ ajaxtag = $('div.ajaxtag');
122
+ // add the unbind function to allow calling the function when the language is modified
123
+ $('input.newtag', ajaxtag).unbind().blur(function() {
124
+ if ( this.value == '' )
125
+ $(this).parent().siblings('.taghint').css('visibility', '');
126
+ }).focus(function(){
127
+ $(this).parent().siblings('.taghint').css('visibility', 'hidden');
128
+ }).keyup(function(e){
129
+ if ( 13 == e.which ) {
130
+ pll_tagBox.flushTags( $(this).closest('.tagsdiv') );
131
+ return false;
132
+ }
133
+ }).keypress(function(e){
134
+ if ( 13 == e.which ) {
135
+ e.preventDefault();
136
+ return false;
137
+ }
138
+ }).each(function(){
139
+ // add the language in the $_GET variable
140
+ var lang = $('#post_lang_choice').attr('value');
141
+ var tax = $(this).closest('div.tagsdiv').attr('id');
142
+ $(this).suggest( ajaxurl + '?action=polylang-ajax-tag-search&lang=' + lang + '&tax=' + tax, { delay: 500, minchars: 2, multiple: true, multipleSep: "," } );
143
+ });
144
+ },
145
+
146
+ init : function() {
147
+ var t = this, ajaxtag = $('div.ajaxtag');
148
+
149
+ $('.tagsdiv').each( function() {
150
+ pll_tagBox.quickClicks(this);
151
+ });
152
+
153
+ $('input.tagadd', ajaxtag).click(function(){
154
+ t.flushTags( $(this).closest('.tagsdiv') );
155
+ });
156
+
157
+ $('div.taghint', ajaxtag).click(function(){
158
+ $(this).css('visibility', 'hidden').parent().siblings('.newtag').focus();
159
+ });
160
+
161
+ pll_tagBox.suggest();
162
+
163
+ // save tags on post save/publish
164
+ $('#post').submit(function(){
165
+ $('div.tagsdiv').each( function() {
166
+ pll_tagBox.flushTags(this, false, 1);
167
+ });
168
+ });
169
+
170
+ // tag cloud
171
+ $('a.tagcloud-link').click(function(){
172
+ pll_tagBox.get( $(this).attr('id'), 1 );
173
+ $(this).unbind().click(function(){
174
+ $(this).siblings('.the-tagcloud').toggle();
175
+ return false;
176
+ });
177
+ return false;
178
+ });
179
+ }
180
+ };
181
+
182
+ })(jQuery);
183
+
184
+ jQuery(document).ready(function($) {
185
+ // collect taxonomies - code partly copied from WordPress
186
+ var taxonomies = new Array();
187
+ $('.categorydiv').each( function(){
188
+ var this_id = $(this).attr('id'), taxonomyParts, taxonomy;
189
+
190
+ taxonomyParts = this_id.split('-');
191
+ taxonomyParts.shift();
192
+ taxonomy = taxonomyParts.join('-');
193
+ taxonomies.push(taxonomy); // store the taxonomy for future use
194
+
195
+ // add our hidden field in the new category form - for each hierarchical taxonomy
196
+ // to set the language when creating a new category
197
+ $('#' + taxonomy + '-add-submit').before($('<input />')
198
+ .attr('type', 'hidden')
199
+ .attr('id', taxonomy + '-lang')
200
+ .attr('name', 'term_lang_choice')
201
+ .attr('value', $('#post_lang_choice').attr('value'))
202
+ );
203
+ });
204
+
205
+ // ajax for changing the post's language in the languages metabox
206
+ $('#post_lang_choice').change( function() {
207
+ var data = {
208
+ action: 'post_lang_choice',
209
+ lang: $(this).attr('value'),
210
+ taxonomies: taxonomies,
211
+ post_id: $('#post_ID').attr('value')
212
+ }
213
+
214
+ $.post(ajaxurl, data , function(response) {
215
+ var res = wpAjax.parseAjaxResponse(response, 'ajax-response');
216
+ $.each(res.responses, function() {
217
+ switch (this.what) {
218
+ case 'translations': // translations fields
219
+ $('#post-translations').html(this.data);
220
+ break;
221
+ case 'taxonomy': // categories metabox for posts
222
+ var tax = this.data;
223
+ $('#' + tax + 'checklist').html(this.supplemental.all);
224
+ $('#' + tax + 'checklist-pop').html(this.supplemental.populars);
225
+ $('#new' + tax + '_parent').replaceWith(this.supplemental.dropdown);
226
+ $('#' + tax + '-lang').val($('#post_lang_choice').attr('value')); // hidden field
227
+ break;
228
+ case 'pages': // parent dropdown list for pages
229
+ $('#parent_id').replaceWith(this.data);
230
+ break;
231
+ default:
232
+ break;
233
+ }
234
+ });
235
+
236
+ // modifies the language in the tag cloud
237
+ $('.tagcloud-link').each(function() {
238
+ var id = $(this).attr('id');
239
+ pll_tagBox.get(id, 0);
240
+ });
241
+
242
+ // modifies the language in the tags suggestion input
243
+ pll_tagBox.suggest();
244
+ });
245
+ });
246
+
247
+ // Tag box
248
+ // copy paste WP code
249
+ // replacing tagsdiv by pll-tagsdiv and tagBox by pll_tagBox
250
+ if ( $('#pll-tagsdiv-post_tag').length ) {
251
+ pll_tagBox.init();
252
+ } else {
253
+ $('#side-sortables, #normal-sortables, #advanced-sortables').children('div.postbox').each(function(){
254
+ if ( this.id.indexOf('pll-tagsdiv-') === 0 ) {
255
+ pll_tagBox.init();
256
+ return false;
257
+ }
258
+ });
259
+ }
260
+
261
+ // quick edit
262
+ jQuery("a.editinline").live("click", function() {
263
+ inlineEditPost.revert();
264
+ var post_id = inlineEditPost.getId(this);
265
+ var lang = $("input[name='lang_"+post_id+"']").attr('value');
266
+ $('#post_lang_choice option:selected').removeAttr('selected');
267
+ $('#post_lang_choice option[value="'+lang+'"]').attr('selected', 'selected');
268
+ });
269
+ });
js/post.min.js ADDED
@@ -0,0 +1 @@
 
1
+ var pll_tagBox;(function(a){pll_tagBox={clean:function(b){return b.replace(/\s*,\s*/g,",").replace(/,+/g,",").replace(/[,\s]+$/,"").replace(/^[,\s]+/,"")},parseTags:function(e){var h=e.id,b=h.split("-check-num-")[1],d=a(e).closest(".tagsdiv"),g=d.find(".the-tags"),c=g.val().split(","),f=[];delete c[b];a.each(c,function(i,j){j=a.trim(j);if(j){f.push(j)}});g.val(this.clean(f.join(",")));this.quickClicks(d);return false},quickClicks:function(d){var g=a(".the-tags",d),e=a(".tagchecklist",d),f=a(d).attr("id"),b,c;if(!g.length){return}c=g.attr("disabled");b=g.val().split(",");e.empty();a.each(b,function(i,k){var j,h;k=a.trim(k);if(!k){return}j=a("<span />").text(k);if(!c){h=a('<a id="'+f+"-check-num-"+i+'" class="ntdelbutton">X</a>');h.click(function(){pll_tagBox.parseTags(this)});j.prepend("&nbsp;").prepend(h)}e.append(j)})},flushTags:function(e,b,g){b=b||false;var i,c=a(".the-tags",e),h=a("input.newtag",e),d;i=b?a(b).text():h.val();tagsval=c.val();d=tagsval?tagsval+","+i:i;d=this.clean(d);d=array_unique_noempty(d.split(",")).join(",");c.val(d);this.quickClicks(e);if(!b){h.val("")}if("undefined"==typeof(g)){h.focus()}return false},get:function(e,b){var c=e.substr(e.indexOf("-")+1);var d={action:"get-tagcloud",lang:a("#post_lang_choice").attr("value"),tax:c};a.post(ajaxurl,d,function(g,f){if(0==g||"success"!=f){g=wpAjax.broken}g=a('<p id="tagcloud-'+c+'" class="the-tagcloud">'+g+"</p>");a("a",g).click(function(){pll_tagBox.flushTags(a(this).closest(".inside").children(".tagsdiv"),this);return false});if(b==1){a("#"+e).after(g)}else{v=a(".the-tagcloud").css("display");a(".the-tagcloud").replaceWith(g);a(".the-tagcloud").css("display",v)}})},suggest:function(){ajaxtag=a("div.ajaxtag");a("input.newtag",ajaxtag).unbind().blur(function(){if(this.value==""){a(this).parent().siblings(".taghint").css("visibility","")}}).focus(function(){a(this).parent().siblings(".taghint").css("visibility","hidden")}).keyup(function(b){if(13==b.which){pll_tagBox.flushTags(a(this).closest(".tagsdiv"));return false}}).keypress(function(b){if(13==b.which){b.preventDefault();return false}}).each(function(){var c=a("#post_lang_choice").attr("value");var b=a(this).closest("div.tagsdiv").attr("id");a(this).suggest(ajaxurl+"?action=polylang-ajax-tag-search&lang="+c+"&tax="+b,{delay:500,minchars:2,multiple:true,multipleSep:","})})},init:function(){var b=this,c=a("div.ajaxtag");a(".tagsdiv").each(function(){pll_tagBox.quickClicks(this)});a("input.tagadd",c).click(function(){b.flushTags(a(this).closest(".tagsdiv"))});a("div.taghint",c).click(function(){a(this).css("visibility","hidden").parent().siblings(".newtag").focus()});pll_tagBox.suggest();a("#post").submit(function(){a("div.tagsdiv").each(function(){pll_tagBox.flushTags(this,false,1)})});a("a.tagcloud-link").click(function(){pll_tagBox.get(a(this).attr("id"),1);a(this).unbind().click(function(){a(this).siblings(".the-tagcloud").toggle();return false});return false})}}})(jQuery);jQuery(document).ready(function(b){var a=new Array();b(".categorydiv").each(function(){var e=b(this).attr("id"),d,c;d=e.split("-");d.shift();c=d.join("-");a.push(c);b("#"+c+"-add-submit").before(b("<input />").attr("type","hidden").attr("id",c+"-lang").attr("name","term_lang_choice").attr("value",b("#post_lang_choice").attr("value")))});b("#post_lang_choice").change(function(){var c={action:"post_lang_choice",lang:b(this).attr("value"),taxonomies:a,post_id:b("#post_ID").attr("value")};b.post(ajaxurl,c,function(d){var e=wpAjax.parseAjaxResponse(d,"ajax-response");b.each(e.responses,function(){switch(this.what){case"translations":b("#post-translations").html(this.data);break;case"taxonomy":var f=this.data;b("#"+f+"checklist").html(this.supplemental.all);b("#"+f+"checklist-pop").html(this.supplemental.populars);b("#new"+f+"_parent").replaceWith(this.supplemental.dropdown);b("#"+f+"-lang").val(b("#post_lang_choice").attr("value"));break;case"pages":b("#parent_id").replaceWith(this.data);break;default:break}});b(".tagcloud-link").each(function(){var f=b(this).attr("id");pll_tagBox.get(f,0)});pll_tagBox.suggest()})});if(b("#pll-tagsdiv-post_tag").length){pll_tagBox.init()}else{b("#side-sortables, #normal-sortables, #advanced-sortables").children("div.postbox").each(function(){if(this.id.indexOf("pll-tagsdiv-")===0){pll_tagBox.init();return false}})}jQuery("a.editinline").live("click",function(){inlineEditPost.revert();var c=inlineEditPost.getId(this);var d=b("input[name='lang_"+c+"']").attr("value");b("#post_lang_choice option:selected").removeAttr("selected");b('#post_lang_choice option[value="'+d+'"]').attr("selected","selected")})});
js/term.dev.js DELETED
@@ -1,39 +0,0 @@
1
- jQuery(document).ready(function($) {
2
- // ajax for changing the term's language
3
- $('#term_lang_choice').change(function() {
4
- var data = {
5
- action: 'term_lang_choice',
6
- lang: $(this).attr('value'),
7
- term_id: $("input[name='tag_ID']").attr('value'),
8
- taxonomy: $("input[name='taxonomy']").attr('value')
9
- }
10
-
11
- $.post(ajaxurl, data, function(response) {
12
- var res = wpAjax.parseAjaxResponse(response, 'ajax-response');
13
- $.each(res.responses, function() {
14
- switch (this.what) {
15
- case 'translations': // translations fields
16
- $("#term-translations").html(this.data);
17
- break;
18
- case 'parent': // parent dropdown list for hierarchical taxonomies
19
- $('#parent').replaceWith(this.data);
20
- break;
21
- case 'tag_cloud': // popular items
22
- $('.tagcloud').replaceWith(this.data);
23
- break;
24
- default:
25
- break;
26
- }
27
- });
28
- });
29
- });
30
-
31
- // quick edit
32
- jQuery("a.editinline").live("click", function() {
33
- inlineEditTax.revert();
34
- var id = inlineEditTax.getId(this);
35
- var lang = $("input[name='lang_"+id+"']").attr('value');
36
- $('#inline_lang_choice option:selected').removeAttr('selected');
37
- $('#inline_lang_choice option[value="'+lang+'"]').attr('selected', 'selected');
38
- });
39
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/term.js CHANGED
@@ -1 +1,39 @@
1
- jQuery(document).ready(function(a){a("#term_lang_choice").change(function(){var b={action:"term_lang_choice",lang:a(this).attr("value"),term_id:a("input[name='tag_ID']").attr("value"),taxonomy:a("input[name='taxonomy']").attr("value")};a.post(ajaxurl,b,function(b){var c=wpAjax.parseAjaxResponse(b,"ajax-response");a.each(c.responses,function(){switch(this.what){case"translations":a("#term-translations").html(this.data);break;case"parent":a("#parent").replaceWith(this.data);break;case"tag_cloud":a(".tagcloud").replaceWith(this.data);break;default:break}})})});jQuery("a.editinline").live("click",function(){inlineEditTax.revert();var b=inlineEditTax.getId(this);var c=a("input[name='lang_"+b+"']").attr("value");a("#inline_lang_choice option:selected").removeAttr("selected");a('#inline_lang_choice option[value="'+c+'"]').attr("selected","selected")})})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($) {
2
+ // ajax for changing the term's language
3
+ $('#term_lang_choice').change(function() {
4
+ var data = {
5
+ action: 'term_lang_choice',
6
+ lang: $(this).attr('value'),
7
+ term_id: $("input[name='tag_ID']").attr('value'),
8
+ taxonomy: $("input[name='taxonomy']").attr('value')
9
+ }
10
+
11
+ $.post(ajaxurl, data, function(response) {
12
+ var res = wpAjax.parseAjaxResponse(response, 'ajax-response');
13
+ $.each(res.responses, function() {
14
+ switch (this.what) {
15
+ case 'translations': // translations fields
16
+ $("#term-translations").html(this.data);
17
+ break;
18
+ case 'parent': // parent dropdown list for hierarchical taxonomies
19
+ $('#parent').replaceWith(this.data);
20
+ break;
21
+ case 'tag_cloud': // popular items
22
+ $('.tagcloud').replaceWith(this.data);
23
+ break;
24
+ default:
25
+ break;
26
+ }
27
+ });
28
+ });
29
+ });
30
+
31
+ // quick edit
32
+ jQuery("a.editinline").live("click", function() {
33
+ inlineEditTax.revert();
34
+ var id = inlineEditTax.getId(this);
35
+ var lang = $("input[name='lang_"+id+"']").attr('value');
36
+ $('#inline_lang_choice option:selected').removeAttr('selected');
37
+ $('#inline_lang_choice option[value="'+lang+'"]').attr('selected', 'selected');
38
+ });
39
+ });
js/term.min.js ADDED
@@ -0,0 +1 @@
 
1
+ jQuery(document).ready(function(a){a("#term_lang_choice").change(function(){var b={action:"term_lang_choice",lang:a(this).attr("value"),term_id:a("input[name='tag_ID']").attr("value"),taxonomy:a("input[name='taxonomy']").attr("value")};a.post(ajaxurl,b,function(b){var c=wpAjax.parseAjaxResponse(b,"ajax-response");a.each(c.responses,function(){switch(this.what){case"translations":a("#term-translations").html(this.data);break;case"parent":a("#parent").replaceWith(this.data);break;case"tag_cloud":a(".tagcloud").replaceWith(this.data);break;default:break}})})});jQuery("a.editinline").live("click",function(){inlineEditTax.revert();var b=inlineEditTax.getId(this);var c=a("input[name='lang_"+b+"']").attr("value");a("#inline_lang_choice option:selected").removeAttr("selected");a('#inline_lang_choice option[value="'+c+'"]').attr("selected","selected")})})
js/user.dev.js DELETED
@@ -1,20 +0,0 @@
1
- jQuery(document).ready(function($) {
2
- // biography
3
- // FIXME there is probably a more efficient way to do this
4
- var td = $('#description').parent();
5
- var d = $('#description').clone();
6
- var span = td.children('.description').clone();
7
- td.children().remove();
8
-
9
- $('.biography').each( function(){
10
- lang = $(this).attr('name').split('-');
11
- desc = d.clone();
12
- desc.attr('name', 'description_'+lang[0]);
13
- desc.html($(this).attr('value'));
14
- td.append('<div>'+lang[1]+'</div');
15
- td.append(desc);
16
- });
17
-
18
- td.append('<br />');
19
- td.append(span);
20
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/user.js CHANGED
@@ -1 +1,20 @@
1
- jQuery(document).ready(function(a){var b=a("#description").parent();var c=a("#description").clone();var d=b.children(".description").clone();b.children().remove();a(".biography").each(function(){lang=a(this).attr("name").split("-");desc=c.clone();desc.attr("name","description_"+lang[0]);desc.html(a(this).attr("value"));b.append("<div>"+lang[1]+"</div");b.append(desc)});b.append("<br />");b.append(d)})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($) {
2
+ // biography
3
+ // FIXME there is probably a more efficient way to do this
4
+ var td = $('#description').parent();
5
+ var d = $('#description').clone();
6
+ var span = td.children('.description').clone();
7
+ td.children().remove();
8
+
9
+ $('.biography').each( function(){
10
+ lang = $(this).attr('name').split('-');
11
+ desc = d.clone();
12
+ desc.attr('name', 'description_'+lang[0]);
13
+ desc.html($(this).attr('value'));
14
+ td.append('<div>'+lang[1]+'</div');
15
+ td.append(desc);
16
+ });
17
+
18
+ td.append('<br />');
19
+ td.append(span);
20
+ });
js/user.min.js ADDED
@@ -0,0 +1 @@
 
1
+ jQuery(document).ready(function(a){var b=a("#description").parent();var c=a("#description").clone();var d=b.children(".description").clone();b.children().remove();a(".biography").each(function(){lang=a(this).attr("name").split("-");desc=c.clone();desc.attr("name","description_"+lang[0]);desc.html(a(this).attr("value"));b.append("<div>"+lang[1]+"</div");b.append(desc)});b.append("<br />");b.append(d)})
languages/polylang-fi.mo CHANGED
Binary file
languages/polylang-fi.po CHANGED
@@ -293,7 +293,7 @@ msgstr "Valitse kielen tekstin suunta"
293
 
294
  #: ../include/languages-form.php:100
295
  msgid "Order"
296
- msgstr "Tilaus"
297
 
298
  #: ../include/languages-form.php:102
299
  msgid "Position of the language in the language switcher"
293
 
294
  #: ../include/languages-form.php:100
295
  msgid "Order"
296
+ msgstr "Järjestys"
297
 
298
  #: ../include/languages-form.php:102
299
  msgid "Position of the language in the language switcher"
polylang.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: Polylang
4
  Plugin URI: http://wordpress.org/extend/plugins/polylang/
5
- Version: 0.9.1
6
  Author: F. Demarle
7
  Description: Adds multilingual capability to Wordpress
8
  */
@@ -24,7 +24,7 @@ Description: Adds multilingual capability to Wordpress
24
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
  */
26
 
27
- define('POLYLANG_VERSION', '0.9.1');
28
  define('PLL_MIN_WP_VERSION', '3.1');
29
 
30
  define('POLYLANG_DIR', dirname(__FILE__)); // our directory
2
  /*
3
  Plugin Name: Polylang
4
  Plugin URI: http://wordpress.org/extend/plugins/polylang/
5
+ Version: 0.9.2
6
  Author: F. Demarle
7
  Description: Adds multilingual capability to Wordpress
8
  */
24
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
  */
26
 
27
+ define('POLYLANG_VERSION', '0.9.2');
28
  define('PLL_MIN_WP_VERSION', '3.1');
29
 
30
  define('POLYLANG_DIR', dirname(__FILE__)); // our directory
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
4
  Tags: multilingual, bilingual, translate, translation, language, multilanguage, i18n, international, l10n, localization
5
  Requires at least: 3.1
6
  Tested up to: 3.4.2
7
- Stable tag: 0.9.1
8
 
9
  Polylang adds multilingual content management support to WordPress.
10
 
@@ -92,6 +92,18 @@ Every suggestions are welcome.
92
 
93
  == Changelog ==
94
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  = 0.9.1 (2012-09-20) =
96
 
97
  * Add Finnish translation contributed by [Jani Alha](http://www.wysiwyg.fi)
4
  Tags: multilingual, bilingual, translate, translation, language, multilanguage, i18n, international, l10n, localization
5
  Requires at least: 3.1
6
  Tested up to: 3.4.2
7
+ Stable tag: 0.9.2
8
 
9
  Polylang adds multilingual content management support to WordPress.
10
 
92
 
93
  == Changelog ==
94
 
95
+ = 0.9.2 (2102-09-30) =
96
+
97
+ * Support new WordPress (WP 3.5+) convention for js and css files naming
98
+ * Improve performance, mainly on frontend
99
+ * Bug correction: the category language is not set when creating it in the post editor (introduced in 0.9)
100
+ * Bug correction: unable to add a query string when using a static front page
101
+ * Bug correction: ajax tag suggestion in "edit post" conflicts with the admin content language filter
102
+ * Bug correction: ugly notices when trying to access a static front page which has not been translated
103
+ * Bug correction: the language code is added to custom post types and taxonomies permalinks even if they are not translatable
104
+ * Bug correction: some arrays in wp_locale mix English and other language
105
+ * Bug correction: the media language is not correctly set when uploading from post if the post has not been saved after choosing the language
106
+
107
  = 0.9.1 (2012-09-20) =
108
 
109
  * Add Finnish translation contributed by [Jani Alha](http://www.wysiwyg.fi)