Polylang - Version 1.4

Version Description

Polylang 1.2 introduced major internal changes. More than ever, make a database backup before upgrading from 1.1.6 or older! If you are using a version older than 0.8, please ugrade to 0.9.8 before ugrading to 1.3

=

Download this release

Release Info

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

Code changes from version 1.3.1 to 1.4

admin/admin-filters-columns.php CHANGED
@@ -7,7 +7,7 @@
7
  * @since 1.2
8
  */
9
  class PLL_Admin_Filters_Columns {
10
- public $model;
11
 
12
  /*
13
  * constructor: setups filters and actions
@@ -16,11 +16,12 @@ class PLL_Admin_Filters_Columns {
16
  *
17
  * @param object $model instance of PLL_Model
18
  */
19
- public function __construct(&$model) {
20
  $this->model = &$model;
 
21
 
22
  // add the language and translations columns in 'All Posts', 'All Pages' and 'Media library' panels
23
- foreach ($this->model->post_types as $type) {
24
  // use the latest filter late as some plugins purely overwrite what's done by others :(
25
  // specific case for media
26
  add_filter('manage_'. ($type == 'attachment' ? 'upload' : 'edit-'. $type) .'_columns', array(&$this, 'add_post_column'), 100);
@@ -32,7 +33,7 @@ class PLL_Admin_Filters_Columns {
32
  add_filter('bulk_edit_custom_box', array(&$this, 'quick_edit_custom_box'), 10, 2);
33
 
34
  // adds the language column in the 'Categories' and 'Post Tags' tables
35
- foreach ($this->model->taxonomies as $tax) {
36
  add_filter('manage_edit-'.$tax.'_columns', array(&$this, 'add_term_column'));
37
  add_action('manage_'.$tax.'_custom_column', array(&$this, 'term_column'), 10, 3);
38
  }
@@ -56,7 +57,7 @@ class PLL_Admin_Filters_Columns {
56
 
57
  foreach ($this->model->get_languages_list() as $language) {
58
  // don't add the column for the filtered language
59
- if ($language->slug != get_user_meta(get_current_user_id(), 'pll_filter_content', true))
60
  $columns['language_'.$language->slug] = $language->flag ? $language->flag : esc_html($language->slug);
61
  }
62
 
@@ -72,7 +73,7 @@ class PLL_Admin_Filters_Columns {
72
  */
73
  protected function get_first_language_column() {
74
  foreach ($this->model->get_languages_list() as $language) {
75
- if ($language->slug != get_user_meta(get_current_user_id(), 'pll_filter_content', true))
76
  $columns[] = 'language_'.$language->slug;
77
  }
78
 
7
  * @since 1.2
8
  */
9
  class PLL_Admin_Filters_Columns {
10
+ public $model, $curlang;
11
 
12
  /*
13
  * constructor: setups filters and actions
16
  *
17
  * @param object $model instance of PLL_Model
18
  */
19
+ public function __construct(&$model, &$curlang) {
20
  $this->model = &$model;
21
+ $this->curlang = &$curlang;
22
 
23
  // add the language and translations columns in 'All Posts', 'All Pages' and 'Media library' panels
24
+ foreach ($this->model->get_translated_post_types() as $type) {
25
  // use the latest filter late as some plugins purely overwrite what's done by others :(
26
  // specific case for media
27
  add_filter('manage_'. ($type == 'attachment' ? 'upload' : 'edit-'. $type) .'_columns', array(&$this, 'add_post_column'), 100);
33
  add_filter('bulk_edit_custom_box', array(&$this, 'quick_edit_custom_box'), 10, 2);
34
 
35
  // adds the language column in the 'Categories' and 'Post Tags' tables
36
+ foreach ($this->model->get_translated_taxonomies() as $tax) {
37
  add_filter('manage_edit-'.$tax.'_columns', array(&$this, 'add_term_column'));
38
  add_action('manage_'.$tax.'_custom_column', array(&$this, 'term_column'), 10, 3);
39
  }
57
 
58
  foreach ($this->model->get_languages_list() as $language) {
59
  // don't add the column for the filtered language
60
+ if (empty($this->curlang) || $language->slug != $this->curlang->slug)
61
  $columns['language_'.$language->slug] = $language->flag ? $language->flag : esc_html($language->slug);
62
  }
63
 
73
  */
74
  protected function get_first_language_column() {
75
  foreach ($this->model->get_languages_list() as $language) {
76
+ if (empty($this->curlang) || $language->slug != $this->curlang->slug)
77
  $columns[] = 'language_'.$language->slug;
78
  }
79
 
admin/admin-filters-media.php CHANGED
@@ -38,6 +38,7 @@ class PLL_Admin_Filters_Media {
38
 
39
  /*
40
  * adds the language field and translations tables in the 'Edit Media' panel
 
41
  *
42
  * @since 0.9
43
  *
@@ -63,28 +64,12 @@ class PLL_Admin_Filters_Media {
63
  ))
64
  );
65
 
66
- // don't show translations except on edit media panel for backward compatibility WP < 3.5
67
- if ($GLOBALS['pagenow'] == 'media.php') {
68
- if ($lang) {
69
- ob_start();
70
- include PLL_ADMIN_INC . '/view-translations-media.php';
71
- $fields['translations'] = array(
72
- 'label' => __('Translations', 'polylang'),
73
- 'input' => 'html',
74
- 'html' => ob_get_contents(),
75
- );
76
- ob_end_clean();
77
- }
78
- else {
79
- $fields['translations'] = array('tr' => '<tr class="translations"></tr>'); // to get a field for ajax
80
- }
81
- }
82
-
83
  return $fields;
84
  }
85
 
86
  /*
87
  * ajax response for changing the language in media form
 
88
  *
89
  * @since 0.9
90
  */
@@ -97,23 +82,6 @@ class PLL_Admin_Filters_Media {
97
  if ($lang) {
98
  include(PLL_ADMIN_INC.'/view-translations-media.php');
99
  $data = ob_get_contents();
100
-
101
- // backward compatibility WP < 3.5, first add the html generated by WP if non AJAX, then our translation table
102
- if (version_compare($GLOBALS['wp_version'], '3.5', '<')) {
103
- $data = sprintf('
104
- <th scope="row" class="label">
105
- <label for="attachments[%d][translations]">
106
- <span class="alignleft">%s</span><br class="clear" />
107
- </label>
108
- </th>
109
- <td class="field">
110
- %s
111
- </td>',
112
- $post_id,
113
- __('Translations', 'polylang'),
114
- $data
115
- );
116
- }
117
  }
118
  $x = new WP_Ajax_Response(array('what' => 'translations', 'data' => $data));
119
  ob_end_clean();
@@ -144,11 +112,7 @@ class PLL_Admin_Filters_Media {
144
  $translations[$_GET['new_lang']] = $tr_id;
145
  $this->model->save_translations('post', $tr_id, $translations);
146
 
147
- wp_redirect(admin_url(sprintf(
148
- version_compare($GLOBALS['wp_version'], '3.5', '<') ?
149
- 'media.php?attachment_id=%d&action=edit' : // backward compatibility WP < 3.5
150
- 'post.php?post=%d&action=edit', // WP 3.5+
151
- $tr_id)));
152
 
153
  exit;
154
  }
38
 
39
  /*
40
  * adds the language field and translations tables in the 'Edit Media' panel
41
+ * needs WP 3.5+
42
  *
43
  * @since 0.9
44
  *
64
  ))
65
  );
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  return $fields;
68
  }
69
 
70
  /*
71
  * ajax response for changing the language in media form
72
+ * needs WP 3.5+
73
  *
74
  * @since 0.9
75
  */
82
  if ($lang) {
83
  include(PLL_ADMIN_INC.'/view-translations-media.php');
84
  $data = ob_get_contents();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  }
86
  $x = new WP_Ajax_Response(array('what' => 'translations', 'data' => $data));
87
  ob_end_clean();
112
  $translations[$_GET['new_lang']] = $tr_id;
113
  $this->model->save_translations('post', $tr_id, $translations);
114
 
115
+ wp_redirect(admin_url(sprintf('post.php?post=%d&action=edit', $tr_id))); // WP 3.5+
 
 
 
 
116
 
117
  exit;
118
  }
admin/admin-filters-post.php CHANGED
@@ -6,7 +6,7 @@
6
  * @since 1.2
7
  */
8
  class PLL_Admin_Filters_Post {
9
- public $model, $options, $pref_lang;
10
 
11
  /*
12
  * constructor: setups filters and actions
@@ -16,9 +16,10 @@ class PLL_Admin_Filters_Post {
16
  * @param object $model instance of PLL_Model
17
  * @param object $pref_lang language chosen in admin filter or default language
18
  */
19
- public function __construct(&$model, $pref_lang) {
20
  $this->model = &$model;
21
  $this->options = &$model->options;
 
22
  $this->pref_lang = $pref_lang;
23
 
24
  // filters posts, pages and media by language
@@ -30,6 +31,8 @@ class PLL_Admin_Filters_Post {
30
  // ajax response for changing the language in the post metabox
31
  add_action('wp_ajax_post_lang_choice', array(&$this,'post_lang_choice'));
32
 
 
 
33
  // adds actions and filters related to languages when creating, saving or deleting posts and pages
34
  add_action('save_post', array(&$this, 'save_post'), 21, 2); // priority 21 to come after advanced custom fields (20) and before the event calendar which breaks everything after 25
35
  add_action('before_delete_post', array(&$this, 'delete_post'));
@@ -51,21 +54,21 @@ class PLL_Admin_Filters_Post {
51
  $qvars = &$query->query_vars;
52
 
53
  // do not filter post types such as nav_menu_item
54
- if (isset($qvars['post_type']) && !in_array($qvars['post_type'], $this->model->post_types)) {
55
  unset ($qvars['lang']);
56
  return;
57
  }
58
 
59
  // filters the list of media by language when uploading from post
60
- if ($this->options['media_support'] && ($GLOBALS['pagenow'] == 'media-upload.php' || // backward compatibility WP < 3.5
61
- ($GLOBALS['pagenow'] == 'admin-ajax.php' && isset($_REQUEST['action']) && $_REQUEST['action'] == 'query-attachments')) && // WP 3.5+
62
  isset($_REQUEST['post_id']) && $lang = $this->model->get_post_language($_REQUEST['post_id']))
63
  $query->set('lang', $lang->slug);
64
 
65
- if (isset($qvars['post_type']) && in_array($qvars['post_type'], $this->model->post_types) && !isset($qvars['lang']) && $lg = get_user_meta(get_current_user_id(), 'pll_filter_content', true))
66
- $qvars['lang'] = $lg;
67
 
68
- if ((isset($qvars['post_type']) && !in_array($qvars['post_type'], $this->model->post_types)) || (isset($qvars['lang']) && $qvars['lang'] == 'all'))
69
  unset ($qvars['lang']);
70
  }
71
 
@@ -77,7 +80,7 @@ class PLL_Admin_Filters_Post {
77
  * @param string $post_type
78
  */
79
  public function add_meta_boxes($post_type) {
80
- if (in_array($post_type, $this->model->post_types))
81
  add_meta_box('ml_box', __('Languages','polylang'), array(&$this, 'post_language'), $post_type, 'side', 'high');
82
 
83
  // replace tag metabox by our own
@@ -108,8 +111,8 @@ class PLL_Admin_Filters_Post {
108
 
109
  // NOTE: the class "tags-input" allows to include the field in the autosave $_POST (see autosave.js)
110
  printf('
111
- <p><em>%s</em></p>
112
- <p>%s<br /></p>
113
  <div id="post-translations" class="translations">',
114
  __('Language', 'polylang'),
115
  $dropdown->walk($this->model->get_languages_list(), array(
@@ -185,6 +188,20 @@ class PLL_Admin_Filters_Post {
185
  $x->send();
186
  }
187
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  /*
189
  * called when a post (or page) is saved, published or updated
190
  * saves languages and translations
@@ -197,7 +214,7 @@ class PLL_Admin_Filters_Post {
197
  */
198
  public function save_post($post_id, $post) {
199
  // does nothing except on post types which are filterable
200
- if (!in_array($post->post_type, $this->model->post_types))
201
  return;
202
 
203
  // bulk edit does not modify the language
@@ -235,14 +252,14 @@ class PLL_Admin_Filters_Post {
235
  // make sure we get save terms in the right language (especially tags with same name in different languages)
236
  if (!empty($lang)) {
237
  // FIXME quite a lot of query in foreach
238
- foreach ($this->model->taxonomies as $tax) {
239
  $terms = get_the_terms($post_id, $tax);
240
 
241
  if (is_array($terms)) {
242
  $newterms = array();
243
  foreach ($terms as $term) {
244
- if ($newterm = $this->model->get_term_by('name', $term->name, $tax, $lang))
245
- $newterms[] = (int) $newterm->term_id; // cast is important otherwise we get 'numeric' tags
246
 
247
  elseif (!is_wp_error($term_info = wp_insert_term($term->name, $tax))) // create the term in the correct language
248
  $newterms[] = (int) $term_info['term_id'];
@@ -293,12 +310,84 @@ class PLL_Admin_Filters_Post {
293
  * @return array modified arguments
294
  */
295
  public function page_attributes_dropdown_pages_args($dropdown_args, $post) {
296
- $lang = isset($_POST['lang']) ? $this->model->get_language($_POST['lang']) : $this->model->get_post_language($post->ID); // ajax or not ?
297
- if (!$lang)
298
- $lang = $this->pref_lang;
299
 
300
- $pages = implode(',', pll_exclude_pages($lang));
301
- $dropdown_args['exclude'] = isset($dropdown_args['exclude']) ? $dropdown_args['exclude'] . ',' . $pages : $pages;
302
  return $dropdown_args;
303
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
304
  }
6
  * @since 1.2
7
  */
8
  class PLL_Admin_Filters_Post {
9
+ public $model, $options, $curlang, $pref_lang;
10
 
11
  /*
12
  * constructor: setups filters and actions
16
  * @param object $model instance of PLL_Model
17
  * @param object $pref_lang language chosen in admin filter or default language
18
  */
19
+ public function __construct(&$model, &$curlang, $pref_lang) {
20
  $this->model = &$model;
21
  $this->options = &$model->options;
22
+ $this->curlang = &$curlang;
23
  $this->pref_lang = $pref_lang;
24
 
25
  // filters posts, pages and media by language
31
  // ajax response for changing the language in the post metabox
32
  add_action('wp_ajax_post_lang_choice', array(&$this,'post_lang_choice'));
33
 
34
+ add_action('wp_ajax_post_translation_choice', array(&$this,'post_translation_choice'));
35
+
36
  // adds actions and filters related to languages when creating, saving or deleting posts and pages
37
  add_action('save_post', array(&$this, 'save_post'), 21, 2); // priority 21 to come after advanced custom fields (20) and before the event calendar which breaks everything after 25
38
  add_action('before_delete_post', array(&$this, 'delete_post'));
54
  $qvars = &$query->query_vars;
55
 
56
  // do not filter post types such as nav_menu_item
57
+ if (isset($qvars['post_type']) && !$this->model->is_translated_post_type($qvars['post_type'])) {
58
  unset ($qvars['lang']);
59
  return;
60
  }
61
 
62
  // filters the list of media by language when uploading from post
63
+ if ($this->options['media_support'] &&
64
+ $GLOBALS['pagenow'] == 'admin-ajax.php' && isset($_REQUEST['action']) && $_REQUEST['action'] == 'query-attachments' && // WP 3.5+
65
  isset($_REQUEST['post_id']) && $lang = $this->model->get_post_language($_REQUEST['post_id']))
66
  $query->set('lang', $lang->slug);
67
 
68
+ if (isset($qvars['post_type']) && $this->model->is_translated_post_type($qvars['post_type']) && !isset($qvars['lang']) && !empty($this->curlang))
69
+ $qvars['lang'] = $this->curlang->slug;
70
 
71
+ if ((isset($qvars['post_type']) && !$this->model->is_translated_post_type($qvars['post_type'])) || (isset($qvars['lang']) && $qvars['lang'] == 'all'))
72
  unset ($qvars['lang']);
73
  }
74
 
80
  * @param string $post_type
81
  */
82
  public function add_meta_boxes($post_type) {
83
+ if ($this->model->is_translated_post_type($post_type))
84
  add_meta_box('ml_box', __('Languages','polylang'), array(&$this, 'post_language'), $post_type, 'side', 'high');
85
 
86
  // replace tag metabox by our own
111
 
112
  // NOTE: the class "tags-input" allows to include the field in the autosave $_POST (see autosave.js)
113
  printf('
114
+ <p><strong>%s</strong></p>
115
+ %s
116
  <div id="post-translations" class="translations">',
117
  __('Language', 'polylang'),
118
  $dropdown->walk($this->model->get_languages_list(), array(
188
  $x->send();
189
  }
190
 
191
+ /*
192
+ * ajax response for changing a translation in the post metabox
193
+ *
194
+ * @since 1.4
195
+ */
196
+ public function post_translation_choice() {
197
+ $link = $_POST['value'] ?
198
+ $this->edit_translation_link($_POST['value']) :
199
+ $this->add_new_translation_link($_POST['post_id'], get_post_type($_POST['post_id']), $this->model->get_language($_POST['lang']));
200
+
201
+ $x = new WP_Ajax_Response(array('what' => 'link', 'data' => $link));
202
+ $x->send();
203
+ }
204
+
205
  /*
206
  * called when a post (or page) is saved, published or updated
207
  * saves languages and translations
214
  */
215
  public function save_post($post_id, $post) {
216
  // does nothing except on post types which are filterable
217
+ if (!$this->model->is_translated_post_type($post->post_type))
218
  return;
219
 
220
  // bulk edit does not modify the language
252
  // make sure we get save terms in the right language (especially tags with same name in different languages)
253
  if (!empty($lang)) {
254
  // FIXME quite a lot of query in foreach
255
+ foreach ($this->model->get_translated_taxonomies() as $tax) {
256
  $terms = get_the_terms($post_id, $tax);
257
 
258
  if (is_array($terms)) {
259
  $newterms = array();
260
  foreach ($terms as $term) {
261
+ if ($newterm = $this->model->term_exists($term->name, $tax, $term->parent, $lang))
262
+ $newterms[] = (int) $newterm; // cast is important otherwise we get 'numeric' tags
263
 
264
  elseif (!is_wp_error($term_info = wp_insert_term($term->name, $tax))) // create the term in the correct language
265
  $newterms[] = (int) $term_info['term_id'];
310
  * @return array modified arguments
311
  */
312
  public function page_attributes_dropdown_pages_args($dropdown_args, $post) {
313
+ $dropdown_args['lang'] = isset($_POST['lang']) ? $this->model->get_language($_POST['lang']) : $this->model->get_post_language($post->ID); // ajax or not ?
314
+ if (!$dropdown_args['lang'])
315
+ $dropdown_args['lang'] = $this->pref_lang;
316
 
 
 
317
  return $dropdown_args;
318
  }
319
+
320
+ /*
321
+ * returns all posts in the $post_type in the $post_language which have no translation in the $translation_language
322
+ *
323
+ * @since 1.4
324
+ *
325
+ * @param string $post_type
326
+ * @param object $post_language the language of the post we want to translate
327
+ * @param object $translation_language the language in which we are looking untranslated terms
328
+ * @return array
329
+ */
330
+ public function get_posts_not_translated($post_type, $post_language, $translation_language) {
331
+ $posts = get_posts(array(
332
+ 'lang' => 0, // avoid admin language filter
333
+ 'numberposts' => -1,
334
+ 'nopaging' => true,
335
+ 'post_status' => 'any',
336
+ 'post_type' => $post_type,
337
+ 'orderby' => 'title',
338
+ 'order' => 'ASC',
339
+ 'tax_query' => array(array(
340
+ 'taxonomy' => 'language',
341
+ 'field' => 'term_taxonomy_id', // WP 3.5+
342
+ 'terms' => $post_language->term_taxonomy_id
343
+ ))
344
+ ));
345
+
346
+ foreach ($posts as $key => $post) {
347
+ if ($this->model->get_translation('post', $post->ID, $translation_language))
348
+ unset($posts[$key]);
349
+ }
350
+
351
+ return $posts;
352
+ }
353
+
354
+ /*
355
+ * returns html markup for a translation link
356
+ *
357
+ * @since 1.4
358
+ *
359
+ * @param int $value translation post id
360
+ * @return string
361
+ */
362
+ public function edit_translation_link($value) {
363
+ return sprintf(
364
+ '<div class="spinner"></div><a href="%1$s" class="pll_icon_edit" title="%2$s"></a>',
365
+ esc_url(get_edit_post_link($value)),
366
+ __('Edit', 'polylang')
367
+ );
368
+ }
369
+
370
+ /*
371
+ * returns html markup to add a new translation
372
+ *
373
+ * @since 1.4
374
+ *
375
+ * @param int $post_ID post id of the post to translate
376
+ * @param string $post_type
377
+ * @param object $language language of the new translation
378
+ * @return string
379
+ */
380
+ public function add_new_translation_link($post_ID, $post_type, $language) {
381
+ $args = array(
382
+ 'post_type' => $post_type,
383
+ 'from_post' => $post_ID,
384
+ 'new_lang' => $language->slug
385
+ );
386
+
387
+ return sprintf(
388
+ '<div class="spinner"></div><a href="%1$s" class="pll_icon_add" title="%2$s"></a>',
389
+ esc_url(add_query_arg($args, admin_url('post-new.php'))),
390
+ __('Add new', 'polylang')
391
+ );
392
+ }
393
  }
admin/admin-filters-term.php CHANGED
@@ -6,7 +6,7 @@
6
  * @since 1.2
7
  */
8
  class PLL_Admin_Filters_Term {
9
- public $model, $options, $pref_lang;
10
  protected $pre_term_name; // used to store the term name before creating a slug if needed
11
 
12
  /*
@@ -15,12 +15,13 @@ class PLL_Admin_Filters_Term {
15
  * @param object $model instance of PLL_Model
16
  * @param object $pref_lang language chosen in admin filter or default language
17
  */
18
- public function __construct(&$model, $pref_lang) {
19
  $this->model = &$model;
20
  $this->options = &$model->options;
 
21
  $this->pref_lang = $pref_lang;
22
 
23
- foreach ($this->model->taxonomies as $tax) {
24
  // adds the language field in the 'Categories' and 'Post Tags' panels
25
  add_action($tax.'_add_form_fields', array(&$this, 'add_term_form'));
26
 
@@ -42,6 +43,8 @@ class PLL_Admin_Filters_Term {
42
  // ajax response for edit term form
43
  add_action('wp_ajax_term_lang_choice', array(&$this,'term_lang_choice'));
44
 
 
 
45
  // filters categories and post tags by language
46
  add_filter('terms_clauses', array(&$this, 'terms_clauses'), 10, 3);
47
 
@@ -157,7 +160,7 @@ class PLL_Admin_Filters_Term {
157
  */
158
  public function save_term($term_id, $tt_id, $taxonomy) {
159
  // does nothing except on taxonomies which are filterable
160
- if (!in_array($taxonomy, $this->model->taxonomies))
161
  return;
162
 
163
  // save language
@@ -226,7 +229,7 @@ class PLL_Admin_Filters_Term {
226
  $slug = $name . '-' . $taxonomy; // a convenient slug which may be modified later by the user
227
 
228
  // if the term already exists in another language
229
- if (!$slug && in_array($taxonomy, $this->model->taxonomies) && term_exists($name, $taxonomy)) {
230
  if (isset($_POST['term_lang_choice']))
231
  $slug = $name . '-' . $this->model->get_language($_POST['term_lang_choice'])->slug;
232
 
@@ -281,6 +284,7 @@ class PLL_Admin_Filters_Term {
281
  $lang = $this->model->get_language($_POST['lang']);
282
  $term_id = isset($_POST['term_id']) ? $_POST['term_id'] : null;
283
  $taxonomy = $_POST['taxonomy'];
 
284
 
285
  ob_start();
286
  if ($lang)
@@ -321,6 +325,20 @@ class PLL_Admin_Filters_Term {
321
  $x->send();
322
  }
323
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
  /*
325
  * filters categories and post tags by language when needed on admin side
326
  *
@@ -334,7 +352,7 @@ class PLL_Admin_Filters_Term {
334
  public function terms_clauses($clauses, $taxonomies, $args) {
335
  // does nothing except on taxonomies which are filterable
336
  foreach ($taxonomies as $tax)
337
- if (!in_array($tax, $this->model->taxonomies))
338
  return $clauses;
339
 
340
  if (function_exists('get_current_screen'))
@@ -372,10 +390,12 @@ class PLL_Admin_Filters_Term {
372
  elseif (!empty($_GET['lang']) && isset($_GET['action']) && 'polylang-ajax-tag-search' == $_GET['action'])
373
  $lang = $this->model->get_language($_GET['lang']);
374
 
375
- // the post is created with the 'add new' (translation) link
376
- elseif (!empty($_GET['new_lang']))
 
377
  $lang = $this->model->get_language($_GET['new_lang']);
378
 
 
379
  // the language filter selection has just changed
380
  // test $screen->base to avoid interference between the language filter and the post language selection and the category parent dropdown list
381
  elseif (!empty($_GET['lang']) && !(isset($screen) && in_array($screen->base, array('post', 'edit-tags')))) {
@@ -386,9 +406,8 @@ class PLL_Admin_Filters_Term {
386
  }
387
 
388
  // again the language filter
389
- elseif (($lg = get_user_meta(get_current_user_id(), 'pll_filter_content', true)) &&
390
- (isset($screen) && $screen->base != 'post' && !($screen->base == 'edit-tags' && isset($args['class'])))) // don't apply to post edit and the category parent dropdown list
391
- $lang = $this->model->get_language($lg);
392
 
393
  elseif (isset($_GET['post']))
394
  $lang = $this->model->get_post_language($_GET['post']);
@@ -461,10 +480,54 @@ class PLL_Admin_Filters_Term {
461
  * @param int $value
462
  * @return int
463
  */
464
- function option_default_category($value) {
465
  $traces = debug_backtrace();
466
 
467
  return isset($traces[4]) && in_array($traces[4]['function'], array('column_cb', 'column_name')) && in_array($traces[4]['args'][0]->term_id, $this->model->get_translations('term', $value)) ?
468
  $traces[4]['args'][0]->term_id : $value;
469
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
470
  }
6
  * @since 1.2
7
  */
8
  class PLL_Admin_Filters_Term {
9
+ public $model, $options, $curlang, $pref_lang;
10
  protected $pre_term_name; // used to store the term name before creating a slug if needed
11
 
12
  /*
15
  * @param object $model instance of PLL_Model
16
  * @param object $pref_lang language chosen in admin filter or default language
17
  */
18
+ public function __construct(&$model, &$curlang, $pref_lang) {
19
  $this->model = &$model;
20
  $this->options = &$model->options;
21
+ $this->curlang = $curlang;
22
  $this->pref_lang = $pref_lang;
23
 
24
+ foreach ($this->model->get_translated_taxonomies() as $tax) {
25
  // adds the language field in the 'Categories' and 'Post Tags' panels
26
  add_action($tax.'_add_form_fields', array(&$this, 'add_term_form'));
27
 
43
  // ajax response for edit term form
44
  add_action('wp_ajax_term_lang_choice', array(&$this,'term_lang_choice'));
45
 
46
+ add_action('wp_ajax_term_translation_choice', array(&$this,'term_translation_choice'));
47
+
48
  // filters categories and post tags by language
49
  add_filter('terms_clauses', array(&$this, 'terms_clauses'), 10, 3);
50
 
160
  */
161
  public function save_term($term_id, $tt_id, $taxonomy) {
162
  // does nothing except on taxonomies which are filterable
163
+ if (!$this->model->is_translated_taxonomy($taxonomy))
164
  return;
165
 
166
  // save language
229
  $slug = $name . '-' . $taxonomy; // a convenient slug which may be modified later by the user
230
 
231
  // if the term already exists in another language
232
+ if (!$slug && $this->model->is_translated_taxonomy($taxonomy) && term_exists($name, $taxonomy)) {
233
  if (isset($_POST['term_lang_choice']))
234
  $slug = $name . '-' . $this->model->get_language($_POST['term_lang_choice'])->slug;
235
 
284
  $lang = $this->model->get_language($_POST['lang']);
285
  $term_id = isset($_POST['term_id']) ? $_POST['term_id'] : null;
286
  $taxonomy = $_POST['taxonomy'];
287
+ $post_type = $_POST['post_type'];
288
 
289
  ob_start();
290
  if ($lang)
325
  $x->send();
326
  }
327
 
328
+ /*
329
+ * ajax response for changing a translation
330
+ *
331
+ * @since 1.4
332
+ */
333
+ public function term_translation_choice() {
334
+ $link = $_POST['value'] ?
335
+ $this->edit_translation_link($_POST['value'], $_POST['taxonomy'], $_POST['post_type']) :
336
+ $this->add_new_translation_link($_POST['term_id'], $_POST['taxonomy'], $_POST['post_type'], $this->model->get_language($_POST['lang']));
337
+
338
+ $x = new WP_Ajax_Response(array('what' => 'link', 'data' => $link));
339
+ $x->send();
340
+ }
341
+
342
  /*
343
  * filters categories and post tags by language when needed on admin side
344
  *
352
  public function terms_clauses($clauses, $taxonomies, $args) {
353
  // does nothing except on taxonomies which are filterable
354
  foreach ($taxonomies as $tax)
355
+ if (!$this->model->is_translated_taxonomy($tax))
356
  return $clauses;
357
 
358
  if (function_exists('get_current_screen'))
390
  elseif (!empty($_GET['lang']) && isset($_GET['action']) && 'polylang-ajax-tag-search' == $_GET['action'])
391
  $lang = $this->model->get_language($_GET['lang']);
392
 
393
+ // the post (or term) is created with the 'add new' (translation) link
394
+ // test of $args['page'] to avoid filtering the terms list table in edit-tags panel
395
+ elseif (!empty($_GET['new_lang']) && empty($args['page']))
396
  $lang = $this->model->get_language($_GET['new_lang']);
397
 
398
+ // FIXME can we simplify how we deal with the admin language filter?
399
  // the language filter selection has just changed
400
  // test $screen->base to avoid interference between the language filter and the post language selection and the category parent dropdown list
401
  elseif (!empty($_GET['lang']) && !(isset($screen) && in_array($screen->base, array('post', 'edit-tags')))) {
406
  }
407
 
408
  // again the language filter
409
+ elseif (!empty($this->curlang) && (isset($screen) && $screen->base != 'post' && !($screen->base == 'edit-tags' && isset($args['class'])))) // don't apply to post edit and the category parent dropdown list
410
+ $lang = $this->curlang;
 
411
 
412
  elseif (isset($_GET['post']))
413
  $lang = $this->model->get_post_language($_GET['post']);
480
  * @param int $value
481
  * @return int
482
  */
483
+ public function option_default_category($value) {
484
  $traces = debug_backtrace();
485
 
486
  return isset($traces[4]) && in_array($traces[4]['function'], array('column_cb', 'column_name')) && in_array($traces[4]['args'][0]->term_id, $this->model->get_translations('term', $value)) ?
487
  $traces[4]['args'][0]->term_id : $value;
488
  }
489
+
490
+ /*
491
+ * returns html markup for a translation link
492
+ *
493
+ * @since 1.4
494
+ *
495
+ * @param object $term_id translation term id
496
+ * @param string $taxonomy
497
+ * @param string $post_type
498
+ * @return string
499
+ */
500
+ public function edit_translation_link($term_id, $taxonomy, $post_type) {
501
+ return sprintf(
502
+ '<div class="spinner"></div><a href="%1$s" class="pll_icon_edit title="%2$s"></a></td>',
503
+ esc_url(get_edit_term_link($term_id, $taxonomy, $post_type)),
504
+ __('Edit','polylang')
505
+ );
506
+ }
507
+
508
+ /*
509
+ * returns html markup to add a new translation
510
+ *
511
+ * @since 1.4
512
+ *
513
+ * @param int $term_id id of the term to translate
514
+ * @param string $taxonomy
515
+ * @param string $post_type
516
+ * @param object $language language of the new translation
517
+ * @return string
518
+ */
519
+ public function add_new_translation_link($term_id, $taxonomy, $post_type, $language) {
520
+ $args = array(
521
+ 'taxonomy' => $taxonomy,
522
+ 'post_type' => $post_type,
523
+ 'from_tag' => $term_id,
524
+ 'new_lang' => $language->slug
525
+ );
526
+
527
+ return sprintf(
528
+ '<div class="spinner"></div><a href="%1$s" class="pll_icon_add" title="%2$s"></a>',
529
+ esc_url(add_query_arg($args, admin_url('edit-tags.php'))),
530
+ __('Add new','polylang')
531
+ );
532
+ }
533
  }
admin/admin-filters.php CHANGED
@@ -1,13 +1,11 @@
1
  <?php
2
 
3
  /*
4
- * setup miscellaneous admin filters
5
  *
6
  * @since 1.2
7
  */
8
- class PLL_Admin_Filters {
9
- public $links_model, $model, $options;
10
- public $pref_lang;
11
 
12
  /*
13
  * constructor: setups filters and actions
@@ -15,14 +13,10 @@ class PLL_Admin_Filters {
15
  * @since 1.2
16
  *
17
  * @param object $links_model
18
- * @param object $pref_lang language chosen in admin filter or default language
19
  */
20
- public function __construct(&$links_model, $pref_lang) {
21
- $this->links_model = &$links_model;
22
- $this->model = &$links_model->model;
23
- $this->options = &$this->model->options;
24
-
25
- $this->pref_lang = $pref_lang;
26
 
27
  // widgets languages filter
28
  add_action('in_widget_form', array(&$this, 'in_widget_form'));
@@ -36,10 +30,6 @@ class PLL_Admin_Filters {
36
  // ugrades languages files after a core upgrade (timing is important)
37
  // FIXME private action ? is there a better way to do this ?
38
  add_action( '_core_updated_successfully', array(&$this, 'upgrade_languages'), 1); // since WP 3.3
39
-
40
- // filters comments by language
41
- add_filter('comments_clauses', array(&$this, 'comments_clauses'), 10, 2);
42
-
43
  }
44
 
45
  /*
@@ -155,26 +145,4 @@ class PLL_Admin_Filters {
155
  if ($language->locale != $_POST['locale']) // do not (re)update the language files of a localized WordPress
156
  PLL_Admin::download_mo($language->locale, $version);
157
  }
158
-
159
- /*
160
- * filters comments by language
161
- *
162
- * @since 0.9
163
- *
164
- * @param array $clauses sql clauses
165
- * @param object $query WP_Comment_Query object
166
- * @return array modified clauses
167
- */
168
- public function comments_clauses($clauses, $query) {
169
- if (!empty($query->query_vars['lang']))
170
- $lang = $query->query_vars['lang'];
171
-
172
- elseif (!empty($_GET['lang']) && $_GET['lang'] != 'all')
173
- $lang = $this->model->get_language($_GET['lang']);
174
-
175
- elseif ($lg = get_user_meta(get_current_user_id(), 'pll_filter_content', true))
176
- $lang = $this->model->get_language($lg);
177
-
178
- return empty($lang) ? $clauses : $this->model->comments_clauses($clauses, $lang);
179
- }
180
  }
1
  <?php
2
 
3
  /*
4
+ * setup miscellaneous admin filters as well as filters common to admin and frontend
5
  *
6
  * @since 1.2
7
  */
8
+ class PLL_Admin_Filters extends PLL_Filters {
 
 
9
 
10
  /*
11
  * constructor: setups filters and actions
13
  * @since 1.2
14
  *
15
  * @param object $links_model
16
+ * @param object $curlang language chosen in admin filter
17
  */
18
+ public function __construct(&$links_model, &$curlang) {
19
+ parent::__construct($links_model, $curlang);
 
 
 
 
20
 
21
  // widgets languages filter
22
  add_action('in_widget_form', array(&$this, 'in_widget_form'));
30
  // ugrades languages files after a core upgrade (timing is important)
31
  // FIXME private action ? is there a better way to do this ?
32
  add_action( '_core_updated_successfully', array(&$this, 'upgrade_languages'), 1); // since WP 3.3
 
 
 
 
33
  }
34
 
35
  /*
145
  if ($language->locale != $_POST['locale']) // do not (re)update the language files of a localized WordPress
146
  PLL_Admin::download_mo($language->locale, $version);
147
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  }
admin/admin-model.php CHANGED
@@ -311,7 +311,7 @@ class PLL_Admin_Model extends PLL_Model {
311
  $posts = get_posts(array(
312
  'numberposts' => -1,
313
  'nopaging' => true,
314
- 'post_type' => $this->post_types,
315
  'post_status' => 'any',
316
  'fields' => 'ids',
317
  'tax_query' => array(array(
@@ -321,7 +321,7 @@ class PLL_Admin_Model extends PLL_Model {
321
  ))
322
  ));
323
 
324
- $terms = get_terms($this->taxonomies, array('get'=>'all', 'fields'=>'ids'));
325
  $groups = $this->get_languages_list(array('fields' => 'tl_term_id'));
326
  $tr_terms = get_objects_in_term($groups, 'term_language');
327
  $terms = array_unique(array_diff($terms, $tr_terms)); // array_unique to avoid duplicates if a term is in more than one taxonomy
311
  $posts = get_posts(array(
312
  'numberposts' => -1,
313
  'nopaging' => true,
314
+ 'post_type' => $this->get_translated_post_types(),
315
  'post_status' => 'any',
316
  'fields' => 'ids',
317
  'tax_query' => array(array(
321
  ))
322
  ));
323
 
324
+ $terms = get_terms($this->get_translated_taxonomies(), array('get'=>'all', 'fields'=>'ids'));
325
  $groups = $this->get_languages_list(array('fields' => 'tl_term_id'));
326
  $tr_terms = get_objects_in_term($groups, 'term_language');
327
  $terms = array_unique(array_diff($terms, $tr_terms)); // array_unique to avoid duplicates if a term is in more than one taxonomy
admin/admin-sync.php CHANGED
@@ -70,7 +70,7 @@ class PLL_Admin_Sync {
70
  // copy or synchronize terms
71
  if (!$sync || in_array('taxonomies', $this->options['sync'])) {
72
  // FIXME quite a lot of query in foreach
73
- foreach ($this->model->taxonomies as $tax) {
74
  $newterms = array();
75
  $terms = get_the_terms($from, $tax);
76
  if (is_array($terms)) {
70
  // copy or synchronize terms
71
  if (!$sync || in_array('taxonomies', $this->options['sync'])) {
72
  // FIXME quite a lot of query in foreach
73
+ foreach ($this->model->get_translated_taxonomies() as $tax) {
74
  $newterms = array();
75
  $terms = get_the_terms($from, $tax);
76
  if (is_array($terms)) {
admin/admin.php CHANGED
@@ -6,14 +6,12 @@
6
  * @since 1.2
7
  */
8
  class PLL_Admin extends PLL_Base {
9
- public $pref_lang;
10
  public $settings_page, $filters, $filters_columns, $filters_post, $filters_term, $nav_menu, $sync, $filters_media;
11
 
12
  /*
13
  * loads the polylang text domain
14
  * setups filters and action needed on all admin pages and on plugins page
15
- * loads the settings pages or the filters base on the request
16
- * manages the admin language filter and the "admin preferred language"
17
  *
18
  * @since 1.2
19
  *
@@ -30,6 +28,7 @@ class PLL_Admin extends PLL_Base {
30
 
31
  // setup js scripts and css styles
32
  add_action('admin_enqueue_scripts', array(&$this, 'admin_enqueue_scripts'));
 
33
 
34
  // adds a 'settings' link in the plugins table
35
  add_filter('plugin_action_links_' . POLYLANG_BASENAME, array(&$this, 'plugin_action_links'));
@@ -37,10 +36,8 @@ class PLL_Admin extends PLL_Base {
37
  }
38
 
39
  /*
40
- * loads the polylang text domain
41
  * setups filters and action needed on all admin pages and on plugins page
42
  * loads the settings pages or the filters base on the request
43
- * manages the admin language filter and the "admin preferred language"
44
  *
45
  * @since 1.2
46
  *
@@ -58,10 +55,8 @@ class PLL_Admin extends PLL_Base {
58
  // filter admin language for users
59
  // we must not call user info before WordPress defines user roles in wp-settings.php
60
  add_filter('setup_theme', array(&$this, 'init_user'));
61
- add_filter('locale', array(&$this, 'get_locale'));
62
 
63
  // adds the languages in admin bar
64
- // FIXME: OK for WP 3.2 and newer (the admin bar is not displayed on admin side for WP 3.1)
65
  add_action('admin_bar_menu', array(&$this, 'admin_bar_menu'), 100); // 100 determines the position
66
 
67
  // setup filters for admin pages
@@ -95,7 +90,7 @@ class PLL_Admin extends PLL_Base {
95
  $scripts = array(
96
  'admin' => array( array('settings_page_mlang'), array('jquery', 'wp-ajax-response', 'postbox'), 1 ),
97
  'post' => array( array('post', 'media', 'async-upload', 'edit'), array('jquery', 'wp-ajax-response', 'inline-edit-post'), 0 ),
98
- 'term' => array( array('edit-tags'), array('jquery', 'wp-ajax-response', 'inline-edit-tax'), 0 ),
99
  'user' => array( array('profile', 'user-edit'), array('jquery'), 0 ),
100
  );
101
 
@@ -111,6 +106,30 @@ class PLL_Admin extends PLL_Base {
111
  wp_enqueue_style('polylang_admin_mobi', POLYLANG_URL .'/css/admin-mobi'.$suffix.'.css', array(), POLYLANG_VERSION);
112
  }
113
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  /*
115
  * adds a 'settings' link in the plugins table
116
  *
@@ -143,14 +162,20 @@ class PLL_Admin extends PLL_Base {
143
  * @since 1.2.3
144
  */
145
  public function init_user() {
146
- // admin language filter
 
147
  if (!defined('DOING_AJAX') && !empty($_GET['lang']) && !is_numeric($_GET['lang']))
148
  update_user_meta(get_current_user_id(), 'pll_filter_content', ($lang = $this->model->get_language($_GET['lang'])) ? $lang->slug : '');
149
 
150
- // set preferred language for use in filters
151
- $this->pref_lang = $this->model->get_language(($lg = get_user_meta(get_current_user_id(), 'pll_filter_content', true)) ? $lg : $this->options['default_lang']);
 
 
152
  $this->pref_lang = apply_filters('pll_admin_preferred_language', $this->pref_lang);
153
 
 
 
 
154
  // inform that the admin language has been set
155
  // only if the admin language is one of the Polylang defined language
156
  if ($curlang = $this->model->get_language(get_locale())) {
@@ -179,10 +204,11 @@ class PLL_Admin extends PLL_Base {
179
  * @since 1.2
180
  */
181
  public function add_filters() {
182
- $this->filters = new PLL_Admin_Filters($this->links_model, $this->pref_lang);
183
- $this->filters_columns = new PLL_Admin_Filters_Columns($this->model);
184
- $this->filters_post = new PLL_Admin_Filters_Post($this->model, $this->pref_lang);
185
- $this->filters_term = new PLL_Admin_Filters_Term($this->model, $this->pref_lang);
 
186
  $this->nav_menu = new PLL_Admin_Nav_Menu($this->model);
187
  $this->sync = new PLL_Admin_Sync($this->model);
188
 
@@ -206,11 +232,7 @@ class PLL_Admin extends PLL_Base {
206
  'flag' => '<span class="ab-icon"></span>'
207
  );
208
 
209
- // $_GET['lang'] is numeric when editing a language, not when selecting a new language in the filter
210
- $selected = !empty($_GET['lang']) && !is_numeric($_GET['lang']) && ($lang = $this->model->get_language($_GET['lang'])) ? $lang->slug :
211
- (($lg = get_user_meta(get_current_user_id(), 'pll_filter_content', true)) ? $lg : 'all');
212
-
213
- $selected = ('all' == $selected) ? $all_item : $this->model->get_language($selected);
214
 
215
  $wp_admin_bar->add_menu(array(
216
  'id' => 'languages',
@@ -236,7 +258,7 @@ class PLL_Admin extends PLL_Base {
236
  /*
237
  * downloads mofiles from http://svn.automattic.com/wordpress-i18n/
238
  * FIXME is it the best class for this?
239
- * FIXME use language packs API coming with WP 3.7 instead
240
  *
241
  * @since 0.6
242
  *
6
  * @since 1.2
7
  */
8
  class PLL_Admin extends PLL_Base {
9
+ public $curlang, $pref_lang;
10
  public $settings_page, $filters, $filters_columns, $filters_post, $filters_term, $nav_menu, $sync, $filters_media;
11
 
12
  /*
13
  * loads the polylang text domain
14
  * setups filters and action needed on all admin pages and on plugins page
 
 
15
  *
16
  * @since 1.2
17
  *
28
 
29
  // setup js scripts and css styles
30
  add_action('admin_enqueue_scripts', array(&$this, 'admin_enqueue_scripts'));
31
+ add_action('admin_print_footer_scripts', array(&$this, 'admin_print_footer_scripts'));
32
 
33
  // adds a 'settings' link in the plugins table
34
  add_filter('plugin_action_links_' . POLYLANG_BASENAME, array(&$this, 'plugin_action_links'));
36
  }
37
 
38
  /*
 
39
  * setups filters and action needed on all admin pages and on plugins page
40
  * loads the settings pages or the filters base on the request
 
41
  *
42
  * @since 1.2
43
  *
55
  // filter admin language for users
56
  // we must not call user info before WordPress defines user roles in wp-settings.php
57
  add_filter('setup_theme', array(&$this, 'init_user'));
 
58
 
59
  // adds the languages in admin bar
 
60
  add_action('admin_bar_menu', array(&$this, 'admin_bar_menu'), 100); // 100 determines the position
61
 
62
  // setup filters for admin pages
90
  $scripts = array(
91
  'admin' => array( array('settings_page_mlang'), array('jquery', 'wp-ajax-response', 'postbox'), 1 ),
92
  'post' => array( array('post', 'media', 'async-upload', 'edit'), array('jquery', 'wp-ajax-response', 'inline-edit-post'), 0 ),
93
+ 'term' => array( array('edit-tags'), array('jquery', 'wp-ajax-response'), 0 ),
94
  'user' => array( array('profile', 'user-edit'), array('jquery'), 0 ),
95
  );
96
 
106
  wp_enqueue_style('polylang_admin_mobi', POLYLANG_URL .'/css/admin-mobi'.$suffix.'.css', array(), POLYLANG_VERSION);
107
  }
108
 
109
+ /*
110
+ * sets pll_ajax_backend on all backend ajax request
111
+ *
112
+ * @since 1.4
113
+ */
114
+ public function admin_print_footer_scripts() { ?>
115
+
116
+ <script type="text/javascript">
117
+ if (typeof jQuery != 'undefined') {
118
+ (function($){
119
+ $.ajaxPrefilter(function (options, originalOptions, jqXHR) {
120
+ if (typeof options.data == 'string') {
121
+ options.data = 'pll_ajax_backend=1&'+options.data;
122
+ }
123
+ else {
124
+ options.data = $.extend(options.data, {pll_ajax_backend: true});
125
+ }
126
+ });
127
+ })(jQuery)
128
+ }
129
+ </script><?php
130
+
131
+ }
132
+
133
  /*
134
  * adds a 'settings' link in the plugins table
135
  *
162
  * @since 1.2.3
163
  */
164
  public function init_user() {
165
+ // language for admin language filter: may be empty
166
+ // $_GET['lang'] is numeric when editing a language, not when selecting a new language in the filter
167
  if (!defined('DOING_AJAX') && !empty($_GET['lang']) && !is_numeric($_GET['lang']))
168
  update_user_meta(get_current_user_id(), 'pll_filter_content', ($lang = $this->model->get_language($_GET['lang'])) ? $lang->slug : '');
169
 
170
+ $this->curlang = $this->model->get_language(get_user_meta(get_current_user_id(), 'pll_filter_content', true));
171
+
172
+ // set preferred language for use when saving posts and terms: must not be empty
173
+ $this->pref_lang = empty($this->curlang) ? $this->model->get_language($this->options['default_lang']) : $this->curlang;
174
  $this->pref_lang = apply_filters('pll_admin_preferred_language', $this->pref_lang);
175
 
176
+ // backend locale
177
+ add_filter('locale', array(&$this, 'get_locale'));
178
+
179
  // inform that the admin language has been set
180
  // only if the admin language is one of the Polylang defined language
181
  if ($curlang = $this->model->get_language(get_locale())) {
204
  * @since 1.2
205
  */
206
  public function add_filters() {
207
+ // all these are separated just for convenience and maintainability
208
+ $this->filters = new PLL_Admin_Filters($this->links_model, $this->curlang);
209
+ $this->filters_columns = new PLL_Admin_Filters_Columns($this->model, $this->curlang);
210
+ $this->filters_post = new PLL_Admin_Filters_Post($this->model, $this->curlang, $this->pref_lang);
211
+ $this->filters_term = new PLL_Admin_Filters_Term($this->model, $this->curlang, $this->pref_lang);
212
  $this->nav_menu = new PLL_Admin_Nav_Menu($this->model);
213
  $this->sync = new PLL_Admin_Sync($this->model);
214
 
232
  'flag' => '<span class="ab-icon"></span>'
233
  );
234
 
235
+ $selected = empty($this->curlang) ? $all_item : $this->curlang;
 
 
 
 
236
 
237
  $wp_admin_bar->add_menu(array(
238
  'id' => 'languages',
258
  /*
259
  * downloads mofiles from http://svn.automattic.com/wordpress-i18n/
260
  * FIXME is it the best class for this?
261
+ * FIXME use language packs API coming with WP 3.7 instead (does not seem to work fully yet)
262
  *
263
  * @since 0.6
264
  *
admin/view-translations-media.php CHANGED
@@ -1,79 +1,36 @@
1
  <?php
2
-
3
- // backward compatibility WP < 3.5
4
- if (version_compare($GLOBALS['wp_version'], '3.5', '<')) {?>
5
- <table class="widefat media-translations">
6
- <thead><tr><?php
7
- echo '<th class="tr-language-column">'.__('Language', 'polylang').'</th>';
8
- echo '<th class="tr-edit-column">'.__('Translation', 'polylang').'</th>';?>
9
- </tr></thead>
10
-
11
- <tbody><?php
12
- foreach ($this->model->get_languages_list() as $language) {
13
- if ($language->term_id == $lang->term_id)
14
- continue;?>
15
-
16
- <tr><td class="tr-language-column"><?php echo esc_html($language->name);?></td><?php
17
- // the translation exists
18
- if (($translation_id = $this->model->get_translation('post', $post_id, $language)) && $translation_id != $post_id) {
19
- printf(
20
- '<td class="tr-edit-column"><input type="hidden" name="media_tr_lang[%s]" value="%d" /><a href="%s">%s</a></td>',
21
- esc_attr($language->slug),
22
- esc_attr($translation_id),
23
- esc_url(admin_url(sprintf('media.php?attachment_id=%d&action=edit', $translation_id))),
24
- __('Edit','polylang')
25
- );
26
- }
27
-
28
- // no translation
29
- else {
30
- printf(
31
- '<td class="tr-edit-column"><a href="%1$s">%2$s</a></td>',
32
- esc_url(admin_url(sprintf('admin.php?action=translate_media&from_media=%d&new_lang=%s', $post_id, $language->slug))),
33
- __('Add new','polylang')
34
- );
35
- }?>
36
- </tr><?php
37
- } // foreach ?>
38
- </tbody>
39
- </table><?php
40
- }
41
-
42
- else { // WP 3.5+ ?>
43
- <p><em><?php _e('Translations', 'polylang');?></em></p>
44
- <table>
45
- <thead><tr>
46
- <th><?php _e('Language', 'polylang');?></th>
47
- <th><?php _e('Translation', 'polylang');?></th>
48
- </tr></thead>
49
-
50
- <tbody><?php
51
- foreach ($this->model->get_languages_list() as $language) {
52
- if ($language->term_id == $lang->term_id)
53
- continue;?>
54
-
55
- <tr><td><?php echo esc_html($language->name);?></td><?php
56
- // the translation exists
57
- if (($translation_id = $this->model->get_translation('post', $post_id, $language)) && $translation_id != $post_id) {
58
- printf(
59
- '<td><input type="hidden" name="media_tr_lang[%s]" value="%d" /><a href="%s">%s</a></td>',
60
- esc_attr($language->slug),
61
- esc_attr($translation_id),
62
- esc_url(get_edit_post_link($translation_id)),
63
- __('Edit','polylang')
64
- );
65
- }
66
-
67
- // no translation
68
- else {
69
- printf(
70
- '<td><a href="%1$s">%2$s</a></td>',
71
- esc_url(admin_url(sprintf('admin.php?action=translate_media&from_media=%d&new_lang=%s', $post_id, $language->slug))),
72
- __('Add new','polylang')
73
- );
74
- }?>
75
- </tr><?php
76
- } // foreach ?>
77
- </tbody>
78
- </table><?php
79
- }
1
  <?php
2
+ // needs WP 3.5+
3
+ ?>
4
+
5
+ <p><strong><?php _e('Translations', 'polylang');?></strong></p>
6
+ <table><?php
7
+ foreach ($this->model->get_languages_list() as $language) {
8
+ if ($language->term_id == $lang->term_id)
9
+ continue;?>
10
+
11
+ <tr>
12
+ <td class = "pll-media-language-column"><?php echo esc_html($language->name); ?></td>
13
+ <td class = "pll-edit-column"><?php
14
+ // the translation exists
15
+ if (($translation_id = $this->model->get_translation('post', $post_id, $language)) && $translation_id != $post_id) {
16
+ printf(
17
+ '<input type="hidden" name="media_tr_lang[%s]" value="%d" /><a href="%s" title="%s" class="pll_icon_edit"></a>',
18
+ esc_attr($language->slug),
19
+ esc_attr($translation_id),
20
+ esc_url(get_edit_post_link($translation_id)),
21
+ __('Edit','polylang')
22
+ );
23
+ }
24
+
25
+ // no translation
26
+ else {
27
+ printf(
28
+ '<a href="%s" title="%s" class="pll_icon_add"></a>',
29
+ esc_url(admin_url(sprintf('admin.php?action=translate_media&from_media=%d&new_lang=%s', $post_id, $language->slug))),
30
+ __('Add new','polylang')
31
+ );
32
+ }?>
33
+ </td>
34
+ </tr><?php
35
+ } // foreach ?>
36
+ </table>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/view-translations-post.php CHANGED
@@ -2,57 +2,49 @@
2
  // displays the translations fields
3
  ?>
4
 
5
- <p><em><?php $post_type == 'page' ? _e('ID of pages in other languages:', 'polylang') : _e('ID of posts in other languages:', 'polylang');?></em></p>
6
- <table>
7
- <thead>
8
- <tr>
9
- <th><?php _e('Language', 'polylang');?></th>
10
- <th><?php $post_type == 'page' ? _e('Page ID', 'polylang') : _e('Post ID', 'polylang');?></th>
11
- <th><?php _e('Edit', 'polylang');?></th>
12
- </tr>
13
- </thead>
14
 
15
- <tbody>
16
  <?php foreach ($this->model->get_languages_list() as $language) {
17
- if ($language->term_id != $lang->term_id) {
18
- $value = $this->model->get_translation('post', $post_ID, $language);
19
- if (!$value || $value == $post_ID) // $value == $post_ID happens if the post has been (auto)saved before changing the language
20
- $value = '';
21
- if (isset($_GET['from_post']))
22
- $value = $this->model->get_post($_GET['from_post'], $language); ?>
23
- <tr>
24
- <td><?php echo esc_html($language->name);?></td><?php
25
- printf(
26
- '<td><input name="post_tr_lang[%1$s]" id="tr_lang_%1$s" class="tags-input" type="text" value="%2$s" size="6"/></td>',
27
- esc_attr($language->slug),
28
- esc_attr($value)
29
- );
30
-
31
- if ($lang) {
32
- if ($value) {
33
- $link = sprintf(
34
- '<a href="%1$s">%2$s</a>',
35
- esc_url(get_edit_post_link($value)),
36
- __('Edit','polylang')
37
- );
38
- }
39
- else {
40
- $args = array(
41
- 'post_type' => $post_type,
42
- 'from_post' => $post_ID,
43
- 'new_lang' => $language->slug
44
- );
45
-
46
- $link = sprintf(
47
- '<a href="%1$s">%2$s</a>',
48
- esc_url(add_query_arg($args, admin_url('post-new.php'))),
49
- __('Add new','polylang')
50
- );
51
- } ?>
52
- <td><?php echo $link ?><td><?php
53
- }?>
54
- </tr><?php
55
  }
56
- } ?>
57
- </tbody>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  </table>
2
  // displays the translations fields
3
  ?>
4
 
5
+ <p><strong><?php _e('Translations', 'polylang');?></strong></p>
 
 
 
 
 
 
 
 
6
 
7
+ <table>
8
  <?php foreach ($this->model->get_languages_list() as $language) {
9
+ if ($language->term_id == $lang->term_id)
10
+ continue;
11
+
12
+ $posts = $this->get_posts_not_translated($post_type, $language, $lang);
13
+
14
+ $value = $this->model->get_translation('post', $post_ID, $language);
15
+ if (!$value || $value == $post_ID) // $value == $post_ID happens if the post has been (auto)saved before changing the language
16
+ $value = '';
17
+ if (isset($_GET['from_post']))
18
+ $value = $this->model->get_post($_GET['from_post'], $language);
19
+
20
+ if ($value) {
21
+ $selected = get_post($value);
22
+
23
+ // move the current post on top of the list
24
+ foreach ($posts as $key => $post) {
25
+ if ($post->ID == $selected->ID)
26
+ unset($posts[$key]);
27
+ }
28
+
29
+ array_unshift($posts, $selected);
30
+
31
+ $link = $this->edit_translation_link($value);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  }
33
+
34
+ else {
35
+ $link = $this->add_new_translation_link($post_ID, $post_type, $language);
36
+ } ?>
37
+
38
+ <tr>
39
+ <td class = "pll-language-column"><?php echo $language->flag ? $language->flag : esc_html($language->slug); ?></td>
40
+ <td class = "pll-edit-column"><?php echo $link;?></td>
41
+ <td class = "pll-translation-column"><?php
42
+ printf('<select name="post_tr_lang[%1$s]" id="tr_lang_%1$s" class="tags-input"><option value="">%2$s</option>%3$s</select>',
43
+ esc_attr($language->slug),
44
+ __('None'),
45
+ walk_page_dropdown_tree($posts, 0, array('selected' => $value))
46
+ ); ?>
47
+ </td>
48
+ </tr><?php
49
+ }?>
50
  </table>
admin/view-translations-term.php CHANGED
@@ -11,83 +11,56 @@ else {
11
  <label><?php _e('Translations', 'polylang');?></label><?php
12
  }?>
13
  <table class="widefat term-translations">
14
- <thead><tr><?php
15
- echo '<th class="tr-language-column">'.__('Language', 'polylang').'</th>';
16
- echo '<th>'.__('Translation', 'polylang').'</th>';
17
- if (isset($term_id))
18
- echo '<th class="tr-edit-column">'.__('Edit', 'polylang').'</th>';?>
19
- </tr></thead>
20
- <tbody>
21
- <?php foreach ($this->model->get_languages_list() as $language) {
22
- if ($language->term_id == $lang->term_id)
23
- continue;
24
 
25
- // look for any existing translation in this language
26
- $translation = 0;
27
- if (isset($term_id) && $translation_id = $this->model->get_translation('term', $term_id, $language))
28
- $translation = get_term($translation_id, $taxonomy);
29
- if (isset($_GET['from_tag']) && $translation_id = $this->model->get_term($_GET['from_tag'], $language))
30
- $translation = get_term($translation_id, $taxonomy);?>
31
 
32
- <tr><td class="tr-language-column"><?php echo esc_html($language->name);?></td><?php
 
 
 
 
 
33
 
34
- // no translation exists in this language
35
- if (!$translation) {
36
- // look for untranslated terms in this language
37
- $translations = $this->get_terms_not_translated($taxonomy, $language, $lang);
38
- if (!empty($translations)) { ?>
39
- <td>
40
- <?php printf('<select name="term_tr_lang[%1$s]" id="tr_lang_%1$s">', esc_attr($language->slug)); ?>
41
- <option value="0"></option><?php
42
- foreach ($translations as $translation) {
43
- printf(
44
- '<option value="%s">%s</option>',
45
- esc_attr($translation->term_id),
46
- esc_html($translation->name)
47
- );
48
- }?>
49
- </select>
50
- </td><?php
51
- }
52
- else {?>
53
- <td><?php _e('No untranslated term', 'polylang'); ?></td><?php
54
- }
55
 
56
- // do not display the add new link in add term form ($term_id not set !!!)
57
- if (isset($term_id)) {
58
- $args = array(
59
- 'taxonomy' => $taxonomy,
60
- 'post_type' => $post_type,
61
- 'from_tag' => $term_id,
62
- 'new_lang' => $language->slug
63
- );
64
- printf(
65
- '<td class="tr-edit-column"><a href="%1$s">%2$s</a></td>',
66
- esc_url(add_query_arg($args, admin_url('edit-tags.php'))),
67
- __('Add new','polylang')
68
- );
69
- }
70
  }
71
 
72
- // a translation exists
73
- else {
74
- printf(
75
- '<td><input type="hidden" name="term_tr_lang[%s]" value="%d" />%s</td>',
76
- esc_attr($language->slug),
77
- esc_attr($translation->term_id),
78
- esc_html($translation->name)
79
- );
80
- if (isset($term_id)) {
81
- printf(
82
- '<td class="tr-edit-column"><a href="%1$s">%2$s</a></td>',
83
- esc_url(get_edit_term_link($translation->term_id, $taxonomy, $post_type)),
84
- __('Edit','polylang')
85
- );
86
- }
 
87
  } ?>
88
- </tr><?php
89
- } // foreach ?>
90
- </tbody>
 
 
 
 
 
 
 
 
 
91
  </table><?php
92
 
93
  if (isset($term_id)) {
11
  <label><?php _e('Translations', 'polylang');?></label><?php
12
  }?>
13
  <table class="widefat term-translations">
14
+ <?php foreach ($this->model->get_languages_list() as $language) {
15
+ if ($language->term_id == $lang->term_id)
16
+ continue;
 
 
 
 
 
 
 
17
 
18
+ $translations = $this->get_terms_not_translated($taxonomy, $language, $lang);
 
 
 
 
 
19
 
20
+ // look for any existing translation in this language
21
+ $translation = 0;
22
+ if (isset($term_id) && $translation_id = $this->model->get_translation('term', $term_id, $language))
23
+ $translation = get_term($translation_id, $taxonomy);
24
+ if (isset($_GET['from_tag']) && $translation_id = $this->model->get_term($_GET['from_tag'], $language))
25
+ $translation = get_term($translation_id, $taxonomy);
26
 
27
+ $link = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
+ if ($translation) {
30
+ foreach ($translations as $key => $term) {
31
+ if ($term->term_id == $translation->term_id)
32
+ unset($translations[$key]);
 
 
 
 
 
 
 
 
 
 
33
  }
34
 
35
+ array_unshift($translations, $translation);
36
+
37
+ $link = $this->edit_translation_link($translation->term_id, $taxonomy, $post_type);
38
+ }
39
+
40
+ elseif (isset($term_id)) { // do not display the add new link in add term form ($term_id not set !!!)
41
+ $link = $this->add_new_translation_link($term_id, $taxonomy, $post_type, $language);
42
+ } ?>
43
+
44
+ <tr><?php
45
+ if (isset($term_id)) { ?>
46
+ <td class = "pll-language-column"><?php echo esc_html($language->name); ?></td>
47
+ <td class = "pll-edit-column"><?php echo $link;?></td><?php
48
+ }
49
+ else { ?>
50
+ <td class = "pll-language-column"><?php echo $language->flag ? $language->flag : esc_html($language->slug); ?></td><?php
51
  } ?>
52
+ <td class = "pll-translation-column"><?php
53
+ printf('<select name="term_tr_lang[%1$s]" id="tr_lang_%1$s"><option value="">%2$s</option>%3$s</select>',
54
+ esc_attr($language->slug),
55
+ __('None'),
56
+ walk_category_dropdown_tree($translations, 0, array(
57
+ 'selected' => empty($translation) ? 0 : $translation->term_id,
58
+ 'show_count' => 0
59
+ ))
60
+ ); ?>
61
+ </td>
62
+ </tr><?php
63
+ } // foreach ?>
64
  </table><?php
65
 
66
  if (isset($term_id)) {
changelog.txt CHANGED
@@ -1,5 +1,29 @@
1
  == Changelog ==
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  = 1.2.4 (2013-11-28) =
4
 
5
  * Better support for theme customizer
1
  == Changelog ==
2
 
3
+ This file contains only old changelog. See readme.txt for newer versions.
4
+
5
+ = 1.3.1 (2013-12-13) =
6
+
7
+ * Bug correction: fatal error on settings page if a static front page without language is set
8
+ * Bug correction: wrong home url when using different domains per language
9
+
10
+ = 1.3 (2013-12-11) =
11
+
12
+ * Refresh admin UI for better look in WP 3.8 and more dynamic comportment
13
+ * The "Detect browser language" option does now also controls returning visits (based on cookie).
14
+ * Improved performance by optimizing some queries for WP 3.5+
15
+ * The user biography in default language is now stored in default WordPress usermeta
16
+ * Add language parameter in API function pll_home_url and allow to call it on admin side
17
+ * Calling 'get_terms' with the 'lang' parameter now uses a cache object per language
18
+ * Bug correction: conflict with unstranslated taxonomies
19
+ * Bug correction: possible malformed translation archive url in language switcher
20
+ * Bug correction: a wrong language may be displayed in quick edit dropdown
21
+ * Bug correction: it is possible to add multiple translations (in the same language) for a single taxonomy term
22
+ * Bug correction: non public post types and taxonomies are visible in Polylang settings
23
+ * Bug correction: the language is always chosen from cookie (or browser preferences) in some installations
24
+ * Bug correction: Firefox language preference is not recognized when comparison is made on locale (instead of ISO 639-1 language code)
25
+ * Bug correction: incorrect tax_query in PLL_Auto_Translate
26
+
27
  = 1.2.4 (2013-11-28) =
28
 
29
  * Better support for theme customizer
css/admin.css CHANGED
@@ -69,51 +69,50 @@ th[class*='column-language_'] {
69
 
70
  /* languages metabox in post.php */
71
  #post-translations table {
 
72
  width: 100%;
73
- text-align: left;
74
- font-size: 11px;
75
- margin: 0 6px;
76
  }
77
 
78
- #post-translations td {
79
- font-size: 11px;
80
  }
81
 
82
- /* language and translations in edit-tags.php as well as media translations in upload.php */
83
- #term-translations table {
84
- width: 97%;
85
  }
86
 
87
- #term-translations .term-translations th, .media-item .describe .media-translations th {
88
- padding: 8px 10px;
89
  }
90
 
91
- #term-translations .term-translations td, .media-item .describe .media-translations td {
92
- font-size: 12px;
93
- line-height: 26px;
94
- margin-bottom: 9px;
95
- padding: 4px 10px;
96
  }
97
 
98
- .tr-language-column {
99
- width: 35%;
100
  }
101
 
102
- div#term-translations select[id*='tr_lang_'] {
103
- width: 95%;
 
104
  }
105
 
106
- tr#term-translations select[id*='tr_lang_'] {
107
- width: 65%;
 
108
  }
109
 
110
- .tr-edit-column {
111
- width: 15%;
 
112
  }
113
 
114
- /* media translations in upload.php */
115
- .media-translations {
116
- width: 460px;
117
  }
118
 
119
  /* icon fonts */
69
 
70
  /* languages metabox in post.php */
71
  #post-translations table {
72
+ table-layout: fixed;
73
  width: 100%;
 
 
 
74
  }
75
 
76
+ #post-translations a {
77
+ text-decoration: none;
78
  }
79
 
80
+ #post-translations .pll-language-column, #post-translations .pll-edit-column {
81
+ width: 10%;
 
82
  }
83
 
84
+ #post-translations td {
85
+ padding: 2px;
86
  }
87
 
88
+ #post-translations .spinner, #term-translations .spinner {
89
+ float: none;
90
+ margin: 0;
91
+ background-position: center;
92
+ width: auto;
93
  }
94
 
95
+ .pll-edit-column {
96
+ text-align: center;
97
  }
98
 
99
+ /* specific case for media */
100
+ #post-translations .pll-media-language-column {
101
+ width: 60%;
102
  }
103
 
104
+ /* language and translations in edit-tags.php */
105
+ #term-translations table {
106
+ width: 97%;
107
  }
108
 
109
+ #term-translations .pll-language-column {
110
+ line-height: 28px;
111
+ width: 20%;
112
  }
113
 
114
+ #term-translations .pll-edit-column {
115
+ width: 10%;
 
116
  }
117
 
118
  /* icon fonts */
css/admin.min.css CHANGED
@@ -1 +1 @@
1
- .column-term_group,.column-flag,.column-count{width:10%}.form-field input[type="radio"]{width:auto;margin-right:2px}#pll_about_box p{text-align:justify}#pll_about_box input{margin:0;padding:0;float:right}#string-translation .search-box{margin:16px 0 8px 0}.stringstranslations .column-name,.stringstranslations .column-context{width:10%}.stringstranslations .column-string{width:33%}.translation label{display:inline-block;width:23%;vertical-align:top}.translation input,.translation textarea{width:72%}.pll_inline_block{margin:0}.pll_inline_block li{display:inline-block;margin:0;width:250px}#pll-domains-table td{padding:2px 2px 2px 1.5em}#pll-force-lang .description{margin-top:0;margin-bottom:.5em}th[class*='column-language_']{width:2em}#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 .term-translations th,.media-item .describe .media-translations th{padding:8px 10px}#term-translations .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}@font-face{font-family:'polylang';src:url('polylang.eot')}@font-face{font-family:'polylang';src:url(data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAcMAA0AAAAAC0QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABMAAAABwAAAAcZv8wr0dERUYAAAFMAAAAJAAAACgANwAmT1MvMgAAAXAAAAA9AAAAYBrwD0djbWFwAAABsAAAAEoAAAFKy/cg/2dhc3AAAAH8AAAACAAAAAgAAAAQZ2x5ZgAAAgQAAANnAAAFwJS/ONtoZWFkAAAFbAAAAC4AAAA2BAEDkWhoZWEAAAWcAAAAGwAAACQO2QfWaG10eAAABbgAAAAZAAAAGg8aAMhsb2NhAAAF1AAAABIAAAASA5wBPm1heHAAAAXoAAAAGAAAACAAGgE8bmFtZQAABgAAAADfAAABsAm7glFwb3N0AAAG4AAAACwAAABSfIE0tAAAAAEAAAAAyYlvMQAAAADOumXnAAAAAM67W5Z4nGNgZGBg4ANiCQYFIMnEwMjAzMAOJFnAPAYGRggGAAo7AF54nGNgZudgnMDAysDAKsxaxsDAKA6hmfczpDCxMaACRgE0AQYHBoVnzOwXGBj+N7PnoEsyKDAwAgBguwdcAAAAeJxjYGBgZoBgGQZGBhBwAfIYwXwWBg0gzQakGRmYGBSeMf//D+QrPGP4////YykWqHogYGRjgHMYmYAEEwMqYIRYMZwBALsxCN4AAAABAAH//wAPeJyVVN9r21YUvkdX0tWVLcnX+mHHlRXfKJYz6qZjjhOaGRcGS7v1pdv+gEJb8lI/pA/rShoKZTDaQvaylZW9LaRv+wFjDyNsjxsMxgZhb6Pda2ErDaNQiGOxK9ny5tAVqg8kHZ1zvvOdcy5CgLJLQuiEJO4X0UXSIz1URSFC8ErJS+A6RE0QzjSiBO2FpS7M2tAATPDD77e21zdeX1k5tb6xdW9nbD2BN5j0+9nBu7/eI73Dzsx6srn/Jj7z1uARaJ8LFTCuf+o/1VlS3oSQs0wHT4TMQ5vxTBFbWFoUolo8fRFo8SQ9AJeRBYtQTceyrGjEyQ/uiKdO9Hz8ZfKd6IM7E37p0sgPbw/98k8vmCBdOlQQ4XFfZTFZLjpNpY3asQCGmoVqihUx1pK6udqImjLWFIOal+P31tyC7RV8b2r/hszgdv9xrMp/Xjh4dJ70mo1odblY9TzDt4trcOsyE8VVRd7/W2bxlf7jNfnmhYO/ziM21hCgedQVEz6HrqDr6EP0CfoK/Yh+QX+gp5CHWTjx3M0LlbPQGuldCp1kNRCqwzjSWkjWUOcuXzwuRXUeNSaRfG0oSY4I5syCLFHA5haY4HJoRcP1hl66wro6LXklLrbtlSaROupJRSGFs5OQyRLA/CR0oc3rgu3ltPaIzh6yjyVlZPVUk2hhMT1KS8I0AQ9zxhWzJKU73FnauIgUZhfww++2tq+lB/zaxtb2zr/WOpyWvt2lBqE6VqQ9Vca0H0/a+IN4B1aV5MDFX0NoYKpRXbGYWSzky54FruvkaPyFrucKVNMgdJycToyiPZWTq+zneCevyyqsDnq7QImE1T0gihgpvJoyarAS3382JbwzoozvT1LCSkIZfwoPBFdepbohqBUZq1ct6qimb5UqkVmt1I54zpGcYxSMft/yDc02ct+YluGyOS9YrjTZR/8TLSvPik5+FYdml1nrm/2zTuTMHbOCWq0bBMtSZ8L096ROpxN8zDXXsYu0UrXLtuk5OtZzVJF+YEU7ch0XzhGqqFg3WMlQIifeXe4EnVp8V24fLQTdmjcXBEHnt5TJ34vvPp8s/myCDOZTsqveXEew+HK7GgRdOF3OVUihZk2507pjFfM+b5aPTjdeet+qFegUY8fCoBm+5hszxRnjwHiBYPQPEYECsgB4nGNgZGBgAOLJSpOl4vltvjJws18AijCc2x29Bplmz2HPAVIcDEwgHgAn0gn2AAB4nGNgZGBgz2EAAvYLYDKHgZEBFbACACvnAcUAeJxjYIAAplkMDMwvGBjYLzCkQCAAJEAD7wAAAAAAAAAAAAAAAAgASAC0APYC4AAAeJxjYGRgYOBgtGIQZAABJgY0AAAIhABYeJx9kD1OQkEUhb/3AyomxEItzZRW5FVsASkotLAfYEJIXmbMAMXrWYBrsHUf7sD9eIBr+ya5mW/O3HNucoE7fij4P6VxwTUPxiVXTIwr6S/GtXhlPOCWo/FQ+pfxiHt+5SrqG5tw4UJzK+OSMU/GlfSpcS1+NR7wSGs8lP5pPOKZ71PsB0kNncoT2UhIbdf6KHojSDicv7KeYXNofe619Hy9Ky2zY6uWiKPRbhrJIe+2Kbpm0vTaZ7LHc4Rnr3utiKVaHXMtM7FQnYKZhRiy34e1W3ZuvkqLlCJ/Md4+aQB4nGNgYsAPOICYkYGJgZmRiZGZkYWRlb00L9PVzMAAShtCaSMobQwAmAoI4Q==) format('woff'),url('polylang.ttf') format('truetype'),url('polylang.svg#polylang') format('svg');font-weight:normal;font-style:normal}.pll_icon_tick:before{content:"\e600"}.pll_icon_add:before{content:"\e601"}.pll_icon_edit:before{content:"\e602"}[class^="pll_icon_"],#wpadminbar #wp-admin-bar-languages .ab-icon:before{font-family:'polylang'}#wpadminbar #wp-admin-bar-languages .ab-item img{margin:0 8px 0 2px}#wpadminbar #wp-admin-bar-languages #wp-admin-bar-all .ab-item .ab-icon{float:none;top:4px}#wpadminbar #wp-admin-bar-languages .ab-icon:before{font:20px/1 'polylang';content:"\e603";top:1px}#wpadminbar #wp-admin-bar-languages .ab-item .ab-icon{margin:0 6px 0 0;padding:4px 0}
1
+ .column-term_group,.column-flag,.column-count{width:10%}.form-field input[type="radio"]{width:auto;margin-right:2px}#pll_about_box p{text-align:justify}#pll_about_box input{margin:0;padding:0;float:right}#string-translation .search-box{margin:16px 0 8px 0}.stringstranslations .column-name,.stringstranslations .column-context{width:10%}.stringstranslations .column-string{width:33%}.translation label{display:inline-block;width:23%;vertical-align:top}.translation input,.translation textarea{width:72%}.pll_inline_block{margin:0}.pll_inline_block li{display:inline-block;margin:0;width:250px}#pll-domains-table td{padding:2px 2px 2px 1.5em}#pll-force-lang .description{margin-top:0;margin-bottom:.5em}th[class*='column-language_']{width:2em}#post-translations table{table-layout:fixed;width:100%}#post-translations a{text-decoration:none}#post-translations .pll-language-column,#post-translations .pll-edit-column{width:10%}#post-translations td{padding:2px}#post-translations .spinner,#term-translations .spinner{float:none;margin:0;background-position:center;width:auto}.pll-edit-column{text-align:center}#post-translations .pll-media-language-column{width:60%}#term-translations table{width:97%}#term-translations .pll-language-column{line-height:28px;width:20%}#term-translations .pll-edit-column{width:10%}@font-face{font-family:'polylang';src:url('polylang.eot')}@font-face{font-family:'polylang';src:url(data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAcMAA0AAAAAC0QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABMAAAABwAAAAcZv8wr0dERUYAAAFMAAAAJAAAACgANwAmT1MvMgAAAXAAAAA9AAAAYBrwD0djbWFwAAABsAAAAEoAAAFKy/cg/2dhc3AAAAH8AAAACAAAAAgAAAAQZ2x5ZgAAAgQAAANnAAAFwJS/ONtoZWFkAAAFbAAAAC4AAAA2BAEDkWhoZWEAAAWcAAAAGwAAACQO2QfWaG10eAAABbgAAAAZAAAAGg8aAMhsb2NhAAAF1AAAABIAAAASA5wBPm1heHAAAAXoAAAAGAAAACAAGgE8bmFtZQAABgAAAADfAAABsAm7glFwb3N0AAAG4AAAACwAAABSfIE0tAAAAAEAAAAAyYlvMQAAAADOumXnAAAAAM67W5Z4nGNgZGBg4ANiCQYFIMnEwMjAzMAOJFnAPAYGRggGAAo7AF54nGNgZudgnMDAysDAKsxaxsDAKA6hmfczpDCxMaACRgE0AQYHBoVnzOwXGBj+N7PnoEsyKDAwAgBguwdcAAAAeJxjYGBgZoBgGQZGBhBwAfIYwXwWBg0gzQakGRmYGBSeMf//D+QrPGP4////YykWqHogYGRjgHMYmYAEEwMqYIRYMZwBALsxCN4AAAABAAH//wAPeJyVVN9r21YUvkdX0tWVLcnX+mHHlRXfKJYz6qZjjhOaGRcGS7v1pdv+gEJb8lI/pA/rShoKZTDaQvaylZW9LaRv+wFjDyNsjxsMxgZhb6Pda2ErDaNQiGOxK9ny5tAVqg8kHZ1zvvOdcy5CgLJLQuiEJO4X0UXSIz1URSFC8ErJS+A6RE0QzjSiBO2FpS7M2tAATPDD77e21zdeX1k5tb6xdW9nbD2BN5j0+9nBu7/eI73Dzsx6srn/Jj7z1uARaJ8LFTCuf+o/1VlS3oSQs0wHT4TMQ5vxTBFbWFoUolo8fRFo8SQ9AJeRBYtQTceyrGjEyQ/uiKdO9Hz8ZfKd6IM7E37p0sgPbw/98k8vmCBdOlQQ4XFfZTFZLjpNpY3asQCGmoVqihUx1pK6udqImjLWFIOal+P31tyC7RV8b2r/hszgdv9xrMp/Xjh4dJ70mo1odblY9TzDt4trcOsyE8VVRd7/W2bxlf7jNfnmhYO/ziM21hCgedQVEz6HrqDr6EP0CfoK/Yh+QX+gp5CHWTjx3M0LlbPQGuldCp1kNRCqwzjSWkjWUOcuXzwuRXUeNSaRfG0oSY4I5syCLFHA5haY4HJoRcP1hl66wro6LXklLrbtlSaROupJRSGFs5OQyRLA/CR0oc3rgu3ltPaIzh6yjyVlZPVUk2hhMT1KS8I0AQ9zxhWzJKU73FnauIgUZhfww++2tq+lB/zaxtb2zr/WOpyWvt2lBqE6VqQ9Vca0H0/a+IN4B1aV5MDFX0NoYKpRXbGYWSzky54FruvkaPyFrucKVNMgdJycToyiPZWTq+zneCevyyqsDnq7QImE1T0gihgpvJoyarAS3382JbwzoozvT1LCSkIZfwoPBFdepbohqBUZq1ct6qimb5UqkVmt1I54zpGcYxSMft/yDc02ct+YluGyOS9YrjTZR/8TLSvPik5+FYdml1nrm/2zTuTMHbOCWq0bBMtSZ8L096ROpxN8zDXXsYu0UrXLtuk5OtZzVJF+YEU7ch0XzhGqqFg3WMlQIifeXe4EnVp8V24fLQTdmjcXBEHnt5TJ34vvPp8s/myCDOZTsqveXEew+HK7GgRdOF3OVUihZk2507pjFfM+b5aPTjdeet+qFegUY8fCoBm+5hszxRnjwHiBYPQPEYECsgB4nGNgZGBgAOLJSpOl4vltvjJws18AijCc2x29Bplmz2HPAVIcDEwgHgAn0gn2AAB4nGNgZGBgz2EAAvYLYDKHgZEBFbACACvnAcUAeJxjYIAAplkMDMwvGBjYLzCkQCAAJEAD7wAAAAAAAAAAAAAAAAgASAC0APYC4AAAeJxjYGRgYOBgtGIQZAABJgY0AAAIhABYeJx9kD1OQkEUhb/3AyomxEItzZRW5FVsASkotLAfYEJIXmbMAMXrWYBrsHUf7sD9eIBr+ya5mW/O3HNucoE7fij4P6VxwTUPxiVXTIwr6S/GtXhlPOCWo/FQ+pfxiHt+5SrqG5tw4UJzK+OSMU/GlfSpcS1+NR7wSGs8lP5pPOKZ71PsB0kNncoT2UhIbdf6KHojSDicv7KeYXNofe619Hy9Ky2zY6uWiKPRbhrJIe+2Kbpm0vTaZ7LHc4Rnr3utiKVaHXMtM7FQnYKZhRiy34e1W3ZuvkqLlCJ/Md4+aQB4nGNgYsAPOICYkYGJgZmRiZGZkYWRlb00L9PVzMAAShtCaSMobQwAmAoI4Q==) format('woff'),url('polylang.ttf') format('truetype'),url('polylang.svg#polylang') format('svg');font-weight:normal;font-style:normal}.pll_icon_tick:before{content:"\e600"}.pll_icon_add:before{content:"\e601"}.pll_icon_edit:before{content:"\e602"}[class^="pll_icon_"],#wpadminbar #wp-admin-bar-languages .ab-icon:before{font-family:'polylang'}#wpadminbar #wp-admin-bar-languages .ab-item img{margin:0 8px 0 2px}#wpadminbar #wp-admin-bar-languages #wp-admin-bar-all .ab-item .ab-icon{float:none;top:4px}#wpadminbar #wp-admin-bar-languages .ab-icon:before{font:20px/1 'polylang';content:"\e603";top:1px}#wpadminbar #wp-admin-bar-languages .ab-item .ab-icon{margin:0 6px 0 0;padding:4px 0}
frontend/choose-lang-content.php CHANGED
@@ -59,8 +59,8 @@ class PLL_Choose_Lang_Content extends PLL_Choose_lang {
59
  elseif ((is_single() || is_page() || (is_attachment() && $this->options['media_support'])) && ( ($var = get_queried_object_id()) || ($var = get_query_var('p')) || ($var = get_query_var('page_id')) || ($var = get_query_var('attachment_id')) ))
60
  $lang = $this->model->get_post_language($var);
61
 
62
- elseif (isset($this->model->taxonomies)) {
63
- foreach ($this->model->taxonomies as $taxonomy) {
64
  if ($var = get_query_var(get_taxonomy($taxonomy)->query_var))
65
  $lang = $this->model->get_term_language($var, $taxonomy);
66
  }
59
  elseif ((is_single() || is_page() || (is_attachment() && $this->options['media_support'])) && ( ($var = get_queried_object_id()) || ($var = get_query_var('p')) || ($var = get_query_var('page_id')) || ($var = get_query_var('attachment_id')) ))
60
  $lang = $this->model->get_post_language($var);
61
 
62
+ else {
63
+ foreach ($this->model->get_translated_taxonomies() as $taxonomy) {
64
  if ($var = get_query_var(get_taxonomy($taxonomy)->query_var))
65
  $lang = $this->model->get_term_language($var, $taxonomy);
66
  }
frontend/choose-lang-url.php CHANGED
@@ -71,12 +71,12 @@ class PLL_Choose_Lang_Url extends PLL_Choose_lang {
71
  public function check_language_code_in_url() {
72
  if (is_single() || is_page()) {
73
  global $post;
74
- if (isset($post->ID) && in_array($post->post_type, $this->model->post_types))
75
  $language = $this->model->get_post_language((int)$post->ID);
76
  }
77
  elseif (is_category() || is_tag() || is_tax()) {
78
  $obj = $GLOBALS['wp_query']->get_queried_object();
79
- if (in_array($obj->taxonomy, $this->model->taxonomies))
80
  $language = $this->model->get_term_language((int)$obj->term_id);
81
  }
82
 
71
  public function check_language_code_in_url() {
72
  if (is_single() || is_page()) {
73
  global $post;
74
+ if (isset($post->ID) && $this->model->is_translated_post_type($post->post_type))
75
  $language = $this->model->get_post_language((int)$post->ID);
76
  }
77
  elseif (is_category() || is_tag() || is_tax()) {
78
  $obj = $GLOBALS['wp_query']->get_queried_object();
79
+ if ($this->model->is_translated_taxonomy($obj->taxonomy))
80
  $language = $this->model->get_term_language((int)$obj->term_id);
81
  }
82
 
frontend/choose-lang.php CHANGED
@@ -190,7 +190,7 @@ abstract class PLL_Choose_Lang {
190
  * @param object $query instance of WP_Query
191
  */
192
  public function parse_main_query($query) {
193
- if (empty($GLOBALS['wp_the_query']) || $query !== $GLOBALS['wp_the_query'])
194
  return;
195
 
196
  $qv = $query->query_vars;
@@ -235,33 +235,21 @@ abstract class PLL_Choose_Lang {
235
  $query->is_home = $query->is_posts_page = true;
236
  }
237
  }
238
-
239
- // backward compatibility WP < 3.4, sets a language for theme preview
240
- if (is_preview() && is_front_page()) {
241
- $this->set_language($this->get_preferred_language());
242
- $this->set_lang_query_var($query, $this->curlang);
243
- }
244
  }
245
 
246
  /*
247
  * sets the language in query
248
- * optimized for WP 3.5+
249
  *
250
  * @since 1.3
251
  */
252
  public function set_lang_query_var(&$query, $lang) {
253
- // backward compatibility WP < 3.5
254
- if (version_compare($GLOBALS['wp_version'], '3.5' , '<')) {
255
- $query->set('lang', $lang->slug);
256
- }
257
- else {
258
- // defining directly the tax_query (rather than setting 'lang' avoids transforming the query by WP)
259
- $query->query_vars['tax_query'][] = array(
260
- 'taxonomy' => 'language',
261
- 'field' => 'term_taxonomy_id', // since WP 3.5
262
- 'terms' => $lang->term_taxonomy_id,
263
- 'operator' => 'IN'
264
- );
265
- }
266
  }
267
  }
190
  * @param object $query instance of WP_Query
191
  */
192
  public function parse_main_query($query) {
193
+ if (!$query->is_main_query())
194
  return;
195
 
196
  $qv = $query->query_vars;
235
  $query->is_home = $query->is_posts_page = true;
236
  }
237
  }
 
 
 
 
 
 
238
  }
239
 
240
  /*
241
  * sets the language in query
242
+ * optimized for (needs) WP 3.5+
243
  *
244
  * @since 1.3
245
  */
246
  public function set_lang_query_var(&$query, $lang) {
247
+ // defining directly the tax_query (rather than setting 'lang' avoids transforming the query by WP)
248
+ $query->query_vars['tax_query'][] = array(
249
+ 'taxonomy' => 'language',
250
+ 'field' => 'term_taxonomy_id', // since WP 3.5
251
+ 'terms' => $lang->term_taxonomy_id,
252
+ 'operator' => 'IN'
253
+ );
 
 
 
 
 
 
254
  }
255
  }
frontend/frontend-auto-translate.php CHANGED
@@ -34,7 +34,7 @@ class PLL_Frontend_Auto_Translate {
34
  global $wpdb;
35
  $qv = &$query->query_vars;
36
 
37
- if (!empty($qv['post_type']) && !$this->model->is_translated_post_type($qv['post_type']))
38
  return;
39
 
40
  $sign = create_function('$n', 'return $n > 0 ? 1 : ($n < 0 ? -1 : 0);');
@@ -99,38 +99,38 @@ class PLL_Frontend_Auto_Translate {
99
  }
100
  }
101
 
102
- if (isset($this->model->taxonomies) && is_array($this->model->taxonomies)) {
103
- // custom taxonomies
104
- // according to codex, this type of query is deprecated as of WP 3.1 but it does not appear in WP 3.5 source code
105
- foreach (array_diff($this->model->taxonomies, array('category', 'post_tag')) as $taxonomy) {
106
- $tax = get_taxonomy($taxonomy);
107
- $arr = array();
108
- if (!empty($qv[$tax->query_var])) {
109
- $sep = strpos($qv[$tax->query_var], ',') !== false ? ',' : '+'; // two possible separators
110
- foreach (explode($sep, $qv[$tax->query_var]) as $slug)
111
- $arr[] = (($tag = get_term_by('slug', $slug, $taxonomy)) && ($tr_id = pll_get_term($tag->term_id)) && !is_wp_error($tr = get_term($tr_id, $taxonomy))) ?
112
- $tr->slug : $slug;
113
-
114
- $qv[$tax->query_var] = implode($sep, $arr);
115
- }
116
  }
 
117
 
118
- // tax_query since WP 3.1
119
- if (!empty($qv['tax_query']) && is_array($qv['tax_query'])) {
120
- foreach ($qv['tax_query'] as $key => $q) {
121
- if (isset($q['taxonomy']) && in_array($q['taxonomy'], $this->model->taxonomies)) {
122
- $arr = array();
123
- $field = isset($q['field']) && in_array($q['field'], array('slug', 'name')) ? $q['field'] : 'term_id';
124
- foreach ( (array) $q['terms'] as $t)
125
- $arr[] = (($tag = get_term_by($field, $t, $q['taxonomy'])) && ($tr_id = pll_get_term($tag->term_id)) && !is_wp_error($tr = get_term($tr_id, $q['taxonomy']))) ?
126
- $tr->$field : $t;
127
-
128
- $qv['tax_query'][$key]['terms'] = $arr;
129
- }
130
  }
131
  }
132
  }
133
 
 
134
  // p, page_id, post_parent can only take one id
135
  foreach (array('p', 'page_id', 'post_parent') as $key)
136
  if (!empty($qv[$key]) && $tr_id = pll_get_post($qv[$key]))
34
  global $wpdb;
35
  $qv = &$query->query_vars;
36
 
37
+ if ($query->is_main_query() || !empty($qv['lang']) || (!empty($qv['post_type']) && !$this->model->is_translated_post_type($qv['post_type'])))
38
  return;
39
 
40
  $sign = create_function('$n', 'return $n > 0 ? 1 : ($n < 0 ? -1 : 0);');
99
  }
100
  }
101
 
102
+
103
+ // custom taxonomies
104
+ // according to codex, this type of query is deprecated as of WP 3.1 but it does not appear in WP 3.5 source code
105
+ foreach (array_intersect($this->model->get_translated_taxonomies(), get_taxonomies(array('_builtin' => false))) as $taxonomy) {
106
+ $tax = get_taxonomy($taxonomy);
107
+ $arr = array();
108
+ if (!empty($qv[$tax->query_var])) {
109
+ $sep = strpos($qv[$tax->query_var], ',') !== false ? ',' : '+'; // two possible separators
110
+ foreach (explode($sep, $qv[$tax->query_var]) as $slug)
111
+ $arr[] = (($tag = get_term_by('slug', $slug, $taxonomy)) && ($tr_id = pll_get_term($tag->term_id)) && !is_wp_error($tr = get_term($tr_id, $taxonomy))) ?
112
+ $tr->slug : $slug;
113
+
114
+ $qv[$tax->query_var] = implode($sep, $arr);
 
115
  }
116
+ }
117
 
118
+ // tax_query since WP 3.1
119
+ if (!empty($qv['tax_query']) && is_array($qv['tax_query'])) {
120
+ foreach ($qv['tax_query'] as $key => $q) {
121
+ if (isset($q['taxonomy']) && $this->model->is_translated_taxonomy($q['taxonomy'])) {
122
+ $arr = array();
123
+ $field = isset($q['field']) && in_array($q['field'], array('slug', 'name')) ? $q['field'] : 'term_id';
124
+ foreach ( (array) $q['terms'] as $t)
125
+ $arr[] = (($tag = get_term_by($field, $t, $q['taxonomy'])) && ($tr_id = pll_get_term($tag->term_id)) && !is_wp_error($tr = get_term($tr_id, $q['taxonomy']))) ?
126
+ $tr->$field : $t;
127
+
128
+ $qv['tax_query'][$key]['terms'] = $arr;
 
129
  }
130
  }
131
  }
132
 
133
+
134
  // p, page_id, post_parent can only take one id
135
  foreach (array('p', 'page_id', 'post_parent') as $key)
136
  if (!empty($qv[$key]) && $tr_id = pll_get_post($qv[$key]))
frontend/frontend-filters.php CHANGED
@@ -5,10 +5,7 @@
5
  *
6
  * @since 1.2
7
  */
8
- class PLL_Frontend_Filters {
9
- public $links_model, $model, $options;
10
- public $curlang;
11
-
12
  /*
13
  * constructor: setups filters and actions
14
  *
@@ -18,18 +15,11 @@ class PLL_Frontend_Filters {
18
  * @param object $curlang
19
  */
20
  public function __construct(&$links_model, &$curlang) {
21
- $this->links_model = &$links_model;
22
- $this->model = &$links_model->model;
23
- $this->options = &$this->model->options;
24
-
25
- $this->curlang = &$curlang;
26
 
27
  // filters the WordPress locale
28
  add_filter('locale', array(&$this, 'get_locale'));
29
 
30
- // backward compatibility WP < 3.4, modifies the language information in rss feed
31
- add_filter('option_rss_language', array(&$this, 'option_rss_language'));
32
-
33
  // translates page for posts and page on front
34
  add_filter('option_page_for_posts', array(&$this, 'translate_page'));
35
  add_filter('option_page_on_front', array(&$this, 'translate_page'));
@@ -40,12 +30,6 @@ class PLL_Frontend_Filters {
40
  // filters categories and post tags by language
41
  add_filter('terms_clauses', array(&$this, 'terms_clauses'), 10, 3);
42
 
43
- // filters the pages according to the current language in wp_list_pages
44
- add_filter('wp_list_pages_excludes', array(&$this, 'wp_list_pages_excludes'));
45
-
46
- // filters the comments according to the current language
47
- add_filter('comments_clauses', array(&$this, 'comments_clauses'), 10, 2);
48
-
49
  // rewrites archives, next and previous post links to filter them by language
50
  foreach (array('getarchives', 'get_previous_post', 'get_next_post') as $filter)
51
  foreach (array('_join', '_where') as $clause)
@@ -88,19 +72,6 @@ class PLL_Frontend_Filters {
88
  return $this->curlang->locale;
89
  }
90
 
91
- /*
92
- * modifies the language information in rss feed
93
- * backward compatibility WP < 3.4
94
- *
95
- * @since 0.8
96
- *
97
- * @param string $value
98
- * @return string
99
- */
100
- public function option_rss_language($value) {
101
- return get_bloginfo_rss('language');
102
- }
103
-
104
  /*
105
  * translates page for posts and page on front
106
  *
@@ -149,39 +120,13 @@ class PLL_Frontend_Filters {
149
  */
150
  public function terms_clauses($clauses, $taxonomies, $args) {
151
  // does nothing except on taxonomies which are filterable
152
- if (!array_intersect($taxonomies, $this->model->taxonomies))
153
  return $clauses;
154
 
155
  // adds our clauses to filter by language
156
  return $this->model->terms_clauses($clauses, isset($args['lang']) ? $args['lang'] : $this->curlang);
157
  }
158
 
159
- /*
160
- * excludes pages which are not in the current language for wp_list_pages
161
- * useful for the pages widget
162
- *
163
- * @since 0.4
164
- *
165
- * @param array $pages list of page ids to exclude from wp_list_pages
166
- * @return array modified list of page ids
167
- */
168
- public function wp_list_pages_excludes($pages) {
169
- return array_merge($pages, pll_exclude_pages($this->curlang));
170
- }
171
-
172
- /*
173
- * filters the comments according to the current language mainly for the recent comments widget
174
- *
175
- * @since 0.2
176
- *
177
- * @param array $clauses
178
- * @param object $query
179
- * @return array modified $clauses
180
- */
181
- public function comments_clauses($clauses, $query) {
182
- return $this->model->comments_clauses($clauses, isset($query->query_vars['lang']) ? $query->query_vars['lang'] : $this->curlang);
183
- }
184
-
185
  /*
186
  * modifies the sql request for wp_get_archives an get_adjacent_post to filter by the current language
187
  *
@@ -204,7 +149,7 @@ class PLL_Frontend_Filters {
204
  */
205
  public function posts_where($sql) {
206
  preg_match("#post_type = '([^']+)'#", $sql, $matches); // find the queried post type
207
- return !empty($matches[1]) && in_array($matches[1], $this->model->post_types) ? $sql . $this->model->where_clause($this->curlang, 'post') : $sql;
208
  }
209
 
210
  /*
@@ -245,7 +190,7 @@ class PLL_Frontend_Filters {
245
  * @param object $post
246
  */
247
  public function save_post($post_id, $post) {
248
- if (in_array($post->post_type, $this->model->post_types)) {
249
  if (isset($_REQUEST['lang']))
250
  $this->model->set_post_language($post_id, $_REQUEST['lang']);
251
 
@@ -271,7 +216,7 @@ class PLL_Frontend_Filters {
271
  * @param string $taxonomy
272
  */
273
  public function save_term($term_id, $tt_id, $taxonomy) {
274
- if (in_array($taxonomy, $this->model->taxonomies)) {
275
  if (isset($_REQUEST['lang']))
276
  $this->model->set_term_language($term_id, $_REQUEST['lang']);
277
 
5
  *
6
  * @since 1.2
7
  */
8
+ class PLL_Frontend_Filters extends PLL_Filters{
 
 
 
9
  /*
10
  * constructor: setups filters and actions
11
  *
15
  * @param object $curlang
16
  */
17
  public function __construct(&$links_model, &$curlang) {
18
+ parent::__construct($links_model, $curlang);
 
 
 
 
19
 
20
  // filters the WordPress locale
21
  add_filter('locale', array(&$this, 'get_locale'));
22
 
 
 
 
23
  // translates page for posts and page on front
24
  add_filter('option_page_for_posts', array(&$this, 'translate_page'));
25
  add_filter('option_page_on_front', array(&$this, 'translate_page'));
30
  // filters categories and post tags by language
31
  add_filter('terms_clauses', array(&$this, 'terms_clauses'), 10, 3);
32
 
 
 
 
 
 
 
33
  // rewrites archives, next and previous post links to filter them by language
34
  foreach (array('getarchives', 'get_previous_post', 'get_next_post') as $filter)
35
  foreach (array('_join', '_where') as $clause)
72
  return $this->curlang->locale;
73
  }
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  /*
76
  * translates page for posts and page on front
77
  *
120
  */
121
  public function terms_clauses($clauses, $taxonomies, $args) {
122
  // does nothing except on taxonomies which are filterable
123
+ if (!$this->model->is_translated_taxonomy($taxonomies))
124
  return $clauses;
125
 
126
  // adds our clauses to filter by language
127
  return $this->model->terms_clauses($clauses, isset($args['lang']) ? $args['lang'] : $this->curlang);
128
  }
129
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  /*
131
  * modifies the sql request for wp_get_archives an get_adjacent_post to filter by the current language
132
  *
149
  */
150
  public function posts_where($sql) {
151
  preg_match("#post_type = '([^']+)'#", $sql, $matches); // find the queried post type
152
+ return !empty($matches[1]) && $this->model->is_translated_post_type($matches[1]) ? $sql . $this->model->where_clause($this->curlang, 'post') : $sql;
153
  }
154
 
155
  /*
190
  * @param object $post
191
  */
192
  public function save_post($post_id, $post) {
193
+ if ($this->model->is_translated_post_type($post->post_type)) {
194
  if (isset($_REQUEST['lang']))
195
  $this->model->set_post_language($post_id, $_REQUEST['lang']);
196
 
216
  * @param string $taxonomy
217
  */
218
  public function save_term($term_id, $tt_id, $taxonomy) {
219
+ if ($this->model->is_translated_taxonomy($taxonomy)) {
220
  if (isset($_REQUEST['lang']))
221
  $this->model->set_term_language($term_id, $_REQUEST['lang']);
222
 
frontend/frontend-links.php CHANGED
@@ -43,6 +43,10 @@ class PLL_Frontend_Links extends PLL_Links {
43
  foreach (array('feed_link', 'author_link', 'post_type_archive_link', 'year_link', 'month_link', 'day_link') as $filter)
44
  add_filter($filter, array(&$this, 'archive_link'), 20);
45
 
 
 
 
 
46
  // modifies the page link in case the front page is not in the default language
47
  add_filter('page_link', array(&$this, 'page_link'), 20, 2);
48
 
@@ -84,7 +88,7 @@ class PLL_Frontend_Links extends PLL_Links {
84
  return $this->links[$link];
85
 
86
  return $this->links[$link] = $tax == 'post_format' ?
87
- $this->links_model->add_language_to_link($link, $this->model->get_term_language($term->term_id)) : parent::term_link($link, $term, $tax);
88
  }
89
 
90
  /*
@@ -100,7 +104,7 @@ class PLL_Frontend_Links extends PLL_Links {
100
  if ($this->page_on_front && ($lang = $this->model->get_post_language($id)) && $id == $this->model->get_post($this->page_on_front, $lang))
101
  return $lang->home_url;
102
 
103
- return _get_page_link($id);
104
  }
105
 
106
  /*
@@ -151,15 +155,22 @@ class PLL_Frontend_Links extends PLL_Links {
151
  if (!(did_action('template_redirect') || did_action('login_init')) || rtrim($url,'/') != $this->home)
152
  return $url;
153
 
154
- $white_list = apply_filters('pll_home_url_white_list', array(
155
- array('file' => get_theme_root()),
156
- array('function' => 'wp_nav_menu'),
157
- array('function' => 'login_footer')
158
- ));
 
 
 
 
159
 
160
- $black_list = apply_filters('pll_home_url_black_list', array(array('function' => 'get_search_form')));
 
161
 
162
- foreach (array_reverse(debug_backtrace(/*!DEBUG_BACKTRACE_PROVIDE_OBJECT|DEBUG_BACKTRACE_IGNORE_ARGS*/)) as $trace) {
 
 
163
  // searchform.php is not passed through get_search_form filter prior to WP 3.6
164
  // backward compatibility WP < 3.6
165
  if (isset($trace['file']) && strpos($trace['file'], 'searchform.php'))
@@ -203,7 +214,7 @@ class PLL_Frontend_Links extends PLL_Links {
203
  $url = get_permalink($id);
204
 
205
  // page for posts
206
- // FIXME the last test should useless now since I test is_posts_page
207
  elseif ($wp_query->is_posts_page && !empty($wp_query->queried_object_id) && ($id = $this->model->get_post($wp_query->queried_object_id, $language)) && $id == $this->model->get_post($this->page_for_posts, $language))
208
  $url = get_permalink($id);
209
 
@@ -216,15 +227,18 @@ class PLL_Frontend_Links extends PLL_Links {
216
 
217
  if (!$lang || $language->slug == $lang->slug)
218
  $url = get_term_link($term, $term->taxonomy); // self link
219
- elseif ($link_id = $this->model->get_translation('term', $term->term_id, $language))
220
- $url = get_term_link(get_term($link_id, $term->taxonomy), $term->taxonomy);
 
 
 
221
  }
222
 
223
  elseif (is_search())
224
  $url = $this->get_archive_url($language);
225
 
226
  elseif (is_archive()) {
227
- $keys = array('post_type', 'm', 'year', 'monthnum', 'day', 'author', 'author_name');
228
  // check if there are existing translations before creating the url
229
  if ($this->model->count_posts($language, array_intersect_key($qv, array_flip($keys))))
230
  $url = $this->get_archive_url($language);
43
  foreach (array('feed_link', 'author_link', 'post_type_archive_link', 'year_link', 'month_link', 'day_link') as $filter)
44
  add_filter($filter, array(&$this, 'archive_link'), 20);
45
 
46
+ // rewrites next and previous post links when not automatically done by WordPress
47
+ if ($this->options['force_lang'] > 1)
48
+ add_filter('get_pagenum_link', array(&$this, 'archive_link'), 20);
49
+
50
  // modifies the page link in case the front page is not in the default language
51
  add_filter('page_link', array(&$this, 'page_link'), 20, 2);
52
 
88
  return $this->links[$link];
89
 
90
  return $this->links[$link] = $tax == 'post_format' ?
91
+ $this->links_model->add_language_to_link($link, $this->curlang) : parent::term_link($link, $term, $tax);
92
  }
93
 
94
  /*
104
  if ($this->page_on_front && ($lang = $this->model->get_post_language($id)) && $id == $this->model->get_post($this->page_on_front, $lang))
105
  return $lang->home_url;
106
 
107
+ return $link;
108
  }
109
 
110
  /*
155
  if (!(did_action('template_redirect') || did_action('login_init')) || rtrim($url,'/') != $this->home)
156
  return $url;
157
 
158
+ static $white_list, $black_list; // avoid evaluating this at each function call
159
+
160
+ if (empty($white_list)) {
161
+ $white_list = apply_filters('pll_home_url_white_list', array(
162
+ array('file' => get_theme_root()),
163
+ array('function' => 'wp_nav_menu'),
164
+ array('function' => 'login_footer')
165
+ ));
166
+ }
167
 
168
+ if (empty($black_list))
169
+ $black_list = apply_filters('pll_home_url_black_list', array(array('function' => 'get_search_form')));
170
 
171
+ $traces = version_compare(PHP_VERSION, '5.2.5', '>=') ? debug_backtrace(false) : debug_backtrace();
172
+
173
+ foreach ($traces as $trace) {
174
  // searchform.php is not passed through get_search_form filter prior to WP 3.6
175
  // backward compatibility WP < 3.6
176
  if (isset($trace['file']) && strpos($trace['file'], 'searchform.php'))
214
  $url = get_permalink($id);
215
 
216
  // page for posts
217
+ // FIXME the last test should be useless now since I test is_posts_page
218
  elseif ($wp_query->is_posts_page && !empty($wp_query->queried_object_id) && ($id = $this->model->get_post($wp_query->queried_object_id, $language)) && $id == $this->model->get_post($this->page_for_posts, $language))
219
  $url = get_permalink($id);
220
 
227
 
228
  if (!$lang || $language->slug == $lang->slug)
229
  $url = get_term_link($term, $term->taxonomy); // self link
230
+ elseif ($tr_id = $this->model->get_translation('term', $term->term_id, $language)) {
231
+ $tr_term = get_term($tr_id, $term->taxonomy);
232
+ if ($tr_term && $tr_term->count)
233
+ $url = get_term_link($tr_term, $term->taxonomy);
234
+ }
235
  }
236
 
237
  elseif (is_search())
238
  $url = $this->get_archive_url($language);
239
 
240
  elseif (is_archive()) {
241
+ $keys = array('post_type', 'm', 'year', 'monthnum', 'day', 'author', 'author_name', 'post_format');
242
  // check if there are existing translations before creating the url
243
  if ($this->model->count_posts($language, array_intersect_key($qv, array_flip($keys))))
244
  $url = $this->get_archive_url($language);
frontend/frontend.php CHANGED
@@ -22,7 +22,7 @@ class PLL_Frontend extends PLL_Base{
22
  add_action('pll_language_defined', array(&$this, 'pll_language_defined'), 1, 2);
23
 
24
  // filters posts by language
25
- add_filter('parse_query', array(&$this, 'parse_query'), 6); // after PLL_Frontend_Filters::parse_query
26
 
27
  // not before 'check_language_code_in_url'
28
  if (!defined('PLL_AUTO_TRANSLATE') || PLL_AUTO_TRANSLATE)
22
  add_action('pll_language_defined', array(&$this, 'pll_language_defined'), 1, 2);
23
 
24
  // filters posts by language
25
+ add_filter('parse_query', array(&$this, 'parse_query'), 6);
26
 
27
  // not before 'check_language_code_in_url'
28
  if (!defined('PLL_AUTO_TRANSLATE') || PLL_AUTO_TRANSLATE)
include/base.php CHANGED
@@ -79,43 +79,3 @@ abstract class PLL_Base {
79
  trigger_error(sprintf('Call to undefined function $polylang->%1$s() in %2$s on line %3$s' . "\nError handler", $func, $debug[0]['file'], $debug[0]['line']), E_USER_ERROR);
80
  }
81
  }
82
-
83
- /*
84
- * helpers functions
85
- */
86
-
87
-
88
- /*
89
- * returns all page ids *not in* language defined by $lang_id
90
- * works for all translated hierarchical post types
91
- *
92
- * @since 1.2
93
- *
94
- * @param object $lang language object
95
- * @return array list of page ids to exclude
96
- */
97
- function pll_exclude_pages($lang) {
98
- global $polylang;
99
-
100
- $args = array(
101
- 'lang' => 0, // so this query is not filtered by our pre_get_post filter in PLL_Frontend_Filters
102
- 'numberposts' => -1,
103
- 'nopaging' => true,
104
- 'post_type' => array_intersect(get_post_types(array('hierarchical' => 1)), $polylang->model->post_types),
105
- 'fields' => 'ids',
106
- 'tax_query' => array(array(
107
- 'taxonomy' => 'language',
108
- 'field' => 'term_taxonomy_id', // since WP 3.5
109
- 'terms' => $lang->term_taxonomy_id,
110
- 'operator' => 'NOT IN'
111
- ))
112
- );
113
-
114
- // backward compatibility WP < 3.5
115
- if (version_compare($GLOBALS['wp_version'], '3.5' , '<')) {
116
- unset($args['tax_query']['field']);
117
- $args['tax_query']['terms'] = $lang->term_id;
118
- }
119
-
120
- return get_posts($args);
121
- }
79
  trigger_error(sprintf('Call to undefined function $polylang->%1$s() in %2$s on line %3$s' . "\nError handler", $func, $debug[0]['file'], $debug[0]['line']), E_USER_ERROR);
80
  }
81
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
include/filters.php ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * setup filters common to admin and frontend
5
+ *
6
+ * @since 1.4
7
+ */
8
+ class PLL_Filters {
9
+ public $links_model, $model, $options, $curlang;
10
+
11
+ /*
12
+ * constructor: setups filters
13
+ *
14
+ * @since 1.4
15
+ *
16
+ * @param object $links_model
17
+ * @param object $curlang
18
+ */
19
+ public function __construct(&$links_model, &$curlang) {
20
+ $this->links_model = &$links_model;
21
+ $this->model = &$links_model->model;
22
+ $this->options = &$this->model->options;
23
+ $this->curlang = $curlang;
24
+
25
+ // filters the comments according to the current language
26
+ add_filter('comments_clauses', array(&$this, 'comments_clauses'), 10, 2);
27
+
28
+ // filters the get_pages function according to the current language
29
+ add_filter('get_pages', array(&$this, 'get_pages'), 10, 2);
30
+ }
31
+
32
+ /*
33
+ * filters the comments according to the current language
34
+ * used by the recent comments widget and admin language filter
35
+ *
36
+ * @since 0.2
37
+ *
38
+ * @param array $clauses sql clauses
39
+ * @param object $query WP_Comment_Query object
40
+ * @return array modified $clauses
41
+ */
42
+ public function comments_clauses($clauses, $query) {
43
+ global $wpdb;
44
+
45
+ $lang = empty($query->query_vars['lang']) ? $this->curlang : $this->model->get_language($query->query_vars['lang']);
46
+
47
+ if (!empty($lang)) {
48
+ // if this clause is not already added by WP
49
+ if (!strpos($clauses['join'], '.ID'))
50
+ $clauses['join'] .= " JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID";
51
+
52
+ $clauses['join'] .= $this->model->join_clause('post');
53
+ $clauses['where'] .= $this->model->where_clause($lang, 'post');
54
+ }
55
+ return $clauses;
56
+ }
57
+
58
+ /*
59
+ * filters get_pages per language
60
+ *
61
+ * @since 1.4
62
+ *
63
+ * @param array $pages an array of pages already queried
64
+ * @param array $args get_pages arguments
65
+ * @return array modified list of pages
66
+ */
67
+ public function get_pages($pages, $args) {
68
+ $language = empty($args['lang']) ? $this->curlang : $this->model->get_language($args['lang']);
69
+
70
+ if (empty($language) || empty($pages) || !$this->model->is_translated_post_type($args['post_type']))
71
+ return $pages;
72
+
73
+ static $once = false;
74
+
75
+ // obliged to redo the get_pages query if we want to get the right number
76
+ if (!empty($args['number']) && !$once) {
77
+ $once = true; // avoid infinite loop
78
+
79
+ $r = array(
80
+ 'lang' => 0, // so this query is not filtered
81
+ 'numberposts' => -1,
82
+ 'nopaging' => true,
83
+ 'post_type' => $args['post_type'],
84
+ 'fields' => 'ids',
85
+ 'tax_query' => array(array(
86
+ 'taxonomy' => 'language',
87
+ 'field' => 'term_taxonomy_id', // since WP 3.5
88
+ 'terms' => $language->term_taxonomy_id,
89
+ 'operator' => 'NOT IN'
90
+ ))
91
+ );
92
+
93
+ $args['exclude'] = array_merge($args['exclude'], get_posts($r));
94
+ $pages = get_pages($args);
95
+ }
96
+
97
+ $ids = wp_list_pluck($pages, 'ID');
98
+
99
+ // filters the queried list of pages by language
100
+ if (!$once) {
101
+ $ids = array_intersect($ids, $this->model->get_objects_in_language($language));
102
+
103
+ foreach ($pages as $key => $page) {
104
+ if (!in_array($page->ID, $ids))
105
+ unset($pages[$key]);
106
+ }
107
+ }
108
+
109
+ // not done by WP but extremely useful for performance when manipulating taxonomies
110
+ update_object_term_cache($ids, $args['post_type']);
111
+
112
+ $once = false; // in case get_pages is called another time
113
+ return $pages;
114
+ }
115
+ }
include/language.php CHANGED
@@ -23,6 +23,7 @@
23
  * flag => html img of the flag
24
  * home_url => home url in this language
25
  * search_url => home url to use in search forms
 
26
  *
27
  * @since 1.2
28
  */
@@ -51,6 +52,8 @@ class PLL_Language {
51
  $this->is_rtl = $description['rtl'];
52
 
53
  $this->description = &$this->locale; // backward compatibility with Polylang < 1.2
 
 
54
  }
55
 
56
  /*
@@ -72,7 +75,7 @@ class PLL_Language {
72
  $this->flag = apply_filters('pll_get_flag', empty($this->flag_url) ? '' :
73
  sprintf(
74
  '<img src="%s" title="%s" alt="%s" />',
75
- esc_url($this->flag_url),
76
  esc_attr(apply_filters('pll_flag_title', $this->name, $this->slug, $this->locale)),
77
  esc_attr($this->name)
78
  ));
@@ -92,22 +95,23 @@ class PLL_Language {
92
  * set home_url and search_url properties
93
  *
94
  * @since 1.3
95
- *
96
  */
97
  public function set_home_url() {
98
- $options = get_option('polylang');
99
-
100
- // a static page is used as front page : /!\ don't use get_page_link to avoid infinite loop
101
- // don't use this for search form
102
- if (!$options['redirect_lang'] && ($page_on_front = get_option('page_on_front')) && $id = pll_get_post($page_on_front, $this))
103
- $this->home_url = _get_page_link($id);
104
-
105
- $link = $GLOBALS['polylang']->links_model->home_url($this);
106
 
107
  // add a trailing slash as done by WP on homepage (otherwise could break the search form when the permalink structure does not include one)
108
  // only for pretty permalinks
109
- $this->search_url = get_option('using_permalinks') ? trailingslashit($link) : $link;
 
 
 
 
 
 
 
110
 
111
- $this->home_url = empty($this->home_url) ? $this->search_url : $this->home_url;
 
112
  }
113
  }
23
  * flag => html img of the flag
24
  * home_url => home url in this language
25
  * search_url => home url to use in search forms
26
+ * mo_id => id of the post storing strings translations
27
  *
28
  * @since 1.2
29
  */
52
  $this->is_rtl = $description['rtl'];
53
 
54
  $this->description = &$this->locale; // backward compatibility with Polylang < 1.2
55
+
56
+ $this->mo_id = PLL_MO::get_id($this);
57
  }
58
 
59
  /*
75
  $this->flag = apply_filters('pll_get_flag', empty($this->flag_url) ? '' :
76
  sprintf(
77
  '<img src="%s" title="%s" alt="%s" />',
78
+ $this->flag_url,
79
  esc_attr(apply_filters('pll_flag_title', $this->name, $this->slug, $this->locale)),
80
  esc_attr($this->name)
81
  ));
95
  * set home_url and search_url properties
96
  *
97
  * @since 1.3
 
98
  */
99
  public function set_home_url() {
100
+ // home url for search form (can't use the page url if a static page is used as front page)
101
+ $this->search_url = $GLOBALS['polylang']->links_model->home_url($this);
 
 
 
 
 
 
102
 
103
  // add a trailing slash as done by WP on homepage (otherwise could break the search form when the permalink structure does not include one)
104
  // only for pretty permalinks
105
+ if (get_option('using_permalinks'))
106
+ $this->search_url = trailingslashit($link);
107
+
108
+ $options = get_option('polylang');
109
+
110
+ // a static page is used as front page
111
+ if (!$options['redirect_lang'] && ($page_on_front = get_option('page_on_front')) && $id = pll_get_post($page_on_front, $this))
112
+ $this->home_url = _get_page_link($id); // /!\ don't use get_page_link to avoid infinite loop
113
 
114
+ else
115
+ $this->home_url = $this->search_url;
116
  }
117
  }
include/links-directory.php CHANGED
@@ -124,9 +124,7 @@ class PLL_Links_Directory {
124
  function add_permastruct() {
125
  // language information always in front of the uri ('with_front' => false)
126
  // the 3rd parameter structure has been modified in WP 3.4
127
- // backward compatibility WP < 3.4
128
- add_permastruct('language', $this->options['rewrite'] ? '%language%' : 'language/%language%',
129
- version_compare($GLOBALS['wp_version'], '3.4' , '<') ? false : array('with_front' => false));
130
  }
131
 
132
  /*
@@ -185,13 +183,13 @@ class PLL_Links_Directory {
185
  $slug = $wp_rewrite->root . ($this->options['rewrite'] ? '' : 'language/') . '('.implode('|', $languages).')/';
186
 
187
  // for custom post type archives
188
- $cpts = array_intersect($this->model->post_types, get_post_types(array('_builtin' => false)));
189
  $cpts = $cpts ? '#post_type=('.implode('|', $cpts).')#' : '';
190
 
191
  foreach ($rules as $key => $rule) {
192
  // we don't need the lang parameter for post types and taxonomies
193
  // moreover adding it would create issues for pages and taxonomies
194
- if ($this->options['force_lang'] && in_array($filter, array_merge($this->model->post_types, $this->model->taxonomies))) {
195
  if (isset($slug))
196
  $newrules[$slug.str_replace($wp_rewrite->root, '', $key)] = str_replace(
197
  array('[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '[1]'),
124
  function add_permastruct() {
125
  // language information always in front of the uri ('with_front' => false)
126
  // the 3rd parameter structure has been modified in WP 3.4
127
+ add_permastruct('language', $this->options['rewrite'] ? '%language%' : 'language/%language%', array('with_front' => false));
 
 
128
  }
129
 
130
  /*
183
  $slug = $wp_rewrite->root . ($this->options['rewrite'] ? '' : 'language/') . '('.implode('|', $languages).')/';
184
 
185
  // for custom post type archives
186
+ $cpts = array_intersect($this->model->get_translated_post_types(), get_post_types(array('_builtin' => false)));
187
  $cpts = $cpts ? '#post_type=('.implode('|', $cpts).')#' : '';
188
 
189
  foreach ($rules as $key => $rule) {
190
  // we don't need the lang parameter for post types and taxonomies
191
  // moreover adding it would create issues for pages and taxonomies
192
+ if ($this->options['force_lang'] && in_array($filter, array_merge($this->model->get_translated_post_types(), $this->model->get_translated_taxonomies()))) {
193
  if (isset($slug))
194
  $newrules[$slug.str_replace($wp_rewrite->root, '', $key)] = str_replace(
195
  array('[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '[1]'),
include/links.php CHANGED
@@ -44,7 +44,7 @@ class PLL_Links {
44
  if (isset($links[$link]))
45
  return $links[$link];
46
 
47
- if ('post_type_link' == current_filter() && !in_array($post->post_type, $this->model->post_types))
48
  return $links[$link] = $link;
49
 
50
  if ('_get_page_link' == current_filter()) // this filter uses the ID instead of the post object
@@ -70,7 +70,7 @@ class PLL_Links {
70
  if (isset($links[$link]))
71
  return $links[$link];
72
 
73
- return $links[$link] = in_array($tax, $this->model->taxonomies) ?
74
  $this->links_model->add_language_to_link($link, $this->model->get_term_language($term->term_id)) : $link;
75
  }
76
 
44
  if (isset($links[$link]))
45
  return $links[$link];
46
 
47
+ if ('post_type_link' == current_filter() && !$this->model->is_translated_post_type($post->post_type))
48
  return $links[$link] = $link;
49
 
50
  if ('_get_page_link' == current_filter()) // this filter uses the ID instead of the post object
70
  if (isset($links[$link]))
71
  return $links[$link];
72
 
73
+ return $links[$link] = $this->model->is_translated_taxonomy($tax) ?
74
  $this->links_model->add_language_to_link($link, $this->model->get_term_language($term->term_id)) : $link;
75
  }
76
 
include/mo.php CHANGED
@@ -8,12 +8,13 @@
8
  class PLL_MO extends MO {
9
 
10
  /*
11
- * registers the polylang_mo custom post type
12
  *
13
  * @since 1.2
14
  */
15
  public function __construct() {
16
- register_post_type('polylang_mo', array('rewrite' => false, 'query_var' => false, '_pll' => true));
 
17
  }
18
 
19
  /*
@@ -32,9 +33,12 @@ class PLL_MO extends MO {
32
  foreach ($this->entries as $entry)
33
  $strings[] = array($entry->singular, $this->translate($entry->singular));
34
 
35
- $lang_id = is_object($lang) ? $lang->term_id : $lang;
36
- $post = get_page_by_title('polylang_mo_' . $lang_id, ARRAY_A, 'polylang_mo'); // wp_insert_post wants an array
37
- $post['post_title'] = 'polylang_mo_' . $lang_id;
 
 
 
38
  // json_encode would take less space but is slower to decode
39
  // wp_insert_post expects slashed data
40
  $post['post_content'] = addslashes(serialize($strings));
@@ -51,9 +55,8 @@ class PLL_MO extends MO {
51
  * @param object $lang the language in which we want to get strings
52
  */
53
  public function import_from_db($lang) {
54
- $lang_id = is_object($lang) ? $lang->term_id : $lang;
55
- $post = get_page_by_title('polylang_mo_' . $lang_id, OBJECT, 'polylang_mo');
56
- if (!empty($post)) {
57
  $strings = unserialize($post->post_content);
58
  if (is_array($strings)) {
59
  foreach ($strings as $msg)
@@ -61,4 +64,17 @@ class PLL_MO extends MO {
61
  }
62
  }
63
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  }
8
  class PLL_MO extends MO {
9
 
10
  /*
11
+ * registers the polylang_mo custom post type, only at first object creation
12
  *
13
  * @since 1.2
14
  */
15
  public function __construct() {
16
+ if (!post_type_exists('polylang_mo'))
17
+ register_post_type('polylang_mo', array('rewrite' => false, 'query_var' => false, '_pll' => true));
18
  }
19
 
20
  /*
33
  foreach ($this->entries as $entry)
34
  $strings[] = array($entry->singular, $this->translate($entry->singular));
35
 
36
+ $post = get_post($lang->mo_id, ARRAY_A); // wp_insert_post wants an array
37
+
38
+ if (empty($post))
39
+ $GLOBALS['polylang']->model->clean_languages_cache(); // to set mo_id
40
+
41
+ $post['post_title'] = 'polylang_mo_' . $lang->term_id;
42
  // json_encode would take less space but is slower to decode
43
  // wp_insert_post expects slashed data
44
  $post['post_content'] = addslashes(serialize($strings));
55
  * @param object $lang the language in which we want to get strings
56
  */
57
  public function import_from_db($lang) {
58
+ if (!empty($lang->mo_id)) {
59
+ $post = get_post($lang->mo_id, OBJECT);
 
60
  $strings = unserialize($post->post_content);
61
  if (is_array($strings)) {
62
  foreach ($strings as $msg)
64
  }
65
  }
66
  }
67
+
68
+ /*
69
+ * returns the post id of the post storing the strings translations
70
+ *
71
+ * @since 1.4
72
+ *
73
+ * @param object $lang
74
+ * @return int
75
+ */
76
+ public static function get_id($lang) {
77
+ global $wpdb;
78
+ return $wpdb->get_var($wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type= %s", 'polylang_mo_' . $lang->term_id, 'polylang_mo'));
79
+ }
80
  }
include/model.php CHANGED
@@ -7,7 +7,6 @@
7
  */
8
  class PLL_Model {
9
  public $options;
10
- public $post_types = array(), $taxonomies = array(); // post types & taxonomies to filter by language
11
  private $languages; // used to cache the list of languages
12
 
13
  /*
@@ -42,9 +41,8 @@ class PLL_Model {
42
  // registers completely the language taxonomy
43
  add_action('setup_theme', array(&$this, 'register_taxonomy'), 1);
44
 
45
- // setups post types and taxonomies to translate
46
  add_action('registered_post_type', array(&$this, 'registered_post_type'));
47
- add_action('registered_taxonomy', array(&$this, 'registered_taxonomy'));
48
 
49
  // just in case someone would like to display the language description ;-)
50
  add_filter('language_description', create_function('$v', "return '';"));
@@ -63,13 +61,10 @@ class PLL_Model {
63
  * @return array unmodified $terms
64
  */
65
  public function _prime_terms_cache($terms, $taxonomies) {
66
- foreach ($terms as $term) {
67
- if (is_object($term)) {
68
- if (in_array($term->taxonomy, $this->taxonomies))
69
- $term_ids[] = $term->term_id;
70
  }
71
- elseif (array_intersect($taxonomies, $this->taxonomies))
72
- $term_ids[] = $term;
73
  }
74
 
75
  if (!empty($term_ids))
@@ -154,21 +149,16 @@ class PLL_Model {
154
 
155
  if (!empty($languages) && !empty($term_languages)) {
156
  array_walk($languages, create_function('&$v, $k, $term_languages', '$v = new PLL_Language($v, $term_languages[$v->name]);'), $term_languages);
157
-
158
- // need to wait for $wp_rewrite availibility to set homepage urls
159
- $this->_languages = $languages;
160
- did_action('setup_theme') ? $this->_languages_urls() : add_action('setup_theme', array(&$this, '_languages_urls'));
161
  }
162
  else {
163
  $languages = array(); // in case something went wrong
164
  }
165
  }
166
 
167
- // add flags (not in db cache as they may be different on frontend and admin)
168
- foreach ($languages as $lang)
169
- $lang->set_flag();
170
-
171
  $this->languages = $languages;
 
 
 
172
  }
173
 
174
  $args = wp_parse_args($args, array('hide_empty' => false));
@@ -181,17 +171,28 @@ class PLL_Model {
181
  }
182
 
183
  /*
184
- * fills home urls in language list and set transient in db
185
- * delayed to be sure we have access to $wp_rewrite
 
186
  *
187
- * @since 1.3
188
  */
189
- public function _languages_urls() {
190
- foreach ($this->_languages as $language)
191
- $language->set_home_url();
 
 
 
 
 
192
 
193
- set_transient('pll_languages_list', $this->_languages);
194
- unset($this->languages, $this->_languages); // in case flags were already set
 
 
 
 
 
195
  }
196
 
197
  /*
@@ -325,7 +326,7 @@ class PLL_Model {
325
  * @return array an associative array of translations with language code as key and translation id as value
326
  */
327
  public function get_translations($type, $id) {
328
- $type = ($type == 'post' || in_array($type, $this->post_types)) ? 'post' : (($type == 'term' || in_array($type, $this->taxonomies)) ? 'term' : false);
329
  return $type && ($term = $this->get_object_term($id, $type . '_translations')) && !empty($term) ? unserialize($term->description) : array();
330
  }
331
 
@@ -476,28 +477,6 @@ class PLL_Model {
476
  return " AND pll_tr.term_taxonomy_id IN (" . implode(',', $languages) . ")";
477
  }
478
 
479
- /*
480
- * adds clauses to comments query to filter them by language - used in both frontend and admin
481
- *
482
- * @since 1.2
483
- *
484
- * @param array $clauses the list of sql clauses in comments query
485
- * @param object $lang PLL_Language object
486
- * @return array modifed list of clauses
487
- */
488
- public function comments_clauses($clauses, $lang) {
489
- global $wpdb;
490
- if (!empty($lang)) {
491
- // if this clause is not already added by WP
492
- if (!strpos($clauses['join'], '.ID'))
493
- $clauses['join'] .= " JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID";
494
-
495
- $clauses['join'] .= $this->join_clause('post');
496
- $clauses['where'] .= $this->where_clause($lang, 'post');
497
- }
498
- return $clauses;
499
- }
500
-
501
  /*
502
  * adds terms clauses to get_terms to filter them by languages - used in both frontend and admin
503
  *
@@ -522,8 +501,7 @@ class PLL_Model {
522
  */
523
  public function register_taxonomy() {
524
  // registers the language taxonomy
525
- // object types will be set later once all custom post types are registered
526
- register_taxonomy('language', $this->post_types, array(
527
  'labels' => array(
528
  'name' => __('Languages', 'polylang'),
529
  'singular_name' => __('Language', 'polylang'),
@@ -536,32 +514,31 @@ class PLL_Model {
536
  }
537
 
538
  /*
539
- * post types that need to be translated
540
  *
541
  * @since 1.2
542
  *
543
- * @return array array of post types names for which Polylang manages languages and translations
 
544
  */
545
- protected function get_post_types() {
546
- $post_types = array('post' => 'post', 'page' => 'page');
547
- if (!empty($this->options['media_support']))
548
- $post_types['attachement'] = 'attachment';
549
 
550
- if (is_array($this->options['post_types']))
551
- $post_types = array_merge($post_types, $this->options['post_types']);
 
 
552
 
553
- return apply_filters('pll_get_post_types', $post_types , false);
554
- }
555
 
556
- /*
557
- * returns valid registered post types that need to be translated
558
- *
559
- * @since 1.2
560
- *
561
- * @return array array of registered post type names for which Polylang manages languages and translations
562
- */
563
- public function get_translated_post_types() {
564
- return $this->post_types = array_intersect($this->get_post_types(), get_post_types());
565
  }
566
 
567
  /*
@@ -572,8 +549,7 @@ class PLL_Model {
572
  * @param string $post_type post type name
573
  */
574
  public function registered_post_type($post_type) {
575
- if (in_array($post_type, $this->get_post_types())) {
576
- $this->post_types[$post_type] = $post_type;
577
  register_taxonomy_for_object_type('language', $post_type);
578
  register_taxonomy_for_object_type('post_translations', $post_type);
579
  }
@@ -587,46 +563,31 @@ class PLL_Model {
587
  * @param string|array $post_type post type name or array of post type names
588
  */
589
  public function is_translated_post_type($post_type) {
590
- return (is_array($post_type) && array_intersect($post_type, $this->post_types) || in_array($post_type, $this->post_types));
 
591
  }
592
 
593
  /*
594
- * taxonomies that need to be translated
595
  *
596
  * @since 1.2
597
  *
598
- * @return array array of taxonomy names for which Polylang manages languages and translations
 
599
  */
600
- protected function get_taxonomies() {
601
- $taxonomies = array('category' => 'category', 'post_tag' => 'post_tag');
602
 
603
- if (is_array($this->options['taxonomies']))
604
- $taxonomies = array_merge($taxonomies, $this->options['taxonomies']);
605
 
606
- return apply_filters('pll_get_taxonomies', $taxonomies, false);
607
- }
608
 
609
- /*
610
- * return valid registered taxonomies that need to be translated
611
- *
612
- * @since 1.2
613
- *
614
- * @return array array of registered taxonomy names for which Polylang manages languages and translations
615
- */
616
- public function get_translated_taxonomies() {
617
- return $this->taxonomies = array_intersect($this->get_taxonomies(), get_taxonomies());
618
- }
619
 
620
- /*
621
- * check if registered post type must be translated
622
- *
623
- * @since 1.2
624
- *
625
- * @param string $taxonomy taxonomy name
626
- */
627
- public function registered_taxonomy($taxonomy) {
628
- if (in_array($taxonomy, $this->get_taxonomies()))
629
- $this->taxonomies[$taxonomy] = $taxonomy;
630
  }
631
 
632
  /*
@@ -637,34 +598,36 @@ class PLL_Model {
637
  * @param string|array $tax taxonomy name or array of taxonomy names
638
  */
639
  public function is_translated_taxonomy($tax) {
640
- return (is_array($tax) && array_intersect($tax, $this->taxonomies) || in_array($tax, $this->taxonomies));
 
641
  }
642
 
643
  /*
644
  * it is possible to have several terms with the same name in the same taxonomy (one per language)
645
- * but the native get_term_by will return only one term
646
  * so here the function adds the language parameter
647
  *
648
- * @since 1.2
649
  *
650
- * @param string $field currently the only possibility is 'name'
651
- * @param string $value the term name
652
  * @param string $taxonomy taxonomy name
 
653
  * @param string|object $language the language slug or object
654
  * @return null|int the term_id of the found term
655
  */
656
- public function get_term_by($field, $value, $taxonomy, $language) {
657
  global $wpdb;
658
 
659
- if ('name' != $field)
660
- return NULL;
 
 
 
661
 
662
- return $wpdb->get_row("SELECT t.*, tt.* FROM $wpdb->terms AS t"
663
- . " INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id"
664
- . $this->join_clause('term')
665
- . $wpdb->prepare(" WHERE tt.taxonomy = %s AND t.name = %s", $taxonomy, $value)
666
- . $this->where_clause($this->get_language($language), 'term')
667
- );
668
  }
669
 
670
  /*
@@ -685,26 +648,30 @@ class PLL_Model {
685
  $counts = wp_cache_get($cache_key, 'pll_count_posts');
686
 
687
  if (false === $counts) {
 
 
688
  $where = " WHERE post_status = 'publish'";
689
- $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_type = %s", $q['post_type']);
 
 
690
 
691
  if (!empty($q['m'])) {
692
  $q['m'] = '' . preg_replace('|[^0-9]|', '', $q['m']);
693
- $where .= $wpdb->prepare(" AND YEAR({$wpdb->posts}.post_date) = %d", substr($q['m'], 0, 4));
694
  if ( strlen($q['m']) > 5 )
695
- $where .= $wpdb->prepare(" AND MONTH({$wpdb->posts}.post_date) = %d", substr($q['m'], 4, 2));
696
  if ( strlen($q['m']) > 7 )
697
- $where .= $wpdb->prepare(" AND DAYOFMONTH({$wpdb->posts}.post_date) = %d", substr($q['m'], 6, 2));
698
  }
699
 
700
  if (!empty($q['year']))
701
- $where .= $wpdb->prepare(" AND YEAR({$wpdb->posts}.post_date) = %d", $q['year']);
702
 
703
  if (!empty($q['monthnum']))
704
- $where .= $wpdb->prepare(" AND MONTH({$wpdb->posts}.post_date) = %d", $q['monthnum']);
705
 
706
  if (!empty($q['day']))
707
- $where .= $wpdb->prepare(" AND DAYOFMONTH({$wpdb->posts}.post_date) = %d", $q['day']);
708
 
709
  if (!empty($q['author_name'])) {
710
  $author = get_user_by('slug', sanitize_title_for_query($q['author_name']));
@@ -713,12 +680,14 @@ class PLL_Model {
713
  }
714
 
715
  if (!empty($q['author']))
716
- $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_author = %d", $q['author']);
717
 
718
- $select = "SELECT pll_tr.term_taxonomy_id, COUNT(*) AS num_posts FROM {$wpdb->posts}";
719
- $join = $this->join_clause('post');
720
- $where .= $this->where_clause($this->get_languages_list(), 'post');
721
- $groupby = " GROUP BY pll_tr.term_taxonomy_id";
 
 
722
 
723
  $res = $wpdb->get_results($select . $join . $where . $groupby, ARRAY_A);
724
  foreach ((array) $res as $row)
@@ -744,4 +713,22 @@ class PLL_Model {
744
 
745
  return $args;
746
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
747
  }
7
  */
8
  class PLL_Model {
9
  public $options;
 
10
  private $languages; // used to cache the list of languages
11
 
12
  /*
41
  // registers completely the language taxonomy
42
  add_action('setup_theme', array(&$this, 'register_taxonomy'), 1);
43
 
44
+ // setups post types to translate
45
  add_action('registered_post_type', array(&$this, 'registered_post_type'));
 
46
 
47
  // just in case someone would like to display the language description ;-)
48
  add_filter('language_description', create_function('$v', "return '';"));
61
  * @return array unmodified $terms
62
  */
63
  public function _prime_terms_cache($terms, $taxonomies) {
64
+ if ($this->is_translated_taxonomy($taxonomies)) {
65
+ foreach ($terms as $term) {
66
+ $term_ids[] = is_object($term) ? $term->term_id : $term;
 
67
  }
 
 
68
  }
69
 
70
  if (!empty($term_ids))
149
 
150
  if (!empty($languages) && !empty($term_languages)) {
151
  array_walk($languages, create_function('&$v, $k, $term_languages', '$v = new PLL_Language($v, $term_languages[$v->name]);'), $term_languages);
 
 
 
 
152
  }
153
  else {
154
  $languages = array(); // in case something went wrong
155
  }
156
  }
157
 
 
 
 
 
158
  $this->languages = $languages;
159
+
160
+ // need to wait for $wp_rewrite availibility to set homepage urls
161
+ did_action('setup_theme') ? $this->_languages_list() : add_action('setup_theme', array(&$this, '_languages_list'));
162
  }
163
 
164
  $args = wp_parse_args($args, array('hide_empty' => false));
171
  }
172
 
173
  /*
174
+ * fills home urls and flags in language list and set transient in db
175
+ * delayed to be sure we have access to $wp_rewrite for home urls
176
+ * home urls are not cached in db if PLL_CACHE_HOME_URL is set to false
177
  *
178
+ * @since 1.4
179
  */
180
+ public function _languages_list() {
181
+ if (false === get_transient('pll_languages_list')) {
182
+ if (!defined('PLL_CACHE_HOME_URL') || PLL_CACHE_HOME_URL) {
183
+ foreach ($this->languages as $language)
184
+ $language->set_home_url();
185
+ }
186
+ set_transient('pll_languages_list', $this->languages);
187
+ }
188
 
189
+ foreach ($this->languages as $language) {
190
+ if (defined('PLL_CACHE_HOME_URL') && !PLL_CACHE_HOME_URL)
191
+ $language->set_home_url();
192
+
193
+ // add flags (not in db cache as they may be different on frontend and admin)
194
+ $language->set_flag();
195
+ }
196
  }
197
 
198
  /*
326
  * @return array an associative array of translations with language code as key and translation id as value
327
  */
328
  public function get_translations($type, $id) {
329
+ $type = ($type == 'post' || $this->is_translated_post_type($type)) ? 'post' : (($type == 'term' || $this->is_translated_taxonomy($type)) ? 'term' : false);
330
  return $type && ($term = $this->get_object_term($id, $type . '_translations')) && !empty($term) ? unserialize($term->description) : array();
331
  }
332
 
477
  return " AND pll_tr.term_taxonomy_id IN (" . implode(',', $languages) . ")";
478
  }
479
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
480
  /*
481
  * adds terms clauses to get_terms to filter them by languages - used in both frontend and admin
482
  *
501
  */
502
  public function register_taxonomy() {
503
  // registers the language taxonomy
504
+ register_taxonomy('language', $this->get_translated_post_types(), array(
 
505
  'labels' => array(
506
  'name' => __('Languages', 'polylang'),
507
  'singular_name' => __('Language', 'polylang'),
514
  }
515
 
516
  /*
517
+ * returns post types that need to be translated
518
  *
519
  * @since 1.2
520
  *
521
+ * @param bool $filter true if we should return only valid registered post types
522
+ * @return array post type names for which Polylang manages languages and translations
523
  */
524
+ public function get_translated_post_types($filter = true) {
525
+ static $post_types = array();
 
 
526
 
527
+ // the post types list is cached for better better performance
528
+ // wait for 'after_setup_theme' to apply the cache to allow themes adding the filter in functions.php
529
+ if (!$post_types || !did_action('after_setup_theme')) {
530
+ $post_types = array('post' => 'post', 'page' => 'page');
531
 
532
+ if (!empty($this->options['media_support']))
533
+ $post_types['attachement'] = 'attachment';
534
 
535
+ if (is_array($this->options['post_types']))
536
+ $post_types = array_merge($post_types, $this->options['post_types']);
537
+
538
+ $post_types = apply_filters('pll_get_post_types', $post_types , false);
539
+ }
540
+
541
+ return $filter ? array_intersect($post_types, get_post_types()) : $post_types;
 
 
542
  }
543
 
544
  /*
549
  * @param string $post_type post type name
550
  */
551
  public function registered_post_type($post_type) {
552
+ if ($this->is_translated_post_type($post_type)) {
 
553
  register_taxonomy_for_object_type('language', $post_type);
554
  register_taxonomy_for_object_type('post_translations', $post_type);
555
  }
563
  * @param string|array $post_type post type name or array of post type names
564
  */
565
  public function is_translated_post_type($post_type) {
566
+ $post_types = $this->get_translated_post_types(false);
567
+ return (is_array($post_type) && array_intersect($post_type, $post_types) || in_array($post_type, $post_types));
568
  }
569
 
570
  /*
571
+ * return taxonomies that need to be translated
572
  *
573
  * @since 1.2
574
  *
575
+ * @param bool $filter true if we should return only valid registered taxonmies
576
+ * @return array array of registered taxonomy names for which Polylang manages languages and translations
577
  */
578
+ public function get_translated_taxonomies($filter = true) {
579
+ static $taxonomies = array();
580
 
581
+ if (!$taxonomies || !did_action('after_setup_theme')) {
582
+ $taxonomies = array('category' => 'category', 'post_tag' => 'post_tag');
583
 
584
+ if (is_array($this->options['taxonomies']))
585
+ $taxonomies = array_merge($taxonomies, $this->options['taxonomies']);
586
 
587
+ $taxonomies = apply_filters('pll_get_taxonomies', $taxonomies, false);
588
+ }
 
 
 
 
 
 
 
 
589
 
590
+ return $filter ? array_intersect($taxonomies, get_taxonomies()) : $taxonomies;
 
 
 
 
 
 
 
 
 
591
  }
592
 
593
  /*
598
  * @param string|array $tax taxonomy name or array of taxonomy names
599
  */
600
  public function is_translated_taxonomy($tax) {
601
+ $taxonomies = $this->get_translated_taxonomies(false);
602
+ return (is_array($tax) && array_intersect($tax, $taxonomies) || in_array($tax, $taxonomies));
603
  }
604
 
605
  /*
606
  * it is possible to have several terms with the same name in the same taxonomy (one per language)
607
+ * but the native term_exists will return true even if only one exists
608
  * so here the function adds the language parameter
609
  *
610
+ * @since 1.4
611
  *
612
+ * @param string $term_name the term name
 
613
  * @param string $taxonomy taxonomy name
614
+ * @param int $parent parent term id
615
  * @param string|object $language the language slug or object
616
  * @return null|int the term_id of the found term
617
  */
618
+ public function term_exists($term_name, $taxonomy, $parent, $language) {
619
  global $wpdb;
620
 
621
+ $select = "SELECT t.term_id FROM $wpdb->terms AS t";
622
+ $join = " INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id";
623
+ $join .= $this->join_clause('term');
624
+ $where = $wpdb->prepare(" WHERE tt.taxonomy = %s AND t.name = %s", $taxonomy, $term_name);
625
+ $where .= $this->where_clause($this->get_language($language), 'term');
626
 
627
+ if ($parent > 0)
628
+ $where .= $wpdb->prepare(" AND tt.parent = %d", $parent);
629
+
630
+ return $wpdb->get_var($select . $join . $where);
 
 
631
  }
632
 
633
  /*
648
  $counts = wp_cache_get($cache_key, 'pll_count_posts');
649
 
650
  if (false === $counts) {
651
+ $select = "SELECT pll_tr.term_taxonomy_id, COUNT(*) AS num_posts FROM {$wpdb->posts} AS p";
652
+ $join = $this->join_clause('post');
653
  $where = " WHERE post_status = 'publish'";
654
+ $where .= $wpdb->prepare(" AND p.post_type = %s", $q['post_type']);
655
+ $where .= $this->where_clause($this->get_languages_list(), 'post');
656
+ $groupby = " GROUP BY pll_tr.term_taxonomy_id";
657
 
658
  if (!empty($q['m'])) {
659
  $q['m'] = '' . preg_replace('|[^0-9]|', '', $q['m']);
660
+ $where .= $wpdb->prepare(" AND YEAR(p.post_date) = %d", substr($q['m'], 0, 4));
661
  if ( strlen($q['m']) > 5 )
662
+ $where .= $wpdb->prepare(" AND MONTH(p.post_date) = %d", substr($q['m'], 4, 2));
663
  if ( strlen($q['m']) > 7 )
664
+ $where .= $wpdb->prepare(" AND DAYOFMONTH(p.post_date) = %d", substr($q['m'], 6, 2));
665
  }
666
 
667
  if (!empty($q['year']))
668
+ $where .= $wpdb->prepare(" AND YEAR(p.post_date) = %d", $q['year']);
669
 
670
  if (!empty($q['monthnum']))
671
+ $where .= $wpdb->prepare(" AND MONTH(p.post_date) = %d", $q['monthnum']);
672
 
673
  if (!empty($q['day']))
674
+ $where .= $wpdb->prepare(" AND DAYOFMONTH(p.post_date) = %d", $q['day']);
675
 
676
  if (!empty($q['author_name'])) {
677
  $author = get_user_by('slug', sanitize_title_for_query($q['author_name']));
680
  }
681
 
682
  if (!empty($q['author']))
683
+ $where .= $wpdb->prepare(" AND p.post_author = %d", $q['author']);
684
 
685
+ if (!empty($q['post_format'])) {
686
+ $join .= " INNER JOIN {$wpdb->term_relationships} AS tr ON tr.object_id = p.ID";
687
+ $join .= " INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_taxonomy_id = tr.term_taxonomy_id";
688
+ $join .= " INNER JOIN {$wpdb->terms} AS t ON t.term_id = tt.term_id";
689
+ $where .= $wpdb->prepare(" AND t.slug = %s", $q['post_format']);
690
+ }
691
 
692
  $res = $wpdb->get_results($select . $join . $where . $groupby, ARRAY_A);
693
  foreach ((array) $res as $row)
713
 
714
  return $args;
715
  }
716
+
717
+ /*
718
+ * returns ids of objects in a language similarly to get_objects_in_term for a taxonomy
719
+ * faster than get_objects_in_term as it avoids a JOIN
720
+ *
721
+ * @since 1.4
722
+ *
723
+ * @param object $lang a PLL_Language object
724
+ * @param string $type optional, either 'post' or 'term', defaults to 'post'
725
+ * @return array
726
+ */
727
+ public function get_objects_in_language($lang, $type = 'post') {
728
+ global $wpdb;
729
+ return $wpdb->get_col($wpdb->prepare("
730
+ SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d",
731
+ 'term' == $type ? $lang->tl_term_taxonomy_id : $lang->term_taxonomy_id
732
+ ));
733
+ }
734
  }
include/olt-manager.php CHANGED
@@ -44,40 +44,39 @@ class PLL_OLT_Manager {
44
  */
45
  public function load_textdomains() {
46
  // our override_load_textdomain filter has done its job. let's remove it before calling load_textdomain
47
- remove_filter('override_load_textdomain', array(&$this, 'mofile'));
48
  remove_filter('gettext', array(&$this, 'gettext'), 10, 3);
49
  remove_filter('gettext_with_context', array(&$this, 'gettext_with_context'), 10, 4);
50
  $new_locale = get_locale();
51
 
52
- if ('en_US' != $new_locale) { // save some time for en_US
53
- // now we can load all overriden text domains with the right language
54
- foreach ($this->list_textdomains as $textdomain) {
55
- if (!load_textdomain($textdomain['domain'], str_replace("{$this->default_locale}.mo", "$new_locale.mo", $textdomain['mo']))) {
56
- // since WP 3.5 themes may store languages files in /wp-content/languages/themes
57
- if (!load_textdomain($textdomain['domain'], WP_LANG_DIR . "/themes/{$textdomain['domain']}-$new_locale.mo")) {
58
- // since WP 3.7 plugins may store languages files in /wp-content/languages/plugins
59
- load_textdomain($textdomain['domain'], WP_LANG_DIR . "/plugins/{$textdomain['domain']}-$new_locale.mo");
60
- }
61
  }
62
  }
 
63
 
64
- // translate labels of post types and taxonomies
65
- foreach ($GLOBALS['wp_taxonomies'] as $tax)
66
- $this->translate_labels($tax);
67
- foreach ($GLOBALS['wp_post_types'] as $pt)
68
- $this->translate_labels($pt);
69
-
70
- // act only if the language has not been set early (before default textdomain loading and $wp_locale creation
71
- if (did_action('after_setup_theme')) {
72
- // reinitializes wp_locale for weekdays and months
73
- unset($GLOBALS['wp_locale']);
74
- $GLOBALS['wp_locale'] = new WP_Locale();
75
- }
76
-
77
- // allow plugins to translate text the same way we do for post types and taxonomies labels
78
- do_action_ref_array('pll_translate_labels', array(&$this->labels));
79
  }
80
 
 
 
 
81
  // free memory
82
  unset($this->default_locale, $this->list_textdomains, $this->labels);
83
  }
@@ -136,11 +135,19 @@ class PLL_OLT_Manager {
136
  * @param object $type either a post type or a taxonomy
137
  */
138
  public function translate_labels($type) {
 
 
 
139
  foreach($type->labels as $key => $label) {
140
  if (is_string($label) && isset($this->labels[$label])) {
141
- $type->labels->$key = isset($this->labels[$label]['context']) ?
142
- _x($label, $this->labels[$label]['context'], $this->labels[$label]['domain']) :
143
- __($label, $this->labels[$label]['domain']);
 
 
 
 
 
144
  }
145
  }
146
  }
44
  */
45
  public function load_textdomains() {
46
  // our override_load_textdomain filter has done its job. let's remove it before calling load_textdomain
47
+ remove_filter('override_load_textdomain', array(&$this, 'mofile'), 10, 3);
48
  remove_filter('gettext', array(&$this, 'gettext'), 10, 3);
49
  remove_filter('gettext_with_context', array(&$this, 'gettext_with_context'), 10, 4);
50
  $new_locale = get_locale();
51
 
52
+ // don't try to save time for en_US as some users have theme written in another language
53
+ // now we can load all overriden text domains with the right language
54
+ foreach ($this->list_textdomains as $textdomain) {
55
+ if (!load_textdomain($textdomain['domain'], str_replace("{$this->default_locale}.mo", "$new_locale.mo", $textdomain['mo']))) {
56
+ // since WP 3.5 themes may store languages files in /wp-content/languages/themes
57
+ if (!load_textdomain($textdomain['domain'], WP_LANG_DIR . "/themes/{$textdomain['domain']}-$new_locale.mo")) {
58
+ // since WP 3.7 plugins may store languages files in /wp-content/languages/plugins
59
+ load_textdomain($textdomain['domain'], WP_LANG_DIR . "/plugins/{$textdomain['domain']}-$new_locale.mo");
 
60
  }
61
  }
62
+ }
63
 
64
+ // translate labels of post types and taxonomies
65
+ foreach ($GLOBALS['wp_taxonomies'] as $tax)
66
+ $this->translate_labels($tax);
67
+ foreach ($GLOBALS['wp_post_types'] as $pt)
68
+ $this->translate_labels($pt);
69
+
70
+ // act only if the language has not been set early (before default textdomain loading and $wp_locale creation
71
+ if (did_action('after_setup_theme')) {
72
+ // reinitializes wp_locale for weekdays and months
73
+ unset($GLOBALS['wp_locale']);
74
+ $GLOBALS['wp_locale'] = new WP_Locale();
 
 
 
 
75
  }
76
 
77
+ // allow plugins to translate text the same way we do for post types and taxonomies labels
78
+ do_action_ref_array('pll_translate_labels', array(&$this->labels));
79
+
80
  // free memory
81
  unset($this->default_locale, $this->list_textdomains, $this->labels);
82
  }
135
  * @param object $type either a post type or a taxonomy
136
  */
137
  public function translate_labels($type) {
138
+ // use static array to avoid translating several times the same (default) labels
139
+ static $translated = array();
140
+
141
  foreach($type->labels as $key => $label) {
142
  if (is_string($label) && isset($this->labels[$label])) {
143
+ if (empty($translated[$label])) {
144
+ $type->labels->$key = $translated[$label] = isset($this->labels[$label]['context']) ?
145
+ _x($label, $this->labels[$label]['context'], $this->labels[$label]['domain']) :
146
+ __($label, $this->labels[$label]['domain']);
147
+ }
148
+ else {
149
+ $type->labels->$key = $translated[$label];
150
+ }
151
  }
152
  }
153
  }
include/plugins-compat.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
 
3
  /*
4
- * manages compatibility with 3rd party plugins
5
  * this class is available as soon as the plugin is loaded
6
  *
7
  * @since 1.0
@@ -31,6 +31,12 @@ class PLL_Plugins_Compat {
31
 
32
  // Aqua Resizer
33
  add_filter('pll_home_url_black_list', create_function('$arr', "return array_merge(\$arr, array(array('function' => 'aq_resize')));"));
 
 
 
 
 
 
34
  }
35
 
36
  /*
@@ -104,4 +110,64 @@ class PLL_Plugins_Compat {
104
  if (isset($custom_field_template, $_REQUEST['from_post'], $_REQUEST['new_lang']) && !empty($post))
105
  $_REQUEST['post'] = $post->ID;
106
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  }
1
  <?php
2
 
3
  /*
4
+ * manages compatibility with 3rd party plugins (and themes)
5
  * this class is available as soon as the plugin is loaded
6
  *
7
  * @since 1.0
31
 
32
  // Aqua Resizer
33
  add_filter('pll_home_url_black_list', create_function('$arr', "return array_merge(\$arr, array(array('function' => 'aq_resize')));"));
34
+
35
+ // Twenty Fourteen
36
+ add_filter('transient_featured_content_ids', array(&$this, 'twenty_fourteen_featured_content_ids'));
37
+
38
+ if (!PLL_ADMIN)
39
+ add_filter('option_featured-content', array(&$this, 'twenty_fourteen_option_featured_content'));
40
  }
41
 
42
  /*
110
  if (isset($custom_field_template, $_REQUEST['from_post'], $_REQUEST['new_lang']) && !empty($post))
111
  $_REQUEST['post'] = $post->ID;
112
  }
113
+
114
+ /*
115
+ * rewrites the function Featured_Content::get_featured_post_ids()
116
+ *
117
+ * @since 1.4
118
+ *
119
+ * @param array $ids featured posts ids
120
+ * @return array modified featured posts ids (include all languages)
121
+ */
122
+ public function twenty_fourteen_featured_content_ids($featured_ids) {
123
+ if (false !== $featured_ids)
124
+ return $featured_ids;
125
+
126
+ $settings = Featured_Content::get_setting();
127
+
128
+ if (!$term = get_term_by( 'name', $settings['tag-name'], 'post_tag' ))
129
+ return $featured_ids;
130
+
131
+ // get fearured tag translations
132
+ $tags = $GLOBALS['polylang']->model->get_translations('term' ,$term->term_id);
133
+ $ids = array();
134
+
135
+ // Query for featured posts in all languages
136
+ // one query per language to get the correct number of posts per language
137
+ foreach ($tags as $tag) {
138
+ $_ids = get_posts(array(
139
+ 'lang' => 0, // avoid language filters
140
+ 'fields' => 'ids',
141
+ 'numberposts' => $settings['quantity'],
142
+ 'tax_query' => array(array(
143
+ 'taxonomy' => 'post_tag',
144
+ 'terms' => (int) $tag,
145
+ )),
146
+ ));
147
+
148
+ $ids = array_merge($ids, $_ids);
149
+ }
150
+
151
+ $ids = array_map( 'absint', $ids );
152
+ set_transient( 'featured_content_ids', $ids );
153
+
154
+ return $ids;
155
+ }
156
+
157
+ /*
158
+ * translates the featured tag id in featured content settings
159
+ * mainly to allow hiding it when requested in featured content options
160
+ * acts only on frontend
161
+ *
162
+ * @since 1.4
163
+ *
164
+ * @param array $settings featured content settings
165
+ * @return array modified $settings
166
+ */
167
+ public function twenty_fourteen_option_featured_content($settings) {
168
+ if ($settings['tag-id'] && $tr = pll_get_term($settings['tag-id']))
169
+ $settings['tag-id'] = $tr;
170
+
171
+ return $settings;
172
+ }
173
  }
include/upgrade.php CHANGED
@@ -88,10 +88,13 @@ class PLL_Upgrade {
88
  * @since 1.2
89
  */
90
  public function _upgrade() {
91
- foreach (array('0.9', '1.0', '1.1', '1.2', '1.2.1', '1.2.3', '1.3', '1.3.1') as $version)
92
  if (version_compare($this->options['version'], $version, '<'))
93
  call_user_func(array(&$this, 'upgrade_' . str_replace('.', '_', $version)));
94
 
 
 
 
95
  $this->options['version'] = POLYLANG_VERSION;
96
  update_option('polylang', $this->options);
97
  }
@@ -361,20 +364,24 @@ class PLL_Upgrade {
361
  }
362
 
363
  /*
364
- * upgrades if the previous version is < 1.3.1
365
- * deletes language cache (due to bug correction in home urls)
 
366
  *
367
- * @since 1.3.1
368
  */
369
- protected function upgrade_1_3_1() {
 
370
  delete_transient('pll_languages_list');
371
  }
372
 
373
  /*
374
- * FIXME don't delete old data in 1.2, just in case...
375
- * ready for a next version
 
 
376
  */
377
- protected function upgrade_1_4() {
378
  // suppress data of the old model < 1.2
379
  global $wpdb;
380
  $wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
@@ -395,5 +402,7 @@ class PLL_Upgrade {
395
  $languages = get_terms('language', array('hide_empty'=>false));
396
  foreach ($languages as $lang)
397
  delete_option('polylang_mo'.$lang->term_id);
 
 
398
  }
399
  }
88
  * @since 1.2
89
  */
90
  public function _upgrade() {
91
+ foreach (array('0.9', '1.0', '1.1', '1.2', '1.2.1', '1.2.3', '1.3', '1.4') as $version)
92
  if (version_compare($this->options['version'], $version, '<'))
93
  call_user_func(array(&$this, 'upgrade_' . str_replace('.', '_', $version)));
94
 
95
+ if (absint(get_transient('pll_upgrade_1_4')) < time())
96
+ $this->delete_pre_1_2_data();
97
+
98
  $this->options['version'] = POLYLANG_VERSION;
99
  update_option('polylang', $this->options);
100
  }
364
  }
365
 
366
  /*
367
+ * upgrades if the previous version is < 1.4
368
+ * sets a transient to delete old model data
369
+ * deletes language cache (due to bug correction in home urls in 1.3.1 and added mo_id in 1.4)
370
  *
371
+ * @since 1.4
372
  */
373
+ protected function upgrade_1_4() {
374
+ set_transient('pll_upgrade_1_4', time() + 60 * 24 * 60 * 60); // 60 days
375
  delete_transient('pll_languages_list');
376
  }
377
 
378
  /*
379
+ * old data were not deleted in 1.2, just in case...
380
+ * delete them at first upgrade at least 60 days after upgrade to 1.4
381
+ *
382
+ * @since 1.4
383
  */
384
+ protected function delete_pre_1_2_data() {
385
  // suppress data of the old model < 1.2
386
  global $wpdb;
387
  $wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
402
  $languages = get_terms('language', array('hide_empty'=>false));
403
  foreach ($languages as $lang)
404
  delete_option('polylang_mo'.$lang->term_id);
405
+
406
+ delete_transient('pll_upgrade_1_4');
407
  }
408
  }
include/wpml-compat.php CHANGED
@@ -12,13 +12,15 @@
12
  * @since 0.9.5
13
  */
14
  function pll_define_wpml_constants() {
15
- $code = PLL_ADMIN ? get_user_meta(get_current_user_id(), 'pll_filter_content', true) : pll_current_language();
16
 
17
- if(!defined('ICL_LANGUAGE_CODE') && !empty($code))
18
- define('ICL_LANGUAGE_CODE', $code);
 
19
 
20
- if(!defined('ICL_LANGUAGE_NAME') && !empty($code))
21
- define('ICL_LANGUAGE_NAME', $GLOBALS['polylang']->model->get_language($code)->name);
 
22
  }
23
 
24
  add_action('pll_language_defined', 'pll_define_wpml_constants');
12
  * @since 0.9.5
13
  */
14
  function pll_define_wpml_constants() {
15
+ global $polylang;
16
 
17
+ if (!empty($polylang->curlang)) {
18
+ if(!defined('ICL_LANGUAGE_CODE'))
19
+ define('ICL_LANGUAGE_CODE', $polylang->curlang->slug);
20
 
21
+ if(!defined('ICL_LANGUAGE_NAME'))
22
+ define('ICL_LANGUAGE_NAME', $polylang->curlang->name);
23
+ }
24
  }
25
 
26
  add_action('pll_language_defined', 'pll_define_wpml_constants');
js/post.js CHANGED
@@ -222,6 +222,36 @@ jQuery(document).ready(function($) {
222
  );
223
  });
224
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  // ajax for changing the post's language in the languages metabox
226
  $('#post_lang_choice').change( function() {
227
  var data = {
@@ -237,6 +267,7 @@ jQuery(document).ready(function($) {
237
  switch (this.what) {
238
  case 'translations': // translations fields
239
  $('#post-translations').html(this.data);
 
240
  break;
241
  case 'taxonomy': // categories metabox for posts
242
  var tax = this.data;
@@ -291,7 +322,7 @@ jQuery(document).ready(function($) {
291
  $.each(res.responses, function() {
292
  switch (this.what) {
293
  case 'translations': // translations fields
294
- $('.translations').html(this.data); // backward compatibility WP < 3.5
295
  $('.compat-field-translations').html(this.data); // WP 3.5+
296
  break;
297
  default:
222
  );
223
  });
224
 
225
+ // ajax for changing a translation in post languages metabox
226
+ function change_translations() {
227
+ var td = $(this).parent().siblings('.pll-edit-column');
228
+ td.children('a').hide();
229
+ td.children('.spinner').show();
230
+
231
+ var data = {
232
+ action: 'post_translation_choice',
233
+ lang: $('#post_lang_choice').attr('value'),
234
+ post_id: $('#post_ID').attr('value'),
235
+ value: $(this).attr('value')
236
+ }
237
+
238
+ $.post(ajaxurl, data , function(response) {
239
+ var res = wpAjax.parseAjaxResponse(response, 'ajax-response');
240
+ $.each(res.responses, function() {
241
+ switch (this.what) {
242
+ case 'link':
243
+ td.children('.spinner').hide();
244
+ td.html(this.data);
245
+ break;
246
+ default:
247
+ break;
248
+ }
249
+ });
250
+ });
251
+ }
252
+
253
+ $("select[name*='post_tr_lang']").change(change_translations);
254
+
255
  // ajax for changing the post's language in the languages metabox
256
  $('#post_lang_choice').change( function() {
257
  var data = {
267
  switch (this.what) {
268
  case 'translations': // translations fields
269
  $('#post-translations').html(this.data);
270
+ $("select[name*='post_tr_lang']").change(change_translations);
271
  break;
272
  case 'taxonomy': // categories metabox for posts
273
  var tax = this.data;
322
  $.each(res.responses, function() {
323
  switch (this.what) {
324
  case 'translations': // translations fields
325
+ $('.translations').html(this.data);
326
  $('.compat-field-translations').html(this.data); // WP 3.5+
327
  break;
328
  default:
js/post.min.js CHANGED
@@ -1 +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.prop("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);(function(b){var a=inlineEditPost.edit;inlineEditPost.edit=function(g){a.apply(this,arguments);var c=0;if(typeof(g)=="object"){c=parseInt(this.getId(g))}if(c>0){var f=b("#edit-"+c);var d=f.find(':input[name="inline_lang_choice"]');d.find("option:selected").removeProp("selected");var e=b("#lang_"+c).html();b("input[name='old_lang']").val(e);d.find('option[value="'+e+'"]').prop("selected",true)}}})(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("#pageparentdiv > .inside").html(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}})}b(".media_lang_choice").change(function(){var c={action:"media_lang_choice",lang:b(this).attr("value"),post_id:b(this).attr("name")};b.post(ajaxurl,c,function(d){var e=wpAjax.parseAjaxResponse(d,"ajax-response");b.each(e.responses,function(){switch(this.what){case"translations":b(".translations").html(this.data);b(".compat-field-translations").html(this.data);break;default:break}})})})});
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.prop("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);(function(b){var a=inlineEditPost.edit;inlineEditPost.edit=function(g){a.apply(this,arguments);var c=0;if(typeof(g)=="object"){c=parseInt(this.getId(g))}if(c>0){var f=b("#edit-"+c);var d=f.find(':input[name="inline_lang_choice"]');d.find("option:selected").removeProp("selected");var e=b("#lang_"+c).html();b("input[name='old_lang']").val(e);d.find('option[value="'+e+'"]').prop("selected",true)}}})(jQuery);jQuery(document).ready(function(c){var b=new Array();c(".categorydiv").each(function(){var f=c(this).attr("id"),e,d;e=f.split("-");e.shift();d=e.join("-");b.push(d);c("#"+d+"-add-submit").before(c("<input />").attr("type","hidden").attr("id",d+"-lang").attr("name","term_lang_choice").attr("value",c("#post_lang_choice").attr("value")))});function a(){var e=c(this).parent().siblings(".pll-edit-column");e.children("a").hide();e.children(".spinner").show();var d={action:"post_translation_choice",lang:c("#post_lang_choice").attr("value"),post_id:c("#post_ID").attr("value"),value:c(this).attr("value")};c.post(ajaxurl,d,function(f){var g=wpAjax.parseAjaxResponse(f,"ajax-response");c.each(g.responses,function(){switch(this.what){case"link":e.children(".spinner").hide();e.html(this.data);break;default:break}})})}c("select[name*='post_tr_lang']").change(a);c("#post_lang_choice").change(function(){var d={action:"post_lang_choice",lang:c(this).attr("value"),taxonomies:b,post_id:c("#post_ID").attr("value")};c.post(ajaxurl,d,function(e){var f=wpAjax.parseAjaxResponse(e,"ajax-response");c.each(f.responses,function(){switch(this.what){case"translations":c("#post-translations").html(this.data);c("select[name*='post_tr_lang']").change(a);break;case"taxonomy":var g=this.data;c("#"+g+"checklist").html(this.supplemental.all);c("#"+g+"checklist-pop").html(this.supplemental.populars);c("#new"+g+"_parent").replaceWith(this.supplemental.dropdown);c("#"+g+"-lang").val(c("#post_lang_choice").attr("value"));break;case"pages":c("#pageparentdiv > .inside").html(this.data);break;default:break}});c(".tagcloud-link").each(function(){var g=c(this).attr("id");pll_tagBox.get(g,0)});pll_tagBox.suggest()})});if(c("#pll-tagsdiv-post_tag").length){pll_tagBox.init()}else{c("#side-sortables, #normal-sortables, #advanced-sortables").children("div.postbox").each(function(){if(this.id.indexOf("pll-tagsdiv-")===0){pll_tagBox.init();return false}})}c(".media_lang_choice").change(function(){var d={action:"media_lang_choice",lang:c(this).attr("value"),post_id:c(this).attr("name")};c.post(ajaxurl,d,function(e){var f=wpAjax.parseAjaxResponse(e,"ajax-response");c.each(f.responses,function(){switch(this.what){case"translations":c(".translations").html(this.data);c(".compat-field-translations").html(this.data);break;default:break}})})})});
js/term.js CHANGED
@@ -1,32 +1,70 @@
1
  // quick edit
2
- (function($) {
3
- var $wp_inline_edit = inlineEditTax.edit;
4
-
5
- inlineEditTax.edit = function( id ) {
6
- $wp_inline_edit.apply( this, arguments );
7
- var $term_id = 0;
8
- if ( typeof( id ) == 'object' )
9
- $term_id = parseInt( this.getId( id ) );
10
-
11
- if ( $term_id > 0 ) {
12
- var $edit_row = $('#edit-' + $term_id);
13
- var $select = $edit_row.find(':input[name="inline_lang_choice"]');
14
- $select.find('option:selected').removeProp('selected');
15
- var lang = $('#lang_' + $term_id).html();
16
- $("input[name='old_lang']").val(lang);
17
- $select.find('option[value="'+lang+'"]').prop('selected', true);
 
 
18
  }
19
- }
20
- })(jQuery);
21
 
22
  jQuery(document).ready(function($) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  // ajax for changing the term's language
24
  $('#term_lang_choice').change(function() {
25
  var data = {
26
  action: 'term_lang_choice',
27
  lang: $(this).attr('value'),
28
  term_id: $("input[name='tag_ID']").attr('value'),
29
- taxonomy: $("input[name='taxonomy']").attr('value')
 
30
  }
31
 
32
  $.post(ajaxurl, data, function(response) {
@@ -35,6 +73,7 @@ jQuery(document).ready(function($) {
35
  switch (this.what) {
36
  case 'translations': // translations fields
37
  $("#term-translations").html(this.data);
 
38
  break;
39
  case 'parent': // parent dropdown list for hierarchical taxonomies
40
  $('#parent').replaceWith(this.data);
@@ -48,4 +87,5 @@ jQuery(document).ready(function($) {
48
  });
49
  });
50
  });
 
51
  });
1
  // quick edit
2
+ if ('undefined' != typeof(inlineEditTax)) {
3
+ (function($) {
4
+ var $wp_inline_edit = inlineEditTax.edit;
5
+
6
+ inlineEditTax.edit = function( id ) {
7
+ $wp_inline_edit.apply( this, arguments );
8
+ var $term_id = 0;
9
+ if ( typeof( id ) == 'object' )
10
+ $term_id = parseInt( this.getId( id ) );
11
+
12
+ if ( $term_id > 0 ) {
13
+ var $edit_row = $('#edit-' + $term_id);
14
+ var $select = $edit_row.find(':input[name="inline_lang_choice"]');
15
+ $select.find('option:selected').removeProp('selected');
16
+ var lang = $('#lang_' + $term_id).html();
17
+ $("input[name='old_lang']").val(lang);
18
+ $select.find('option[value="'+lang+'"]').prop('selected', true);
19
+ }
20
  }
21
+ })(jQuery);
22
+ }
23
 
24
  jQuery(document).ready(function($) {
25
+ // ajax for changing a translation in edit-tags.php
26
+ function change_translations() {
27
+ var td = $(this).parent().siblings('.pll-edit-column');
28
+ if (!td)
29
+ return;
30
+
31
+ td.children('a').hide();
32
+ td.children('.spinner').show();
33
+
34
+ var data = {
35
+ action: 'term_translation_choice',
36
+ lang: $('#term_lang_choice').attr('value'),
37
+ term_id: $("input[name='tag_ID']").attr('value'),
38
+ taxonomy: $("input[name='taxonomy']").attr('value'),
39
+ post_type: typenow,
40
+ value: $(this).attr('value')
41
+ }
42
+
43
+ $.post(ajaxurl, data , function(response) {
44
+ var res = wpAjax.parseAjaxResponse(response, 'ajax-response');
45
+ $.each(res.responses, function() {
46
+ switch (this.what) {
47
+ case 'link':
48
+ td.children('.spinner').hide();
49
+ td.html(this.data);
50
+ break;
51
+ default:
52
+ break;
53
+ }
54
+ });
55
+ });
56
+ }
57
+
58
+ $("select[name*='term_tr_lang']").change(change_translations);
59
+
60
  // ajax for changing the term's language
61
  $('#term_lang_choice').change(function() {
62
  var data = {
63
  action: 'term_lang_choice',
64
  lang: $(this).attr('value'),
65
  term_id: $("input[name='tag_ID']").attr('value'),
66
+ taxonomy: $("input[name='taxonomy']").attr('value'),
67
+ post_type: typenow
68
  }
69
 
70
  $.post(ajaxurl, data, function(response) {
73
  switch (this.what) {
74
  case 'translations': // translations fields
75
  $("#term-translations").html(this.data);
76
+ $("select[name*='term_tr_lang']").change(change_translations);
77
  break;
78
  case 'parent': // parent dropdown list for hierarchical taxonomies
79
  $('#parent').replaceWith(this.data);
87
  });
88
  });
89
  });
90
+
91
  });
js/term.min.js CHANGED
@@ -1 +1 @@
1
- (function(b){var a=inlineEditTax.edit;inlineEditTax.edit=function(g){a.apply(this,arguments);var d=0;if(typeof(g)=="object"){d=parseInt(this.getId(g))}if(d>0){var f=b("#edit-"+d);var c=f.find(':input[name="inline_lang_choice"]');c.find("option:selected").removeProp("selected");var e=b("#lang_"+d).html();b("input[name='old_lang']").val(e);c.find('option[value="'+e+'"]').prop("selected",true)}}})(jQuery);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(c){var d=wpAjax.parseAjaxResponse(c,"ajax-response");a.each(d.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}})})})});
1
+ if("undefined"!=typeof(inlineEditTax)){(function(b){var a=inlineEditTax.edit;inlineEditTax.edit=function(g){a.apply(this,arguments);var d=0;if(typeof(g)=="object"){d=parseInt(this.getId(g))}if(d>0){var f=b("#edit-"+d);var c=f.find(':input[name="inline_lang_choice"]');c.find("option:selected").removeProp("selected");var e=b("#lang_"+d).html();b("input[name='old_lang']").val(e);c.find('option[value="'+e+'"]').prop("selected",true)}}})(jQuery)}jQuery(document).ready(function(b){function a(){var d=b(this).parent().siblings(".pll-edit-column");if(!d){return}d.children("a").hide();d.children(".spinner").show();var c={action:"term_translation_choice",lang:b("#term_lang_choice").attr("value"),term_id:b("input[name='tag_ID']").attr("value"),taxonomy:b("input[name='taxonomy']").attr("value"),post_type:typenow,value:b(this).attr("value")};b.post(ajaxurl,c,function(e){var f=wpAjax.parseAjaxResponse(e,"ajax-response");b.each(f.responses,function(){switch(this.what){case"link":d.children(".spinner").hide();d.html(this.data);break;default:break}})})}b("select[name*='term_tr_lang']").change(a);b("#term_lang_choice").change(function(){var c={action:"term_lang_choice",lang:b(this).attr("value"),term_id:b("input[name='tag_ID']").attr("value"),taxonomy:b("input[name='taxonomy']").attr("value"),post_type:typenow};b.post(ajaxurl,c,function(d){var e=wpAjax.parseAjaxResponse(d,"ajax-response");b.each(e.responses,function(){switch(this.what){case"translations":b("#term-translations").html(this.data);b("select[name*='term_tr_lang']").change(a);break;case"parent":b("#parent").replaceWith(this.data);break;case"tag_cloud":b(".tagcloud").replaceWith(this.data);break;default:break}})})})});
languages/polylang-et.mo CHANGED
Binary file
languages/polylang-et.po CHANGED
@@ -3,38 +3,55 @@ msgstr ""
3
  "Project-Id-Version: Polylang\n"
4
  "Report-Msgid-Bugs-To: \n"
5
  "POT-Creation-Date: \n"
6
- "PO-Revision-Date: 2013-12-03 16:43+0100\n"
7
  "Last-Translator: Ahto Naris <ahto.naris@live.com>\n"
8
  "Language-Team: \n"
9
- "Language: \n"
10
  "MIME-Version: 1.0\n"
11
  "Content-Type: text/plain; charset=UTF-8\n"
12
  "Content-Transfer-Encoding: 8bit\n"
13
  "Plural-Forms: nplurals=2; plural=n != 1;\n"
14
  "X-Poedit-SourceCharset: utf-8\n"
15
- "X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2\n"
 
16
  "X-Poedit-Basepath: ../\n"
17
  "X-Textdomain-Support: yes\n"
18
- "X-Generator: Poedit 1.5.5\n"
19
  "X-Poedit-SearchPath-0: .\n"
20
 
21
  # @ polylang
22
  #: admin/view-about.php:3
23
  #, php-format
24
- msgid "Polylang is provided with an extensive %sdocumentation%s (in English only). It includes information on how to set up your multilingual site and use it on a daily basis, a FAQ, as well as a documentation for programmers to adapt their plugins and themes."
25
- msgstr "Polylang on varustatud ulatusliku %sdokumentatsiooniga%s (ainult inglise keeles). See sisaldab teavet kuidas luua ja kasutada igapäevaselt oma mitmekeelset kodulehte, KKK-d ning ka dokumentatsiooni programmeerijatele kuidas kohandada oma pluginad ja teemad."
 
 
 
 
 
 
 
 
26
 
27
  # @ polylang
28
  #: admin/view-about.php:9
29
  #, php-format
30
- msgid "You will also find useful information in the %ssupport forum%s. However don't forget to make a search before posting a new topic."
31
- msgstr "Kasulikku informatsiooni on võimalik ka leida %sfoorumist%s. Paljud teemad on enne foorumis juba läbi arutatud, seega kasuta enne uue teema postitamist otsingut."
 
 
 
 
 
32
 
33
  # @ polylang
34
  #: admin/view-about.php:16
35
  #, php-format
36
- msgid "Polylang is free of charge and is released under the same license as WordPress, the %sGPL%s."
37
- msgstr "Polylang on tasuta ja avaldatud sama litsentsi alusel nagu WordPress - %sGPL%s."
 
 
 
 
38
 
39
  # @ polylang
40
  #: admin/view-about.php:22
@@ -44,15 +61,16 @@ msgstr "Kui sul on isu selles projektis abiks olla alusta %ssiit%s."
44
 
45
  # @ polylang
46
  #: admin/view-about.php:27
47
- msgid "Finally if you like this plugin or if it helps your business, donations to the author are greatly appreciated."
48
- msgstr "Kui see plugin meeldib teile või aitab teie äri kaaluge autorile annetuse tegemist."
 
 
 
 
49
 
50
  # @ polylang
51
- #: admin/admin-filters-post.php:81
52
- #: admin/admin.php:76
53
- #: admin/settings.php:42
54
- #: admin/settings.php:57
55
- #: include/model.php:501
56
  msgid "Languages"
57
  msgstr "Keeled"
58
 
@@ -92,38 +110,28 @@ msgid "Show all languages"
92
  msgstr "Näita kõiki keeli"
93
 
94
  # @ polylang
95
- #: admin/admin-filters-columns.php:126
96
- #: admin/admin-filters-columns.php:218
97
  msgid "Add new translation"
98
  msgstr "Lisa uus tõlge"
99
 
100
  # @ polylang
101
- #: admin/admin-filters-columns.php:160
102
- #: admin/admin-filters-media.php:57
103
- #: admin/admin-filters-post.php:114
104
- #: admin/admin-filters-term.php:73
105
- #: admin/admin-filters-term.php:110
106
- #: admin/view-translations-media.php:7
107
- #: admin/view-translations-media.php:45
108
- #: admin/view-translations-post.php:8
109
- #: admin/view-translations-term.php:15
110
- #: include/model.php:502
111
  msgid "Language"
112
  msgstr "Keel"
113
 
114
  # @ polylang
115
- #: admin/admin-filters-media.php:72
116
- #: admin/admin-filters-media.php:111
117
- #: admin/table-string.php:111
118
- #: admin/view-translations-media.php:42
119
- #: admin/view-translations-term.php:6
120
- #: admin/view-translations-term.php:11
121
  msgid "Translations"
122
  msgstr "Tõlked"
123
 
124
  # @ polylang
125
- #: admin/admin-filters-term.php:75
126
- #: admin/admin-filters-term.php:112
127
  msgid "Sets the language"
128
  msgstr "Määrab keele"
129
 
@@ -133,8 +141,7 @@ msgid "The widget is displayed for:"
133
  msgstr "Moodul kuvatakse:"
134
 
135
  # @ polylang
136
- #: admin/admin-filters.php:62
137
- #: include/model.php:503
138
  msgid "All languages"
139
  msgstr "Kõik keeled"
140
 
@@ -149,8 +156,7 @@ msgid "Wordpress default"
149
  msgstr "Wordpressi vaikimisi väärtus"
150
 
151
  # @ polylang
152
- #: admin/admin.php:116
153
- #: admin/settings.php:62
154
  msgid "Settings"
155
  msgstr "Sätted"
156
 
@@ -191,8 +197,12 @@ msgstr "Keelel peab olema nimetus"
191
 
192
  # @ polylang
193
  #: admin/settings.php:78
194
- msgid "The language was created, but the WordPress language file was not downloaded. Please install it manually."
195
- msgstr "Keel loodi, aga WordPressi keelefaili allalaadimine ebaõnnestus. Palun paigalda see käsitsi."
 
 
 
 
196
 
197
  # @ polylang
198
  #: admin/settings.php:308
@@ -260,8 +270,7 @@ msgid "Edit language"
260
  msgstr "Muuda keelt"
261
 
262
  # @ polylang
263
- #: admin/view-languages.php:42
264
- #: admin/view-languages.php:117
265
  msgid "Add new language"
266
  msgstr "Lisa uus keel"
267
 
@@ -273,11 +282,12 @@ msgstr "Vali keel"
273
  # @ polylang
274
  #: admin/view-languages.php:72
275
  msgid "You can choose a language in the list or directly edit it below."
276
- msgstr "Saate valida keele loendist või vahetult redigeerida allpool olevates lahtrites."
 
 
277
 
278
  # @ polylang
279
- #: admin/table-languages.php:74
280
- #: admin/view-languages.php:76
281
  msgid "Full name"
282
  msgstr "Täisnimi"
283
 
@@ -287,15 +297,18 @@ msgid "The name is how it is displayed on your site (for example: English)."
287
  msgstr "Täisnimi kuvatakse sinu lehel (näiteks: Eesti)."
288
 
289
  # @ polylang
290
- #: admin/table-languages.php:75
291
- #: admin/view-languages.php:82
292
  msgid "Locale"
293
  msgstr "Locale"
294
 
295
  # @ polylang
296
  #: admin/view-languages.php:87
297
- msgid "Wordpress Locale for the language (for example: en_US). You will need to install the .mo file for this language."
298
- msgstr "WordPress Locale keelele (näiteks: en_US). Peate paigaldama .mo tõlkefaili selle keele jaoks."
 
 
 
 
299
 
300
  # @ polylang
301
  #: admin/view-languages.php:91
@@ -328,8 +341,7 @@ msgid "Choose the text direction for the language"
328
  msgstr "Vali keele teksti suund "
329
 
330
  # @ polylang
331
- #: admin/table-languages.php:77
332
- #: admin/view-languages.php:112
333
  msgid "Order"
334
  msgstr "Järjekord"
335
 
@@ -339,12 +351,9 @@ msgid "Position of the language in the language switcher"
339
  msgstr "Keele positsioon keele vahetajas"
340
 
341
  # @ polylang
342
- #: admin/admin-nav-menu.php:52
343
- #: admin/admin-nav-menu.php:90
344
- #: admin/admin-nav-menu.php:93
345
- #: admin/admin-nav-menu.php:124
346
- #: admin/admin-nav-menu.php:181
347
- #: include/upgrade.php:298
348
  msgid "Language switcher"
349
  msgstr "Keele vahetaja"
350
 
@@ -365,8 +374,12 @@ msgstr "Vaikimisi keel"
365
 
366
  # @ polylang
367
  #: admin/view-languages.php:180
368
- msgid "There are posts, pages, categories or tags without language set. Do you want to set them all to default language ?"
369
- msgstr "Leidub postitusi, lehti, rubriike või silte millel pole keel määratud. Kas soovite neile määrata vaikimisi keele?"
 
 
 
 
370
 
371
  # @ polylang
372
  #: admin/view-languages.php:189
@@ -375,8 +388,11 @@ msgstr "Tuvasta veebilehitseja keel"
375
 
376
  # @ polylang
377
  #: admin/view-languages.php:195
378
- msgid "When the front page is visited, set the language according to the browser preference"
379
- msgstr "Kui külastatakse esilehte, kasuta keele määramiseks veebilehitseja eelistusi"
 
 
 
380
 
381
  # @ polylang
382
  #: admin/view-languages.php:202
@@ -424,19 +440,15 @@ msgid "Activate languages and translations for custom taxonomies."
424
  msgstr "Aktiveeri keeled ja tõlked kohandatud taksonoomiate jaoks."
425
 
426
  # @ polylang
427
- #: admin/table-languages.php:54
428
- #: admin/view-translations-media.php:24
429
- #: admin/view-translations-media.php:62
430
- #: admin/view-translations-post.php:10
431
- #: admin/view-translations-post.php:39
432
- #: admin/view-translations-term.php:18
433
  #: admin/view-translations-term.php:78
434
  msgid "Edit"
435
  msgstr "Muuda"
436
 
437
  # @ polylang
438
- #: admin/table-languages.php:60
439
- #: admin/table-string.php:167
440
  msgid "Delete"
441
  msgstr "Kustuta"
442
 
@@ -466,17 +478,14 @@ msgid "String"
466
  msgstr "Sõna(d)"
467
 
468
  # @ polylang
469
- #: admin/view-translations-media.php:8
470
- #: admin/view-translations-media.php:46
471
  #: admin/view-translations-term.php:16
472
  msgid "Translation"
473
  msgstr "Tõlge"
474
 
475
  # @ polylang
476
- #: admin/view-translations-media.php:33
477
- #: admin/view-translations-media.php:70
478
- #: admin/view-translations-post.php:44
479
- #: admin/view-translations-term.php:61
480
  msgid "Add new"
481
  msgstr "Lisa uus"
482
 
@@ -530,18 +539,22 @@ msgstr "Lisab mitmekeelsuse WordPressile"
530
  #: polylang.php:159
531
  #, php-format
532
  msgid "You are using WordPress %s. Polylang requires at least WordPress %s."
533
- msgstr "Kasutusel on WordPress %s. Polylang vajab töötamiseks vähemalt WordPress versiooni %s."
 
 
534
 
535
  # @ polylang
536
  #: include/upgrade.php:76
537
- msgid "Polylang has been deactivated because you upgraded from a too old version."
 
538
  msgstr "Polylang on deaktiveeritud kuna uuendasite liiga vana versiooni pealt."
539
 
540
  # @ polylang
541
  #: include/upgrade.php:78
542
  #, php-format
543
  msgid "Please upgrade first to %s before ugrading to %s."
544
- msgstr "Palun uuendage kõigepealt versioonile %s ja alles seejärel versioonile %s."
 
545
 
546
  # @ polylang
547
  #: admin/table-string.php:108
@@ -556,80 +569,88 @@ msgstr "Vaata kõiki gruppe"
556
  # @ polylang
557
  #: admin/table-languages.php:59
558
  msgid "You are about to permanently delete this language. Are you sure?"
559
- msgstr ""
560
 
561
  # @ polylang
562
  #: admin/view-languages.php:147
563
- msgid "Use this to remove unused strings from database, for example after a plugin has been uninstalled."
 
 
564
  msgstr ""
 
 
565
 
566
  # @ polylang
567
  #: admin/view-languages.php:314
568
- msgid "The synchronization options allow to maintain exact same values (or translations in the case of taxonomies and page parent) of meta content between the translations of a post or page."
 
 
 
569
  msgstr ""
 
 
570
 
571
  # @ polylang
572
  #: admin/settings.php:75
573
  msgid "The language code contains invalid characters"
574
- msgstr ""
575
 
576
  # @ polylang
577
  #: admin/view-languages.php:208
578
  msgid "The language is set from content"
579
- msgstr ""
580
 
581
  # @ polylang
582
  #: admin/view-languages.php:211
583
  msgid "Posts, pages, categories and tags urls are not modified."
584
- msgstr ""
585
 
586
  # @ polylang
587
  #: admin/view-languages.php:217
588
  msgid "The language is set from the directory name in pretty permalinks"
589
- msgstr ""
590
 
591
  # @ polylang
592
- #: admin/view-languages.php:220
593
- #: admin/view-languages.php:229
594
- #: admin/view-languages.php:276
595
- #: admin/view-languages.php:285
596
  msgid "Example:"
597
- msgstr ""
598
 
599
  # @ polylang
600
  #: admin/view-languages.php:226
601
  msgid "The language is set from the subdomain name in pretty permalinks"
602
- msgstr ""
603
 
604
  # @ polylang
605
  #: admin/view-languages.php:235
606
  msgid "The language is set from different domains"
607
- msgstr ""
608
 
609
  # @ polylang
610
  #: admin/view-languages.php:273
611
  msgid "Remove /language/ in pretty permalinks"
612
- msgstr ""
613
 
614
  # @ polylang
615
  #: admin/view-languages.php:282
616
  msgid "Keep /language/ in pretty permalinks"
617
- msgstr ""
618
 
619
  # @ polylang
620
  #: admin/view-languages.php:297
621
- msgid "The front page url contains the language code instead of the page name or page id"
622
- msgstr ""
 
 
623
 
624
  # @ polylang
625
  #: admin/admin-filters-term.php:141
626
  #, php-format
627
  msgid "A translation does already exist for %s"
628
- msgstr ""
629
 
630
  # @ polylang
631
  #: admin/view-languages.php:302
632
  #, php-format
633
  msgid "Example: %s instead of %s"
634
- msgstr ""
635
-
3
  "Project-Id-Version: Polylang\n"
4
  "Report-Msgid-Bugs-To: \n"
5
  "POT-Creation-Date: \n"
6
+ "PO-Revision-Date: 2014-01-10 16:19+0200\n"
7
  "Last-Translator: Ahto Naris <ahto.naris@live.com>\n"
8
  "Language-Team: \n"
 
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
  "Plural-Forms: nplurals=2; plural=n != 1;\n"
13
  "X-Poedit-SourceCharset: utf-8\n"
14
+ "X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;"
15
+ "_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2\n"
16
  "X-Poedit-Basepath: ../\n"
17
  "X-Textdomain-Support: yes\n"
18
+ "X-Generator: Poedit 1.5.7\n"
19
  "X-Poedit-SearchPath-0: .\n"
20
 
21
  # @ polylang
22
  #: admin/view-about.php:3
23
  #, php-format
24
+ msgid ""
25
+ "Polylang is provided with an extensive %sdocumentation%s (in English only). "
26
+ "It includes information on how to set up your multilingual site and use it "
27
+ "on a daily basis, a FAQ, as well as a documentation for programmers to adapt "
28
+ "their plugins and themes."
29
+ msgstr ""
30
+ "Polylang on varustatud ulatusliku %sdokumentatsiooniga%s (ainult inglise "
31
+ "keeles). See sisaldab teavet kuidas luua ja kasutada igapäevaselt oma "
32
+ "mitmekeelset kodulehte, KKK-d ning ka dokumentatsiooni programmeerijatele "
33
+ "kuidas kohandada oma pluginad ja teemad."
34
 
35
  # @ polylang
36
  #: admin/view-about.php:9
37
  #, php-format
38
+ msgid ""
39
+ "You will also find useful information in the %ssupport forum%s. However "
40
+ "don't forget to make a search before posting a new topic."
41
+ msgstr ""
42
+ "Kasulikku informatsiooni on võimalik ka leida %sfoorumist%s. Paljud teemad "
43
+ "on enne foorumis juba läbi arutatud, seega kasuta enne uue teema postitamist "
44
+ "otsingut."
45
 
46
  # @ polylang
47
  #: admin/view-about.php:16
48
  #, php-format
49
+ msgid ""
50
+ "Polylang is free of charge and is released under the same license as "
51
+ "WordPress, the %sGPL%s."
52
+ msgstr ""
53
+ "Polylang on tasuta ja avaldatud sama litsentsi alusel nagu WordPress - %sGPL"
54
+ "%s."
55
 
56
  # @ polylang
57
  #: admin/view-about.php:22
61
 
62
  # @ polylang
63
  #: admin/view-about.php:27
64
+ msgid ""
65
+ "Finally if you like this plugin or if it helps your business, donations to "
66
+ "the author are greatly appreciated."
67
+ msgstr ""
68
+ "Kui see plugin meeldib teile või aitab teie äri kaaluge autorile annetuse "
69
+ "tegemist."
70
 
71
  # @ polylang
72
+ #: admin/admin-filters-post.php:81 admin/admin.php:76 admin/settings.php:42
73
+ #: admin/settings.php:57 include/model.php:501
 
 
 
74
  msgid "Languages"
75
  msgstr "Keeled"
76
 
110
  msgstr "Näita kõiki keeli"
111
 
112
  # @ polylang
113
+ #: admin/admin-filters-columns.php:126 admin/admin-filters-columns.php:218
 
114
  msgid "Add new translation"
115
  msgstr "Lisa uus tõlge"
116
 
117
  # @ polylang
118
+ #: admin/admin-filters-columns.php:160 admin/admin-filters-media.php:57
119
+ #: admin/admin-filters-post.php:114 admin/admin-filters-term.php:73
120
+ #: admin/admin-filters-term.php:110 admin/view-translations-media.php:7
121
+ #: admin/view-translations-media.php:45 admin/view-translations-post.php:8
122
+ #: admin/view-translations-term.php:15 include/model.php:502
 
 
 
 
 
123
  msgid "Language"
124
  msgstr "Keel"
125
 
126
  # @ polylang
127
+ #: admin/admin-filters-media.php:72 admin/admin-filters-media.php:111
128
+ #: admin/table-string.php:111 admin/view-translations-media.php:42
129
+ #: admin/view-translations-term.php:6 admin/view-translations-term.php:11
 
 
 
130
  msgid "Translations"
131
  msgstr "Tõlked"
132
 
133
  # @ polylang
134
+ #: admin/admin-filters-term.php:75 admin/admin-filters-term.php:112
 
135
  msgid "Sets the language"
136
  msgstr "Määrab keele"
137
 
141
  msgstr "Moodul kuvatakse:"
142
 
143
  # @ polylang
144
+ #: admin/admin-filters.php:62 include/model.php:503
 
145
  msgid "All languages"
146
  msgstr "Kõik keeled"
147
 
156
  msgstr "Wordpressi vaikimisi väärtus"
157
 
158
  # @ polylang
159
+ #: admin/admin.php:116 admin/settings.php:62
 
160
  msgid "Settings"
161
  msgstr "Sätted"
162
 
197
 
198
  # @ polylang
199
  #: admin/settings.php:78
200
+ msgid ""
201
+ "The language was created, but the WordPress language file was not "
202
+ "downloaded. Please install it manually."
203
+ msgstr ""
204
+ "Keel loodi, aga WordPressi keelefaili allalaadimine ebaõnnestus. Palun "
205
+ "paigalda see käsitsi."
206
 
207
  # @ polylang
208
  #: admin/settings.php:308
270
  msgstr "Muuda keelt"
271
 
272
  # @ polylang
273
+ #: admin/view-languages.php:42 admin/view-languages.php:117
 
274
  msgid "Add new language"
275
  msgstr "Lisa uus keel"
276
 
282
  # @ polylang
283
  #: admin/view-languages.php:72
284
  msgid "You can choose a language in the list or directly edit it below."
285
+ msgstr ""
286
+ "Saate valida keele loendist või vahetult redigeerida allpool olevates "
287
+ "lahtrites."
288
 
289
  # @ polylang
290
+ #: admin/table-languages.php:74 admin/view-languages.php:76
 
291
  msgid "Full name"
292
  msgstr "Täisnimi"
293
 
297
  msgstr "Täisnimi kuvatakse sinu lehel (näiteks: Eesti)."
298
 
299
  # @ polylang
300
+ #: admin/table-languages.php:75 admin/view-languages.php:82
 
301
  msgid "Locale"
302
  msgstr "Locale"
303
 
304
  # @ polylang
305
  #: admin/view-languages.php:87
306
+ msgid ""
307
+ "Wordpress Locale for the language (for example: en_US). You will need to "
308
+ "install the .mo file for this language."
309
+ msgstr ""
310
+ "WordPress Locale keelele (näiteks: en_US). Peate paigaldama .mo tõlkefaili "
311
+ "selle keele jaoks."
312
 
313
  # @ polylang
314
  #: admin/view-languages.php:91
341
  msgstr "Vali keele teksti suund "
342
 
343
  # @ polylang
344
+ #: admin/table-languages.php:77 admin/view-languages.php:112
 
345
  msgid "Order"
346
  msgstr "Järjekord"
347
 
351
  msgstr "Keele positsioon keele vahetajas"
352
 
353
  # @ polylang
354
+ #: admin/admin-nav-menu.php:52 admin/admin-nav-menu.php:90
355
+ #: admin/admin-nav-menu.php:93 admin/admin-nav-menu.php:124
356
+ #: admin/admin-nav-menu.php:181 include/upgrade.php:298
 
 
 
357
  msgid "Language switcher"
358
  msgstr "Keele vahetaja"
359
 
374
 
375
  # @ polylang
376
  #: admin/view-languages.php:180
377
+ msgid ""
378
+ "There are posts, pages, categories or tags without language set. Do you want "
379
+ "to set them all to default language ?"
380
+ msgstr ""
381
+ "Leidub postitusi, lehti, rubriike või silte millel pole keel määratud. Kas "
382
+ "soovite neile määrata vaikimisi keele?"
383
 
384
  # @ polylang
385
  #: admin/view-languages.php:189
388
 
389
  # @ polylang
390
  #: admin/view-languages.php:195
391
+ msgid ""
392
+ "When the front page is visited, set the language according to the browser "
393
+ "preference"
394
+ msgstr ""
395
+ "Kui külastatakse esilehte, kasuta keele määramiseks veebilehitseja eelistusi"
396
 
397
  # @ polylang
398
  #: admin/view-languages.php:202
440
  msgstr "Aktiveeri keeled ja tõlked kohandatud taksonoomiate jaoks."
441
 
442
  # @ polylang
443
+ #: admin/table-languages.php:54 admin/view-translations-media.php:24
444
+ #: admin/view-translations-media.php:62 admin/view-translations-post.php:10
445
+ #: admin/view-translations-post.php:39 admin/view-translations-term.php:18
 
 
 
446
  #: admin/view-translations-term.php:78
447
  msgid "Edit"
448
  msgstr "Muuda"
449
 
450
  # @ polylang
451
+ #: admin/table-languages.php:60 admin/table-string.php:167
 
452
  msgid "Delete"
453
  msgstr "Kustuta"
454
 
478
  msgstr "Sõna(d)"
479
 
480
  # @ polylang
481
+ #: admin/view-translations-media.php:8 admin/view-translations-media.php:46
 
482
  #: admin/view-translations-term.php:16
483
  msgid "Translation"
484
  msgstr "Tõlge"
485
 
486
  # @ polylang
487
+ #: admin/view-translations-media.php:33 admin/view-translations-media.php:70
488
+ #: admin/view-translations-post.php:44 admin/view-translations-term.php:61
 
 
489
  msgid "Add new"
490
  msgstr "Lisa uus"
491
 
539
  #: polylang.php:159
540
  #, php-format
541
  msgid "You are using WordPress %s. Polylang requires at least WordPress %s."
542
+ msgstr ""
543
+ "Kasutusel on WordPress %s. Polylang vajab töötamiseks vähemalt WordPress "
544
+ "versiooni %s."
545
 
546
  # @ polylang
547
  #: include/upgrade.php:76
548
+ msgid ""
549
+ "Polylang has been deactivated because you upgraded from a too old version."
550
  msgstr "Polylang on deaktiveeritud kuna uuendasite liiga vana versiooni pealt."
551
 
552
  # @ polylang
553
  #: include/upgrade.php:78
554
  #, php-format
555
  msgid "Please upgrade first to %s before ugrading to %s."
556
+ msgstr ""
557
+ "Palun uuendage kõigepealt versioonile %s ja alles seejärel versioonile %s."
558
 
559
  # @ polylang
560
  #: admin/table-string.php:108
569
  # @ polylang
570
  #: admin/table-languages.php:59
571
  msgid "You are about to permanently delete this language. Are you sure?"
572
+ msgstr "Oled sa kindel, et tahad selle keele jäädavalt kustuda?"
573
 
574
  # @ polylang
575
  #: admin/view-languages.php:147
576
+ msgid ""
577
+ "Use this to remove unused strings from database, for example after a plugin "
578
+ "has been uninstalled."
579
  msgstr ""
580
+ "Kasutage seda kasutamata sõnade eemaldamiseks andmebaasist, näiteks pärast "
581
+ "plugina eemaldamist."
582
 
583
  # @ polylang
584
  #: admin/view-languages.php:314
585
+ msgid ""
586
+ "The synchronization options allow to maintain exact same values (or "
587
+ "translations in the case of taxonomies and page parent) of meta content "
588
+ "between the translations of a post or page."
589
  msgstr ""
590
+ "Sünkroniseerimise võimalused lubavad säilitada meta seosed tõlgitud "
591
+ "postituste ja lehtede vahel. "
592
 
593
  # @ polylang
594
  #: admin/settings.php:75
595
  msgid "The language code contains invalid characters"
596
+ msgstr "Keelekood sisaldab sobimatuid tähemärke"
597
 
598
  # @ polylang
599
  #: admin/view-languages.php:208
600
  msgid "The language is set from content"
601
+ msgstr "Keel on määratud sisust"
602
 
603
  # @ polylang
604
  #: admin/view-languages.php:211
605
  msgid "Posts, pages, categories and tags urls are not modified."
606
+ msgstr "Postituste, lehtede, rubriikide ja siltide aadresse (URLe) ei muudeta."
607
 
608
  # @ polylang
609
  #: admin/view-languages.php:217
610
  msgid "The language is set from the directory name in pretty permalinks"
611
+ msgstr "Keel on määratud kataloogidega"
612
 
613
  # @ polylang
614
+ #: admin/view-languages.php:220 admin/view-languages.php:229
615
+ #: admin/view-languages.php:276 admin/view-languages.php:285
 
 
616
  msgid "Example:"
617
+ msgstr "Näide:"
618
 
619
  # @ polylang
620
  #: admin/view-languages.php:226
621
  msgid "The language is set from the subdomain name in pretty permalinks"
622
+ msgstr "Keel on määratud alamdomeenidega"
623
 
624
  # @ polylang
625
  #: admin/view-languages.php:235
626
  msgid "The language is set from different domains"
627
+ msgstr "Keel on määratud domeenidega"
628
 
629
  # @ polylang
630
  #: admin/view-languages.php:273
631
  msgid "Remove /language/ in pretty permalinks"
632
+ msgstr "Eemalda /language/ ilusatest püsiviidetest"
633
 
634
  # @ polylang
635
  #: admin/view-languages.php:282
636
  msgid "Keep /language/ in pretty permalinks"
637
+ msgstr "Säilita /language/ ilusates püsiviidetes"
638
 
639
  # @ polylang
640
  #: admin/view-languages.php:297
641
+ msgid ""
642
+ "The front page url contains the language code instead of the page name or "
643
+ "page id"
644
+ msgstr "Esilehe aadress (URL) sisaldab lehe nime või lehe id asemel keelekoodi"
645
 
646
  # @ polylang
647
  #: admin/admin-filters-term.php:141
648
  #, php-format
649
  msgid "A translation does already exist for %s"
650
+ msgstr "Tõlge juba eksisteerib sõna(de)le: %s"
651
 
652
  # @ polylang
653
  #: admin/view-languages.php:302
654
  #, php-format
655
  msgid "Example: %s instead of %s"
656
+ msgstr "Näide: %s asendab %s"
 
languages/polylang-zh_TW.mo ADDED
Binary file
languages/polylang-zh_TW.po ADDED
@@ -0,0 +1,687 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Polylang v1.4\n"
4
+ "Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: \n"
6
+ "PO-Revision-Date: 2014-01-08 20:26+0800\n"
7
+ "Last-Translator: 張香腸 <s9011514@gmail.com>\n"
8
+ "Language-Team: 香腸炒魷魚 <service@sofree.cc>\n"
9
+ "Language: zh_TW\n"
10
+ "MIME-Version: 1.0\n"
11
+ "Content-Type: text/plain; charset=UTF-8\n"
12
+ "Content-Transfer-Encoding: 8bit\n"
13
+ "Plural-Forms: nplurals=2; plural=n != 1;\n"
14
+ "X-Poedit-SourceCharset: UTF-8\n"
15
+ "X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;"
16
+ "_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2\n"
17
+ "X-Poedit-Basepath: ../\n"
18
+ "X-Textdomain-Support: yes\n"
19
+ "X-Generator: Poedit 1.5.7\n"
20
+ "X-Poedit-SearchPath-0: .\n"
21
+
22
+ # @ polylang
23
+ #: admin/view-about.php:3
24
+ #, php-format
25
+ msgid ""
26
+ "Polylang is provided with an extensive %sdocumentation%s (in English only). "
27
+ "It includes information on how to set up your multilingual site and use it "
28
+ "on a daily basis, a FAQ, as well as a documentation for programmers to adapt "
29
+ "their plugins and themes."
30
+ msgstr ""
31
+ "Polylang 提供一個完整的 %s說明文件%s (僅提供英文)。這包含了如何設定多語言網站"
32
+ "並日常使用,常見問題說明,以及幫助程式設計師可快速套用到他們的外掛或是佈景主"
33
+ "題。"
34
+
35
+ # @ polylang
36
+ #: admin/view-about.php:9
37
+ #, php-format
38
+ msgid ""
39
+ "You will also find useful information in the %ssupport forum%s. However "
40
+ "don't forget to make a search before posting a new topic."
41
+ msgstr ""
42
+ "你也可以在%s支援論壇%s獲取更多有用的資訊。但別忘記,發新問題詢問前,要先搜尋"
43
+ "與爬文。"
44
+
45
+ # @ polylang
46
+ #: admin/view-about.php:16
47
+ #, php-format
48
+ msgid ""
49
+ "Polylang is free of charge and is released under the same license as "
50
+ "WordPress, the %sGPL%s."
51
+ msgstr "Polylang 是免費的,與 WordPress 一樣是基於 %sGPL%s 釋出。"
52
+
53
+ # @ polylang
54
+ #: admin/view-about.php:22
55
+ #, php-format
56
+ msgid "If you wonder how you can help the project, just %sread this%s."
57
+ msgstr "如果你想知道如何協助這個專案,請%s閱讀這篇%s。"
58
+
59
+ # @ polylang
60
+ #: admin/view-about.php:27
61
+ msgid ""
62
+ "Finally if you like this plugin or if it helps your business, donations to "
63
+ "the author are greatly appreciated."
64
+ msgstr ""
65
+ "最後,如果你喜歡這個外掛或是它有助於你的業務,不妨贊助作者。<br /><br /> "
66
+ "Polylang 正體中文語系由 <a href=\"http://sofree.cc\" target=\"_blank\">香腸"
67
+ "炒魷魚</a> 與 <a href=\"http://achang.tw\" target=\"_blank\">阿腸網頁設計工作"
68
+ "室</a> 翻譯提供。"
69
+
70
+ # @ polylang
71
+ #: admin/admin-filters-post.php:81 admin/admin.php:76 admin/settings.php:42
72
+ #: admin/settings.php:57 include/model.php:501
73
+ msgid "Languages"
74
+ msgstr "語言"
75
+
76
+ # @ polylang
77
+ #: include/switcher.php:22
78
+ msgid "Displays language names"
79
+ msgstr "顯示語言名稱"
80
+
81
+ # @ polylang
82
+ #: include/switcher.php:23
83
+ msgid "Displays flags"
84
+ msgstr "顯示旗幟"
85
+
86
+ # @ polylang
87
+ #: include/switcher.php:24
88
+ msgid "Forces link to front page"
89
+ msgstr "強制鏈結到首頁"
90
+
91
+ # @ polylang
92
+ #: include/switcher.php:25
93
+ msgid "Hides the current language"
94
+ msgstr "隱藏當前語言"
95
+
96
+ # @ polylang
97
+ #: include/switcher.php:29
98
+ msgid "Displays as dropdown"
99
+ msgstr "顯示為下拉式選單"
100
+
101
+ # @ polylang
102
+ #: admin/admin.php:212
103
+ msgid "Filters content by language"
104
+ msgstr "透過語言過濾內容"
105
+
106
+ # @ polylang
107
+ #: admin/admin.php:199
108
+ msgid "Show all languages"
109
+ msgstr "顯示所有語言"
110
+
111
+ # @ polylang
112
+ #: admin/admin-filters-columns.php:126 admin/admin-filters-columns.php:218
113
+ msgid "Add new translation"
114
+ msgstr "新增翻譯"
115
+
116
+ # @ polylang
117
+ #: admin/admin-filters-columns.php:160 admin/admin-filters-media.php:57
118
+ #: admin/admin-filters-post.php:114 admin/admin-filters-term.php:73
119
+ #: admin/admin-filters-term.php:110 admin/view-translations-media.php:7
120
+ #: admin/view-translations-media.php:45 admin/view-translations-post.php:8
121
+ #: admin/view-translations-term.php:15 include/model.php:502
122
+ msgid "Language"
123
+ msgstr "語言"
124
+
125
+ # @ polylang
126
+ #: admin/admin-filters-media.php:72 admin/admin-filters-media.php:111
127
+ #: admin/table-string.php:111 admin/view-translations-media.php:42
128
+ #: admin/view-translations-term.php:6 admin/view-translations-term.php:11
129
+ msgid "Translations"
130
+ msgstr "翻譯"
131
+
132
+ # @ polylang
133
+ #: admin/admin-filters-term.php:75 admin/admin-filters-term.php:112
134
+ msgid "Sets the language"
135
+ msgstr "設定語言"
136
+
137
+ # @ polylang
138
+ #: admin/admin-filters.php:59
139
+ msgid "The widget is displayed for:"
140
+ msgstr "此小工具顯示:"
141
+
142
+ # @ polylang
143
+ #: admin/admin-filters.php:62 include/model.php:503
144
+ msgid "All languages"
145
+ msgstr "所有語言"
146
+
147
+ # @ polylang
148
+ #: admin/admin-filters.php:123
149
+ msgid "Admin language"
150
+ msgstr "管理語言"
151
+
152
+ # @ polylang
153
+ #: admin/admin-filters.php:126
154
+ msgid "Wordpress default"
155
+ msgstr "WordPress 預設"
156
+
157
+ # @ polylang
158
+ #: admin/admin.php:116 admin/settings.php:62
159
+ msgid "Settings"
160
+ msgstr "設定"
161
+
162
+ # @ polylang
163
+ #: admin/admin-filters.php:156
164
+ msgid "Upgrading language files&#8230;"
165
+ msgstr "升級語言檔案 &#8230;"
166
+
167
+ # @ polylang
168
+ #: admin/settings.php:38
169
+ msgid "About Polylang"
170
+ msgstr "關於 Polylang"
171
+
172
+ # @ polylang
173
+ #: admin/settings.php:46
174
+ msgid "Strings translations"
175
+ msgstr "字串翻譯"
176
+
177
+ # @ polylang
178
+ #: admin/settings.php:61
179
+ msgid "Strings translation"
180
+ msgstr "字串翻譯"
181
+
182
+ # @ polylang
183
+ #: admin/settings.php:74
184
+ msgid "Enter a valid WordPress locale"
185
+ msgstr "輸入一個有效的 WordPress 語言環境"
186
+
187
+ # @ polylang
188
+ #: admin/settings.php:76
189
+ msgid "The language code must be unique"
190
+ msgstr "語言代碼必須是獨一無二"
191
+
192
+ # @ polylang
193
+ #: admin/settings.php:77
194
+ msgid "The language must have a name"
195
+ msgstr "這個語言必須有一個名字"
196
+
197
+ # @ polylang
198
+ #: admin/settings.php:78
199
+ msgid ""
200
+ "The language was created, but the WordPress language file was not "
201
+ "downloaded. Please install it manually."
202
+ msgstr "語言已經被建立,但是WordPress語言包並沒有下載到,請手動安裝它。"
203
+
204
+ # @ polylang
205
+ #: admin/settings.php:308
206
+ msgid "Widget title"
207
+ msgstr "小工具標題"
208
+
209
+ # @ polylang
210
+ #: admin/settings.php:326
211
+ msgid "Taxonomies"
212
+ msgstr "自訂分類"
213
+
214
+ # @ polylang
215
+ #: admin/settings.php:327
216
+ msgid "Custom fields"
217
+ msgstr "自訂欄位"
218
+
219
+ # @ polylang
220
+ #: admin/settings.php:328
221
+ msgid "Comment status"
222
+ msgstr "迴響狀態"
223
+
224
+ # @ polylang
225
+ #: admin/settings.php:329
226
+ msgid "Ping status"
227
+ msgstr "通知狀態"
228
+
229
+ # @ polylang
230
+ #: admin/settings.php:330
231
+ msgid "Sticky posts"
232
+ msgstr "置頂文章"
233
+
234
+ # @ polylang
235
+ #: admin/settings.php:331
236
+ msgid "Published date"
237
+ msgstr "發佈日期"
238
+
239
+ # @ polylang
240
+ #: admin/settings.php:332
241
+ msgid "Post format"
242
+ msgstr "文章格式"
243
+
244
+ # @ polylang
245
+ #: admin/settings.php:333
246
+ msgid "Page parent"
247
+ msgstr "分頁上層"
248
+
249
+ # @ polylang
250
+ #: admin/settings.php:334
251
+ msgid "Page template"
252
+ msgstr "分頁模板"
253
+
254
+ # @ polylang
255
+ #: admin/settings.php:335
256
+ msgid "Page order"
257
+ msgstr "分頁順序"
258
+
259
+ # @ polylang
260
+ #: admin/settings.php:336
261
+ msgid "Featured image"
262
+ msgstr "特色圖片"
263
+
264
+ # @ polylang
265
+ #: admin/view-languages.php:42
266
+ msgid "Edit language"
267
+ msgstr "編輯語言"
268
+
269
+ # @ polylang
270
+ #: admin/view-languages.php:42 admin/view-languages.php:117
271
+ msgid "Add new language"
272
+ msgstr "新增語言"
273
+
274
+ # @ polylang
275
+ #: admin/view-languages.php:58
276
+ msgid "Choose a language"
277
+ msgstr "選擇一個語言"
278
+
279
+ # @ polylang
280
+ #: admin/view-languages.php:72
281
+ msgid "You can choose a language in the list or directly edit it below."
282
+ msgstr "你可以在列表內選擇一個語言或直接在這邊編輯它。"
283
+
284
+ # @ polylang
285
+ #: admin/table-languages.php:74 admin/view-languages.php:76
286
+ msgid "Full name"
287
+ msgstr "全名"
288
+
289
+ # @ polylang
290
+ #: admin/view-languages.php:78
291
+ msgid "The name is how it is displayed on your site (for example: English)."
292
+ msgstr "這個名字是顯示於網站上(範例: English)"
293
+
294
+ # @ polylang
295
+ #: admin/table-languages.php:75 admin/view-languages.php:82
296
+ msgid "Locale"
297
+ msgstr "語言環境"
298
+
299
+ # @ polylang
300
+ #: admin/view-languages.php:87
301
+ msgid ""
302
+ "Wordpress Locale for the language (for example: en_US). You will need to "
303
+ "install the .mo file for this language."
304
+ msgstr "WordPress 語言環境設定(範例:en_US)。你必須安裝對應此語言的 .mo 檔案。"
305
+
306
+ # @ polylang
307
+ #: admin/view-languages.php:91
308
+ msgid "Language code"
309
+ msgstr "語言代碼"
310
+
311
+ # @ polylang
312
+ #: admin/view-languages.php:93
313
+ msgid "2-letters ISO 639-1 language code (for example: en)"
314
+ msgstr "依據 ISO 639-1 規範的 2 個字母之語言代碼 (範例: en )"
315
+
316
+ # @ polylang
317
+ #: admin/view-languages.php:97
318
+ msgid "Text direction"
319
+ msgstr "文字方向"
320
+
321
+ # @ polylang
322
+ #: admin/view-languages.php:101
323
+ msgid "left to right"
324
+ msgstr "左到右"
325
+
326
+ # @ polylang
327
+ #: admin/view-languages.php:106
328
+ msgid "right to left"
329
+ msgstr "右到左"
330
+
331
+ # @ polylang
332
+ #: admin/view-languages.php:108
333
+ msgid "Choose the text direction for the language"
334
+ msgstr "選擇此語言的文字方向"
335
+
336
+ # @ polylang
337
+ #: admin/table-languages.php:77 admin/view-languages.php:112
338
+ msgid "Order"
339
+ msgstr "順序"
340
+
341
+ # @ polylang
342
+ #: admin/view-languages.php:114
343
+ msgid "Position of the language in the language switcher"
344
+ msgstr "此語言在語言切換選項中的位置"
345
+
346
+ # @ polylang
347
+ #: admin/admin-nav-menu.php:52 admin/admin-nav-menu.php:90
348
+ #: admin/admin-nav-menu.php:93 admin/admin-nav-menu.php:124
349
+ #: admin/admin-nav-menu.php:181 include/upgrade.php:298
350
+ msgid "Language switcher"
351
+ msgstr "語言切換"
352
+
353
+ # @ polylang
354
+ #: admin/view-languages.php:143
355
+ msgid "Search translations"
356
+ msgstr "搜尋翻譯"
357
+
358
+ # @ polylang
359
+ #: admin/view-languages.php:146
360
+ msgid "Clean strings translation database"
361
+ msgstr "清除資料庫中翻譯的字串"
362
+
363
+ # @ polylang
364
+ #: admin/view-languages.php:165
365
+ msgid "Default language"
366
+ msgstr "預設語言"
367
+
368
+ # @ polylang
369
+ #: admin/view-languages.php:180
370
+ msgid ""
371
+ "There are posts, pages, categories or tags without language set. Do you want "
372
+ "to set them all to default language ?"
373
+ msgstr "有文章、頁面、分類或標籤尚未設置語言。你要將要全部設定為預設語言嗎?"
374
+
375
+ # @ polylang
376
+ #: admin/view-languages.php:189
377
+ msgid "Detect browser language"
378
+ msgstr "偵測瀏覽器語言"
379
+
380
+ # @ polylang
381
+ #: admin/view-languages.php:195
382
+ msgid ""
383
+ "When the front page is visited, set the language according to the browser "
384
+ "preference"
385
+ msgstr "當首頁被訪問時,根據瀏覽器的偏好設置語言"
386
+
387
+ # @ polylang
388
+ #: admin/view-languages.php:202
389
+ msgid "URL modifications"
390
+ msgstr "URL 網址改寫"
391
+
392
+ # @ polylang
393
+ #: admin/view-languages.php:259
394
+ msgid "Hide URL language information for default language"
395
+ msgstr "隱藏預設語言的 URL 訊息"
396
+
397
+ # @ polylang
398
+ #: admin/view-languages.php:312
399
+ msgid "Media"
400
+ msgstr "媒體庫"
401
+
402
+ # @ polylang
403
+ #: admin/view-languages.php:318
404
+ msgid "Activate languages and translations for media"
405
+ msgstr "為媒體庫啟用語言與翻譯功能"
406
+
407
+ # @ polylang
408
+ #: admin/view-languages.php:365
409
+ msgid "Synchronization"
410
+ msgstr "同步"
411
+
412
+ # @ polylang
413
+ #: admin/view-languages.php:326
414
+ msgid "Custom post types"
415
+ msgstr "自訂文章格式"
416
+
417
+ # @ polylang
418
+ #: admin/view-languages.php:339
419
+ msgid "Activate languages and translations for custom post types."
420
+ msgstr "為自訂文章格式啟用語言與翻譯。"
421
+
422
+ # @ polylang
423
+ #: admin/view-languages.php:346
424
+ msgid "Custom taxonomies"
425
+ msgstr "自定義分類"
426
+
427
+ # @ polylang
428
+ #: admin/view-languages.php:359
429
+ msgid "Activate languages and translations for custom taxonomies."
430
+ msgstr "為自定義分類啟用語言與翻譯功能。"
431
+
432
+ # @ polylang
433
+ #: admin/table-languages.php:54 admin/view-translations-media.php:24
434
+ #: admin/view-translations-media.php:62 admin/view-translations-post.php:10
435
+ #: admin/view-translations-post.php:39 admin/view-translations-term.php:18
436
+ #: admin/view-translations-term.php:78
437
+ msgid "Edit"
438
+ msgstr "編輯"
439
+
440
+ # @ polylang
441
+ #: admin/table-languages.php:60 admin/table-string.php:167
442
+ msgid "Delete"
443
+ msgstr "刪除"
444
+
445
+ # @ polylang
446
+ #: admin/table-languages.php:76
447
+ msgid "Code"
448
+ msgstr "代碼"
449
+
450
+ # @ polylang
451
+ #: admin/table-languages.php:78
452
+ msgid "Flag"
453
+ msgstr "旗幟"
454
+
455
+ # @ polylang
456
+ #: admin/table-languages.php:79
457
+ msgid "Posts"
458
+ msgstr "文章"
459
+
460
+ # @ polylang
461
+ #: admin/table-string.php:109
462
+ msgid "Name"
463
+ msgstr "名稱"
464
+
465
+ # @ polylang
466
+ #: admin/table-string.php:110
467
+ msgid "String"
468
+ msgstr "字串"
469
+
470
+ # @ polylang
471
+ #: admin/view-translations-media.php:8 admin/view-translations-media.php:46
472
+ #: admin/view-translations-term.php:16
473
+ msgid "Translation"
474
+ msgstr "翻譯"
475
+
476
+ # @ polylang
477
+ #: admin/view-translations-media.php:33 admin/view-translations-media.php:70
478
+ #: admin/view-translations-post.php:44 admin/view-translations-term.php:61
479
+ msgid "Add new"
480
+ msgstr "新增"
481
+
482
+ # @ polylang
483
+ #: admin/view-translations-post.php:5
484
+ msgid "ID of pages in other languages:"
485
+ msgstr "其他語言的頁面ID:"
486
+
487
+ # @ polylang
488
+ #: admin/view-translations-post.php:5
489
+ msgid "ID of posts in other languages:"
490
+ msgstr "其他語言的文章ID:"
491
+
492
+ # @ polylang
493
+ #: admin/view-translations-post.php:9
494
+ msgid "Page ID"
495
+ msgstr "頁面ID"
496
+
497
+ # @ polylang
498
+ #: admin/view-translations-post.php:9
499
+ msgid "Post ID"
500
+ msgstr "文章ID"
501
+
502
+ # @ polylang
503
+ #: admin/view-translations-term.php:48
504
+ msgid "No untranslated term"
505
+ msgstr "沒有未翻譯自定義標籤"
506
+
507
+ # @ polylang
508
+ #: include/widget-languages.php:16
509
+ msgid "Language Switcher"
510
+ msgstr "語言切換"
511
+
512
+ # @ polylang
513
+ #: include/widget-languages.php:16
514
+ msgid "Displays a language switcher"
515
+ msgstr "顯示語言切換工具"
516
+
517
+ # @ polylang
518
+ #: include/widget-languages.php:100
519
+ msgid "Title:"
520
+ msgstr "標題:"
521
+
522
+ # @ polylang
523
+ #. translators: plugin header field 'Description'
524
+ #: polylang.php:0
525
+ msgid "Adds multilingual capability to WordPress"
526
+ msgstr "讓WordPress增加多語言功能"
527
+
528
+ # @ polylang
529
+ #: polylang.php:159
530
+ #, php-format
531
+ msgid "You are using WordPress %s. Polylang requires at least WordPress %s."
532
+ msgstr "你正在使用 WordPress %s。 Polylang 最低系統需求 WordPress %s。"
533
+
534
+ # @ polylang
535
+ #: include/upgrade.php:76
536
+ msgid ""
537
+ "Polylang has been deactivated because you upgraded from a too old version."
538
+ msgstr "Polylang 已經停用,因為你從太舊的版本升級。"
539
+
540
+ # @ polylang
541
+ #: include/upgrade.php:78
542
+ #, php-format
543
+ msgid "Please upgrade first to %s before ugrading to %s."
544
+ msgstr "在升級到 %s 之前請先升級到 %s。"
545
+
546
+ # @ polylang
547
+ #: admin/table-string.php:108
548
+ msgid "Group"
549
+ msgstr "群組"
550
+
551
+ # @ polylang
552
+ #: admin/table-string.php:186
553
+ msgid "View all groups"
554
+ msgstr "檢視全部群組"
555
+
556
+ # @ polylang
557
+ #: admin/table-languages.php:59
558
+ msgid "You are about to permanently delete this language. Are you sure?"
559
+ msgstr "你將永遠刪除此語言。確定刪除?"
560
+
561
+ # @ polylang
562
+ #: admin/view-languages.php:147
563
+ msgid ""
564
+ "Use this to remove unused strings from database, for example after a plugin "
565
+ "has been uninstalled."
566
+ msgstr "使用它從資料庫中刪除未使用的字串。例如在外掛被移除後。"
567
+
568
+ # @ polylang
569
+ #: admin/view-languages.php:314
570
+ msgid ""
571
+ "The synchronization options allow to maintain exact same values (or "
572
+ "translations in the case of taxonomies and page parent) of meta content "
573
+ "between the translations of a post or page."
574
+ msgstr ""
575
+ "同步的設定允許在一篇文章或是頁面(或自定義分類、上層頁面)的翻譯保存相同內容的"
576
+ "值。<br />[ The synchronization options allow to maintain exact same values "
577
+ "(or translations in the case of taxonomies and page parent) of meta content "
578
+ "between the translations of a post or page.]"
579
+
580
+ # @ polylang
581
+ #: admin/settings.php:75
582
+ msgid "The language code contains invalid characters"
583
+ msgstr "語言代碼中帶有無效的字元"
584
+
585
+ # @ polylang
586
+ #: admin/view-languages.php:208
587
+ msgid "The language is set from content"
588
+ msgstr "只針對內容作多語言設定。(網址不變更)"
589
+
590
+ # @ polylang
591
+ #: admin/view-languages.php:211
592
+ msgid "Posts, pages, categories and tags urls are not modified."
593
+ msgstr "文章、頁面、分類與標籤的網址並不會被改寫。"
594
+
595
+ # @ polylang
596
+ #: admin/view-languages.php:217
597
+ msgid "The language is set from the directory name in pretty permalinks"
598
+ msgstr "語言設置是在漂亮的固定網址中加入目錄名稱"
599
+
600
+ # @ polylang
601
+ #: admin/view-languages.php:220 admin/view-languages.php:229
602
+ #: admin/view-languages.php:276 admin/view-languages.php:285
603
+ msgid "Example:"
604
+ msgstr "範例:"
605
+
606
+ # @ polylang
607
+ #: admin/view-languages.php:226
608
+ msgid "The language is set from the subdomain name in pretty permalinks"
609
+ msgstr "語言設置是透過子網域來設定漂亮的固定網址。"
610
+
611
+ # @ polylang
612
+ #: admin/view-languages.php:235
613
+ msgid "The language is set from different domains"
614
+ msgstr "透過不同的網域名稱來設置不同的語言。"
615
+
616
+ # @ polylang
617
+ #: admin/view-languages.php:273
618
+ msgid "Remove /language/ in pretty permalinks"
619
+ msgstr "在漂亮的固定網址中移除「/language/」"
620
+
621
+ # @ polylang
622
+ #: admin/view-languages.php:282
623
+ msgid "Keep /language/ in pretty permalinks"
624
+ msgstr "在漂亮的固定網址中保留「/language/」"
625
+
626
+ # @ polylang
627
+ #: admin/view-languages.php:297
628
+ msgid ""
629
+ "The front page url contains the language code instead of the page name or "
630
+ "page id"
631
+ msgstr "首頁URL包含語言代碼而不是頁面名稱或是頁面ID"
632
+
633
+ # @ polylang
634
+ #: admin/admin-filters-term.php:141
635
+ #, php-format
636
+ msgid "A translation does already exist for %s"
637
+ msgstr "有個翻譯檔案已經以 %s 存在"
638
+
639
+ # @ polylang
640
+ #: admin/view-languages.php:302
641
+ #, php-format
642
+ msgid "Example: %s instead of %s"
643
+ msgstr "範例: %s 而不是 %s"
644
+
645
+ #~ msgid "&mdash; No Change &mdash;"
646
+ #~ msgstr "&mdash; 沒有任何變更 &mdash;"
647
+
648
+ #~ msgid "None"
649
+ #~ msgstr "無"
650
+
651
+ #~ msgid "Uncategorized"
652
+ #~ msgstr "未分類"
653
+
654
+ #~ msgid "Site Title"
655
+ #~ msgstr "網誌標題"
656
+
657
+ #~ msgid "Tagline"
658
+ #~ msgstr "網誌描述"
659
+
660
+ #~ msgid "Date Format"
661
+ #~ msgstr "日期格式"
662
+
663
+ #~ msgid "Time Format"
664
+ #~ msgstr "時間格式"
665
+
666
+ #~ msgid "Filter"
667
+ #~ msgstr "篩選"
668
+
669
+ #~ msgid "Update"
670
+ #~ msgstr "更新"
671
+
672
+ #~ msgid "Search"
673
+ #~ msgstr "搜尋"
674
+
675
+ #~ msgid ""
676
+ #~ "Import <strong>posts, pages, comments, custom fields, categories, and "
677
+ #~ "tags</strong> from a WordPress export file."
678
+ #~ msgstr ""
679
+ #~ "從WordPress匯出檔案,匯入 <strong>文章、頁面、留言、自訂欄位、分類與標籤</"
680
+ #~ "strong>。"
681
+
682
+ #~ msgctxt "calendar caption"
683
+ #~ msgid "%1$s %2$s"
684
+ #~ msgstr "%1$s %2$s"
685
+
686
+ #~ msgid "View posts for %1$s %2$s"
687
+ #~ msgstr "檢視文章 %1$s %2$s"
polylang.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: Polylang
4
  Plugin URI: http://polylang.wordpress.com/
5
- Version: 1.3.1
6
  Author: Frédéric Demarle
7
  Description: Adds multilingual capability to WordPress
8
  Text Domain: polylang
@@ -10,7 +10,7 @@ Domain Path: /languages
10
  */
11
 
12
  /*
13
- * Copyright 2011-2013 Frédéric Demarle
14
  *
15
  * This program is free software; you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License as published by
@@ -29,8 +29,8 @@ Domain Path: /languages
29
  *
30
  */
31
 
32
- define('POLYLANG_VERSION', '1.3.1');
33
- define('PLL_MIN_WP_VERSION', '3.1');
34
 
35
  define('POLYLANG_BASENAME', plugin_basename(__FILE__)); // plugin name as known by WP
36
 
@@ -84,9 +84,9 @@ class Polylang {
84
  if (isset($_GET['action'], $_GET['plugin']) && 'deactivate' == $_GET['action'] && plugin_basename(__FILE__) == $_GET['plugin'])
85
  return;
86
 
87
- // avoid loading polylang admin for frontend ajax requests if 'pll_load_front' is set (thanks to g100g)
88
  if (!defined('PLL_AJAX_ON_FRONT'))
89
- define('PLL_AJAX_ON_FRONT', isset($_REQUEST['pll_load_front']));
90
 
91
  if (!defined('PLL_ADMIN'))
92
  define('PLL_ADMIN', defined('DOING_CRON') || (is_admin() && !PLL_AJAX_ON_FRONT));
@@ -171,6 +171,8 @@ class Polylang {
171
  * @since 0.5
172
  */
173
  protected function _activate() {
 
 
174
  if ($options = get_option('polylang')) {
175
  // plugin upgrade
176
  if (version_compare($options['version'], POLYLANG_VERSION, '<')) {
@@ -197,8 +199,9 @@ class Polylang {
197
  update_option('polylang', $options);
198
  }
199
 
200
- // add our rewrite rules
201
- $this->get_links_model(new PLL_Admin_Model($options), $options);
 
202
  flush_rewrite_rules();
203
  }
204
 
@@ -243,8 +246,10 @@ class Polylang {
243
  public function autoload($class) {
244
  $class = str_replace('_', '-', strtolower(substr($class, 4)));
245
  foreach (array(PLL_INC, PLL_FRONT_INC, PLL_ADMIN_INC) as $path)
246
- if (file_exists($file = "$path/$class.php"))
247
  require_once($file);
 
 
248
  }
249
 
250
  /*
2
  /*
3
  Plugin Name: Polylang
4
  Plugin URI: http://polylang.wordpress.com/
5
+ Version: 1.4
6
  Author: Frédéric Demarle
7
  Description: Adds multilingual capability to WordPress
8
  Text Domain: polylang
10
  */
11
 
12
  /*
13
+ * Copyright 2011-2014 Frédéric Demarle
14
  *
15
  * This program is free software; you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License as published by
29
  *
30
  */
31
 
32
+ define('POLYLANG_VERSION', '1.4');
33
+ define('PLL_MIN_WP_VERSION', '3.5');
34
 
35
  define('POLYLANG_BASENAME', plugin_basename(__FILE__)); // plugin name as known by WP
36
 
84
  if (isset($_GET['action'], $_GET['plugin']) && 'deactivate' == $_GET['action'] && plugin_basename(__FILE__) == $_GET['plugin'])
85
  return;
86
 
87
+ // avoid loading polylang admin for frontend ajax requests
88
  if (!defined('PLL_AJAX_ON_FRONT'))
89
+ define('PLL_AJAX_ON_FRONT', defined('DOING_AJAX') && DOING_AJAX && empty($_REQUEST['pll_ajax_backend']));
90
 
91
  if (!defined('PLL_ADMIN'))
92
  define('PLL_ADMIN', defined('DOING_CRON') || (is_admin() && !PLL_AJAX_ON_FRONT));
171
  * @since 0.5
172
  */
173
  protected function _activate() {
174
+ global $polylang;
175
+
176
  if ($options = get_option('polylang')) {
177
  // plugin upgrade
178
  if (version_compare($options['version'], POLYLANG_VERSION, '<')) {
199
  update_option('polylang', $options);
200
  }
201
 
202
+ // always provide a global $polylang object and add our rewrite rules if needed
203
+ $polylang = new StdClass();
204
+ $polylang->links_model = $this->get_links_model(new PLL_Admin_Model($options), $options);
205
  flush_rewrite_rules();
206
  }
207
 
246
  public function autoload($class) {
247
  $class = str_replace('_', '-', strtolower(substr($class, 4)));
248
  foreach (array(PLL_INC, PLL_FRONT_INC, PLL_ADMIN_INC) as $path)
249
+ if (file_exists($file = "$path/$class.php")) {
250
  require_once($file);
251
+ break;
252
+ }
253
  }
254
 
255
  /*
readme.txt CHANGED
@@ -2,9 +2,9 @@
2
  Contributors: Chouby
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CCWWYUUQV8F4E
4
  Tags: multilingual, bilingual, translate, translation, language, multilanguage, international, localization
5
- Requires at least: 3.1
6
  Tested up to: 3.8
7
- Stable tag: 1.3.1
8
  License: GPLv2 or later
9
 
10
  Polylang adds multilingual content management support to WordPress.
@@ -24,7 +24,7 @@ Polylang allows you to create a bilingual or multilingual WordPress site. You wr
24
 
25
  = Translators =
26
 
27
- The plugin admin interface is currently available in 30 languages: English, French, German by [Christian Ries](http://www.singbyfoot.lu), Russian by [yoyurec](http://yoyurec.in.ua) and unostar, Greek by [theodotos](http://www.ubuntucy.org), Dutch by [AlbertGn](http://wordpress.org/support/profile/albertgn), Hebrew by [ArielK](http://www.arielk.net), Polish by [Peter Paciorkiewicz](http://www.paciorkiewicz.pl) and [Bartosz](http://www.dfactory.eu/), Latvian by [@AndyDeGroo](http://twitter.com/AndyDeGroo), Italian by [Luca Barbetti](http://wordpress.org/support/profile/lucabarbetti), Danish by [Compute](http://wordpress.org/support/profile/compute), Spanish by Curro, Portuguese by [Vitor Carvalho](http://vcarvalho.com/), Lithuanian by [Naglis Jonaitis](http://najo.lt/), Turkish by [darchws](http://darch.ws/), Finnish by [Jani Alha](http://www.wysiwyg.fi), Bulgarian by [pavelsof](http://wordpress.org/support/profile/pavelsof), Belarusian by [Alexander Markevitch](http://fourfeathers.by/), Afrikaans by [Kobus Joubert](http://translate3d.com/), Hungarian by Csaba Erdei, Norwegian by [Tom Boersma](http://www.oransje.com/), Slovak by [Branco (WebHostingGeeks.com)](http://webhostinggeeks.com/user-reviews/), Swedish by [matsii](http://wordpress.org/support/profile/matsii) and [Jon Täng](http://jontang.se), Catalan by [Núria Martínez Berenguer](http://www.linkedin.com/profile/view?id=127867004&trk=nav_responsive_tab_profile&locale=en_US), Ukrainian by [cmd soft](http://www.cmd-soft.com/), Estonian by [Ahto Naris](http://profiles.wordpress.org/ahtonaris/), Venetian by Michele Brunelli, simplified Chinese by [Changmeng Hu](http://www.wpdaxue.com), Indonesian by [ajoull](http://www.ajoull.com/), Arabic by [Anas Sulaiman](http://ahs.pw/)
28
 
29
  = Credits =
30
 
@@ -60,35 +60,32 @@ See http://polylang.wordpress.com/documentation/contribute/
60
 
61
  == Screenshots ==
62
 
63
- 1. The Polylang languages admin panel in WordPress 3.3.1
64
 
65
  == Upgrade Notice ==
66
 
67
- = 1.3.1 =
68
  Polylang 1.2 introduced major internal changes. More than ever, make a database backup before upgrading from 1.1.6 or older! If you are using a version older than 0.8, please ugrade to 0.9.8 before ugrading to 1.3
69
 
70
  == Changelog ==
71
 
72
- = 1.3.1 (2013-12-13) =
73
-
74
- * Bug correction: fatal error on settings page if a static front page without language is set
75
- * Bug correction: wrong home url when using different domains per language
76
-
77
- = 1.3 (2013-12-11) =
78
-
79
- * Refresh admin UI for better look in WP 3.8 and more dynamic comportment
80
- * The "Detect browser language" option does now also controls returning visits (based on cookie).
81
- * Improved performance by optimizing some queries for WP 3.5+
82
- * The user biography in default language is now stored in default WordPress usermeta
83
- * Add language parameter in API function pll_home_url and allow to call it on admin side
84
- * Calling 'get_terms' with the 'lang' parameter now uses a cache object per language
85
- * Bug correction: conflict with unstranslated taxonomies
86
- * Bug correction: possible malformed translation archive url in language switcher
87
- * Bug correction: a wrong language may be displayed in quick edit dropdown
88
- * Bug correction: it is possible to add multiple translations (in the same language) for a single taxonomy term
89
- * Bug correction: non public post types and taxonomies are visible in Polylang settings
90
- * Bug correction: the language is always chosen from cookie (or browser preferences) in some installations
91
- * Bug correction: Firefox language preference is not recognized when comparison is made on locale (instead of ISO 639-1 language code)
92
- * Bug correction: incorrect tax_query in PLL_Auto_Translate
93
 
94
  See changelog.txt for older changelog
2
  Contributors: Chouby
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CCWWYUUQV8F4E
4
  Tags: multilingual, bilingual, translate, translation, language, multilanguage, international, localization
5
+ Requires at least: 3.5
6
  Tested up to: 3.8
7
+ Stable tag: 1.4
8
  License: GPLv2 or later
9
 
10
  Polylang adds multilingual content management support to WordPress.
24
 
25
  = Translators =
26
 
27
+ The plugin admin interface is currently available in 31 languages: English, French, German by [Christian Ries](http://www.singbyfoot.lu), Russian by [yoyurec](http://yoyurec.in.ua) and unostar, Greek by [theodotos](http://www.ubuntucy.org), Dutch by [AlbertGn](http://wordpress.org/support/profile/albertgn), Hebrew by [ArielK](http://www.arielk.net), Polish by [Peter Paciorkiewicz](http://www.paciorkiewicz.pl) and [Bartosz](http://www.dfactory.eu/), Latvian by [@AndyDeGroo](http://twitter.com/AndyDeGroo), Italian by [Luca Barbetti](http://wordpress.org/support/profile/lucabarbetti), Danish by [Compute](http://wordpress.org/support/profile/compute), Spanish by Curro, Portuguese by [Vitor Carvalho](http://vcarvalho.com/), Lithuanian by [Naglis Jonaitis](http://najo.lt/), Turkish by [darchws](http://darch.ws/), Finnish by [Jani Alha](http://www.wysiwyg.fi), Bulgarian by [pavelsof](http://wordpress.org/support/profile/pavelsof), Belarusian by [Alexander Markevitch](http://fourfeathers.by/), Afrikaans by [Kobus Joubert](http://translate3d.com/), Hungarian by Csaba Erdei, Norwegian by [Tom Boersma](http://www.oransje.com/), Slovak by [Branco (WebHostingGeeks.com)](http://webhostinggeeks.com/user-reviews/), Swedish by [matsii](http://wordpress.org/support/profile/matsii) and [Jon Täng](http://jontang.se), Catalan by [Núria Martínez Berenguer](http://www.linkedin.com/profile/view?id=127867004&trk=nav_responsive_tab_profile&locale=en_US), Ukrainian by [cmd soft](http://www.cmd-soft.com/), Estonian by [Ahto Naris](http://profiles.wordpress.org/ahtonaris/), Venetian by Michele Brunelli, simplified Chinese by [Changmeng Hu](http://www.wpdaxue.com), Indonesian by [ajoull](http://www.ajoull.com/), Arabic by [Anas Sulaiman](http://ahs.pw/), traditional Chinese by [香腸](http://sofree.cc/)
28
 
29
  = Credits =
30
 
60
 
61
  == Screenshots ==
62
 
63
+ 1. The Polylang languages admin panel in WordPress 3.8
64
 
65
  == Upgrade Notice ==
66
 
67
+ = 1.4 =
68
  Polylang 1.2 introduced major internal changes. More than ever, make a database backup before upgrading from 1.1.6 or older! If you are using a version older than 0.8, please ugrade to 0.9.8 before ugrading to 1.3
69
 
70
  == Changelog ==
71
 
72
+ = 1.4 (2014-01-22) =
73
+
74
+ * Add Traditionial Chinese translation contributed by [香腸](http://sofree.cc/)
75
+ * Minimum WordPress version is now v3.5
76
+ * Refresh translations metaboxes: now translated posts are chosen in a dropdown list
77
+ * Check if translated archives for category, tag and post format are empty before displaying the language switcher
78
+ * Add specific management of translated featured tag in Twenty Fourteen
79
+ * Add the possibility not to cache homepage urls with option PLL_CACHE_HOME_URL (for users having several domains).
80
+ * The function get_pages is now filtered by language
81
+ * Ajax requests on frontend are now automatically detected. It is no more necessary to set 'pll_load_front' :)
82
+ * Various performance improvements
83
+ * 'pll_get_post_types' and 'pll_get_taxonomies' filters must be added *before* 'after_setup_theme' is fired
84
+ * Pre 1.2 data will be removed from DB at first upgrade at least 60 days after upgrade to 1.4
85
+ * Removed some duplicate code between admin and frontend
86
+ * Bug correction: incorrect pagination when using domains or subdomains
87
+ * Bug correction: post format link not translated
88
+ * Bug correction: impossible to use child terms with same name in hierarchical taxonomies
89
+ * Bug correction: the terms list table is filtered according to new translation language instead of admin language filter
 
 
 
90
 
91
  See changelog.txt for older changelog
screenshot-1.png CHANGED
Binary file
uninstall.php CHANGED
@@ -35,7 +35,7 @@ class PLL_Uninstall {
35
  */
36
  function uninstall() {
37
  // suppress data of the old model < 1.2
38
- // FIXME: to remove in 1.3
39
  global $wpdb;
40
  $wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
41
 
@@ -81,7 +81,7 @@ class PLL_Uninstall {
81
  wp_delete_post($id, true);
82
 
83
  // delete the strings translations (<1.2)
84
- // FIXME: to remove in 1.3
85
  foreach ($languages as $lang)
86
  delete_option('polylang_mo'.$lang->term_id);
87
 
@@ -120,6 +120,7 @@ class PLL_Uninstall {
120
 
121
  //delete transients
122
  delete_transient('pll_languages_list');
 
123
  }
124
  }
125
 
35
  */
36
  function uninstall() {
37
  // suppress data of the old model < 1.2
38
+ // FIXME: to remove when support for v1.1.6 will be dropped
39
  global $wpdb;
40
  $wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
41
 
81
  wp_delete_post($id, true);
82
 
83
  // delete the strings translations (<1.2)
84
+ // FIXME: to remove when support for v1.1.6 will be dropped
85
  foreach ($languages as $lang)
86
  delete_option('polylang_mo'.$lang->term_id);
87
 
120
 
121
  //delete transients
122
  delete_transient('pll_languages_list');
123
+ delete_transient('pll_upgrade_1_4');
124
  }
125
  }
126