Version Description
- Initial release
Download this release
Release Info
Developer | Chouby |
Plugin | Polylang |
Version | 0.1 |
Comparing to | |
See all releases |
Version 0.1
- add-term-form.php +11 -0
- admin.php +450 -0
- base.php +62 -0
- edit-term-form.php +74 -0
- languages-form.php +117 -0
- list-table.php +100 -0
- polylang-fr_FR.mo +0 -0
- polylang-fr_FR.po +172 -0
- polylang.php +654 -0
- post-metabox.php +40 -0
- readme.txt +76 -0
- uninstall.php +36 -0
- widget.php +19 -0
add-term-form.php
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php // adds a language select list in the Categories and Post tags admin panels ?>
|
2 |
+
<div class="form-field">
|
3 |
+
<label for="lang_choice"><?php _e('Language', 'polylang');?></label>
|
4 |
+
<select name="lang_choice" id="lang_choice">
|
5 |
+
<option value="-1"></option> <?php
|
6 |
+
foreach ($listlanguages as $language) {
|
7 |
+
printf("<option value='%s' %s>%s</option>\n", $language->term_id, $language == $lang ? 'selected="selected"' : '', $language->name);
|
8 |
+
} ?>
|
9 |
+
</select>
|
10 |
+
<p><?php _e('Sets the language', 'polylang');?></p>
|
11 |
+
</div>
|
admin.php
ADDED
@@ -0,0 +1,450 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require_once(dirname(__FILE__).'/list-table.php');
|
4 |
+
|
5 |
+
class Polylang_Admin extends Polylang_Base {
|
6 |
+
function __construct() {
|
7 |
+
// adds a 'settings' link in the plugins table
|
8 |
+
$plugin_file = basename( dirname( __FILE__ ) ).'/polylang.php';
|
9 |
+
add_filter('plugin_action_links_'.$plugin_file, array(&$this, 'plugin_action_links'));
|
10 |
+
|
11 |
+
// adds the link to the languages panel in the wordpress admin menu
|
12 |
+
add_action('admin_menu', array(&$this, 'add_menus'));
|
13 |
+
|
14 |
+
// add the language column (as well as a filter by language) in 'All Posts' an 'All Pages' panels
|
15 |
+
add_filter('manage_posts_columns', array(&$this, 'add_post_column'), 10, 2);
|
16 |
+
add_filter('manage_pages_columns', array(&$this, 'add_post_column'));
|
17 |
+
add_action('manage_posts_custom_column', array(&$this, 'post_column'), 10, 2);
|
18 |
+
add_action('manage_pages_custom_column', array(&$this, 'post_column'), 10, 2);
|
19 |
+
add_filter('parse_query',array(&$this,'parse_query'));
|
20 |
+
add_action('restrict_manage_posts', array(&$this, 'restrict_manage_posts'));
|
21 |
+
|
22 |
+
// adds the Languages box in the 'Edit Post' and 'Edit Page' panels
|
23 |
+
add_action('add_meta_boxes', array(&$this, 'add_meta_boxes'));
|
24 |
+
|
25 |
+
// adds actions related to languages when saving aor deleting posts and pages
|
26 |
+
add_action('save_post', array(&$this, 'save_post'));
|
27 |
+
add_action('before_delete_post', array(&$this, 'delete_post'));
|
28 |
+
|
29 |
+
// adds the language field in the 'Categories' and 'Post Tags' panels
|
30 |
+
add_action('category_add_form_fields', array(&$this, 'add_term_form'));
|
31 |
+
add_action('post_tag_add_form_fields', array(&$this, 'add_term_form'));
|
32 |
+
|
33 |
+
// adds the language field and translations tables in the 'Edit Category' and 'Edit Tag' panels
|
34 |
+
add_action('category_edit_form_fields', array(&$this, 'edit_term_form'));
|
35 |
+
add_action('post_tag_edit_form_fields', array(&$this, 'edit_term_form'));
|
36 |
+
|
37 |
+
// adds the language column in the 'Categories' and 'Post Tags' tables
|
38 |
+
add_filter('manage_edit-category_columns', array(&$this, 'add_term_column'));
|
39 |
+
add_filter('manage_edit-post_tag_columns', array(&$this, 'add_term_column'));
|
40 |
+
add_action('manage_category_custom_column', array(&$this, 'term_column'), 10, 3);
|
41 |
+
add_action('manage_post_tag_custom_column', array(&$this, 'term_column'), 10, 3);
|
42 |
+
|
43 |
+
// adds actions related to languages when saving or deleting categories and post tags
|
44 |
+
add_action('created_category', array(&$this,'save_term'));
|
45 |
+
add_action('created_post_tag', array(&$this,'save_term'));
|
46 |
+
add_action('edited_category', array(&$this,'save_term'));
|
47 |
+
add_action('edited_post_tag', array(&$this,'save_term'));
|
48 |
+
add_action('delete_category', array(&$this,'delete_term'));
|
49 |
+
add_action('delete_post_tag', array(&$this,'delete_term'));
|
50 |
+
|
51 |
+
// refresh rewrite rules if the 'page_on_front' option is modified
|
52 |
+
add_action('update_option', array(&$this,'update_option'));
|
53 |
+
}
|
54 |
+
|
55 |
+
// adds a 'settings' link in the plugins table
|
56 |
+
function plugin_action_links($links) {
|
57 |
+
$settings_link = '<a href="admin.php?page=mlang">' . __('Settings') . '</a>';
|
58 |
+
array_unshift( $links, $settings_link );
|
59 |
+
return $links;
|
60 |
+
}
|
61 |
+
|
62 |
+
// adds the link to the languages panel in the wordpress admin menu
|
63 |
+
function add_menus() {
|
64 |
+
add_submenu_page('options-general.php', __('Languages','polylang'), __('Languages','polylang'), 'manage_options', 'mlang', array($this, 'languages_page'));
|
65 |
+
}
|
66 |
+
|
67 |
+
// the languages panel
|
68 |
+
function languages_page() {
|
69 |
+
global $wp_rewrite;
|
70 |
+
$options = get_option('polylang');
|
71 |
+
|
72 |
+
$listlanguages = $this->get_languages_list();
|
73 |
+
$list_table = new Polylang_List_Table();
|
74 |
+
|
75 |
+
$action = '';
|
76 |
+
if (isset($_REQUEST['action']))
|
77 |
+
$action = $_REQUEST['action'];
|
78 |
+
|
79 |
+
switch ($action) {
|
80 |
+
case 'add':
|
81 |
+
check_admin_referer( 'add-lang', '_wpnonce_add-lang' );
|
82 |
+
|
83 |
+
if (isset($_POST['name']) && isset($_POST['description'])) {
|
84 |
+
wp_insert_term($_POST['name'],'language',array('slug'=>$_POST['slug'], 'description'=>$_POST['description']));
|
85 |
+
$wp_rewrite->flush_rules(); // refresh rewrite rules
|
86 |
+
}
|
87 |
+
if (!isset($options['default_lang'])) { // if this is the first language created, set it as default language
|
88 |
+
$options['default_lang'] = $_POST['slug'];
|
89 |
+
update_option('polylang', $options);
|
90 |
+
}
|
91 |
+
wp_redirect('admin.php?page=mlang'); // to refresh the page (possible thanks to the $_GET['noheader']=true)
|
92 |
+
exit;
|
93 |
+
break;
|
94 |
+
|
95 |
+
case 'delete':
|
96 |
+
check_admin_referer( 'delete-lang');
|
97 |
+
|
98 |
+
if (isset($_GET['lang'])) {
|
99 |
+
$lang = $this->get_language($_GET['lang']);
|
100 |
+
$lang_slug = $lang->slug;
|
101 |
+
|
102 |
+
// delete all translations in posts in this language
|
103 |
+
$args = array('numberposts'=>-1, 'taxonomy' => 'language', 'term' => $lang_slug, 'post_type'=>'any', 'post_status'=>'any');
|
104 |
+
$posts = get_posts($args);
|
105 |
+
foreach ($posts as $post) {
|
106 |
+
foreach ($languages as $language) {
|
107 |
+
delete_post_meta($post->ID, '_lang-'.$language->slug);
|
108 |
+
}
|
109 |
+
}
|
110 |
+
|
111 |
+
// delete references to this language in all posts
|
112 |
+
$args = array('numberposts'=>-1, 'meta_key'=>'_lang-'.$lang_slug, 'post_type'=>'any', 'post_status'=>'any');
|
113 |
+
$posts = get_posts($args);
|
114 |
+
foreach ($posts as $post) {
|
115 |
+
delete_post_meta($post->ID, '_lang-'.$lang_slug);
|
116 |
+
}
|
117 |
+
|
118 |
+
// delete references to this language in categories & post tags
|
119 |
+
$terms = get_terms(array('category', 'post_tag'), 'get=all');
|
120 |
+
foreach ($terms as $term) {
|
121 |
+
if ($this->get_term_language($term->term_id) == $lang) {
|
122 |
+
foreach ($languages as $language) {
|
123 |
+
delete_metadata('term', $term->term_id, '_lang-'.$language->slug); // deletes translations of this term
|
124 |
+
}
|
125 |
+
delete_metadata('term', $term->term_id, '_language', $_GET['lang']); // delete language of this term
|
126 |
+
}
|
127 |
+
delete_metadata('term', $term->term_id, '_lang-'.$lang_slug); // deletes references to this term in translated term
|
128 |
+
}
|
129 |
+
|
130 |
+
// delete the language itself
|
131 |
+
wp_delete_term($_GET['lang'], 'language');
|
132 |
+
$wp_rewrite->flush_rules(); // refresh rewrite rules
|
133 |
+
|
134 |
+
// oops ! we deleted the default language...
|
135 |
+
if ($options['default_lang'] == $lang_slug) {
|
136 |
+
if (!empty($languages))
|
137 |
+
$options['default_lang'] = $languages[0]->slug; // arbitrary choice...
|
138 |
+
else
|
139 |
+
unset($options['default_lang']);
|
140 |
+
update_option('polylang', $options);
|
141 |
+
}
|
142 |
+
}
|
143 |
+
wp_redirect('admin.php?page=mlang'); // to refresh the page (possible thanks to the $_GET['noheader']=true)
|
144 |
+
exit;
|
145 |
+
break;
|
146 |
+
|
147 |
+
case 'edit':
|
148 |
+
if (isset($_GET['lang']))
|
149 |
+
$edit_lang = $this->get_language($_GET['lang']);
|
150 |
+
break;
|
151 |
+
|
152 |
+
case 'update':
|
153 |
+
check_admin_referer( 'add-lang', '_wpnonce_add-lang' );
|
154 |
+
|
155 |
+
if (isset($_POST['lang'])) {
|
156 |
+
// Update links to this language in posts and terms in case the slug has been modified
|
157 |
+
$lang = $this->get_language($_POST['lang']);
|
158 |
+
$old_slug = $lang->slug;
|
159 |
+
|
160 |
+
if ($old_slug != $_POST['slug']) {
|
161 |
+
// update the language slug in posts meta
|
162 |
+
$args = array('numberposts'=>-1, 'meta_key'=>'_lang-'.$old_slug, 'post_type'=>'any', 'post_status'=>'any');
|
163 |
+
$posts = get_posts($args);
|
164 |
+
foreach ($posts as $post) {
|
165 |
+
$post_id = get_post_meta($post->ID, '_lang-'.$old_slug, true);
|
166 |
+
delete_post_meta($post->ID, '_lang-'.$old_slug);
|
167 |
+
update_post_meta($post->ID, '_lang-'.$_POST['slug'], $post_id);
|
168 |
+
}
|
169 |
+
|
170 |
+
// update the language slug in categories & post tags meta
|
171 |
+
$terms = get_terms(array('category', 'post_tag'), 'get=all');
|
172 |
+
foreach ($terms as $term) {
|
173 |
+
$term_id = get_metadata('term', $term->term_id, '_lang-'.$old_slug, true);
|
174 |
+
if ($term_id) {
|
175 |
+
delete_metadata('term', $term->term_id, '_lang-'.$old_slug);
|
176 |
+
update_metadata('term', $term->term_id, '_lang-'.$_POST['slug'], $term_id);
|
177 |
+
}
|
178 |
+
}
|
179 |
+
}
|
180 |
+
|
181 |
+
// and finally update the language itself
|
182 |
+
wp_update_term($_POST['lang'], 'language', array('name'=>$_POST['name'], 'slug'=>$_POST['slug'], 'description'=>$_POST['description']));
|
183 |
+
$wp_rewrite->flush_rules(); // refresh rewrite rules
|
184 |
+
}
|
185 |
+
wp_redirect('admin.php?page=mlang'); // to refresh the page (possible thanks to the $_GET['noheader']=true)
|
186 |
+
exit;
|
187 |
+
break;
|
188 |
+
|
189 |
+
case 'options':
|
190 |
+
check_admin_referer( 'options-lang', '_wpnonce_options-lang' );
|
191 |
+
|
192 |
+
$options['rewrite'] = $_POST['rewrite'];
|
193 |
+
isset($_POST['browser']) ? $options['browser'] = 1 : $options['browser'] = 0;
|
194 |
+
$options['default_lang'] = $_POST['default_lang'];
|
195 |
+
update_option('polylang', $options);
|
196 |
+
|
197 |
+
// refresh refresh permalink structure and rewrite rules in case rewrite option has been modified
|
198 |
+
$wp_rewrite->extra_permastructs['language'][0] = $options['rewrite'] ? '%language%' : '/language/%language%';
|
199 |
+
$wp_rewrite->flush_rules();
|
200 |
+
break;
|
201 |
+
|
202 |
+
default:
|
203 |
+
}
|
204 |
+
|
205 |
+
// prepare the list table of languages
|
206 |
+
$data = array();
|
207 |
+
foreach ($listlanguages as $lang)
|
208 |
+
$data[] = (array) $lang;
|
209 |
+
|
210 |
+
$list_table->prepare_items($data);
|
211 |
+
|
212 |
+
// displays the page
|
213 |
+
include(dirname(__FILE__).'/languages-form.php');
|
214 |
+
}
|
215 |
+
|
216 |
+
// adds the language column (before the date column) in the posts and pages list table
|
217 |
+
function add_post_column($columns, $post_type ='') {
|
218 |
+
if (in_array($post_type, array('', 'post', 'page'))) {
|
219 |
+
$keys = array( 'date', 'comments' );
|
220 |
+
foreach ($keys as $k) {
|
221 |
+
if (array_key_exists($k, $columns))
|
222 |
+
$end[$k] = array_pop($columns);
|
223 |
+
}
|
224 |
+
|
225 |
+
$columns['language'] = __('Language', 'polylang');
|
226 |
+
|
227 |
+
if (isset($end))
|
228 |
+
$columns = array_merge($columns, $end);
|
229 |
+
}
|
230 |
+
return $columns;
|
231 |
+
}
|
232 |
+
|
233 |
+
// fills the language column in the posts table
|
234 |
+
function post_column($column, $post_id) {
|
235 |
+
$lang = $this->get_post_language($post_id);
|
236 |
+
if ($lang && $column == 'language')
|
237 |
+
echo $lang->name;
|
238 |
+
}
|
239 |
+
|
240 |
+
// converts language term_id to slug in $query
|
241 |
+
// needed to filter the posts by language with wp_dropdown_categories in restrict_manage_posts
|
242 |
+
function parse_query($query) {
|
243 |
+
global $pagenow;
|
244 |
+
$qvars = &$query->query_vars;
|
245 |
+
if ($pagenow=='edit.php' && isset($qvars['lang']) && is_numeric($qvars['lang'])) {
|
246 |
+
$lang = $this->get_language($qvars['lang']);
|
247 |
+
if ($lang)
|
248 |
+
$qvars['lang'] = $lang->slug;
|
249 |
+
}
|
250 |
+
}
|
251 |
+
|
252 |
+
// adds a filter for languages in the Posts and Pages panels
|
253 |
+
function restrict_manage_posts() {
|
254 |
+
global $typenow;
|
255 |
+
global $wp_query;
|
256 |
+
$languages = $this->get_languages_list();
|
257 |
+
|
258 |
+
if (!empty($languages) && in_array($typenow, array('', 'post', 'page'))) {
|
259 |
+
$qvars = $wp_query->query;
|
260 |
+
wp_dropdown_categories(array(
|
261 |
+
'show_option_all' => __('Show all languages', 'polylang'),
|
262 |
+
'name' => 'lang',
|
263 |
+
'selected' => isset($qvars['lang']) ? $qvars['lang'] : 0,
|
264 |
+
'taxonomy' => 'language'));
|
265 |
+
}
|
266 |
+
}
|
267 |
+
|
268 |
+
// adds the Languages box in the 'Edit Post' and 'Edit Page' panels
|
269 |
+
function add_meta_boxes() {
|
270 |
+
add_meta_box('ml_box', __('Languages','multiLang'), array(&$this,'post_language'), 'post', 'side','high');
|
271 |
+
add_meta_box('ml_box', __('Languages','multiLang'), array(&$this,'post_language'), 'page', 'side','high');
|
272 |
+
}
|
273 |
+
|
274 |
+
// the Languages metabox in the 'Edit Post' and 'Edit Page' panels
|
275 |
+
function post_language() {
|
276 |
+
global $post_ID;
|
277 |
+
$post_type = get_post_type($post_ID);
|
278 |
+
|
279 |
+
$lang = $this->get_post_language($post_ID);
|
280 |
+
if (isset($_GET['new_lang']))
|
281 |
+
$lang = $this->get_language($_GET['new_lang']);
|
282 |
+
|
283 |
+
include(dirname(__FILE__).'/post-metabox.php');
|
284 |
+
}
|
285 |
+
|
286 |
+
// called when a post (or page) is saved, published or updated
|
287 |
+
// the underscore in '_lang' hides the post meta in the Custom Fields metabox in the Edit Post screen
|
288 |
+
function save_post($post_id) {
|
289 |
+
$id = wp_is_post_revision($post_id);
|
290 |
+
if ($id)
|
291 |
+
$post_id = $id;
|
292 |
+
|
293 |
+
if (isset($_POST['lang_choice']))
|
294 |
+
wp_set_object_terms($post_id, $_POST['lang_choice'], 'language' );
|
295 |
+
|
296 |
+
$lang = $this->get_post_language($post_id);
|
297 |
+
$listlanguages = $this->get_languages_list();
|
298 |
+
foreach ($listlanguages as $language) {
|
299 |
+
if (isset($_POST[$language->slug])) {
|
300 |
+
$value = $_POST[$language->slug];
|
301 |
+
if ($value)
|
302 |
+
update_post_meta($post_id, '_lang-'.$language->slug, $value); // saves the links to translated posts
|
303 |
+
}
|
304 |
+
if ($lang && $language != $lang){
|
305 |
+
update_post_meta($this->get_translated_post($post_id, $language), '_lang-'.$lang->slug, $post_id); // tells the translated to link to this post
|
306 |
+
}
|
307 |
+
}
|
308 |
+
|
309 |
+
// propagates translations between them
|
310 |
+
foreach ($listlanguages as $language) {
|
311 |
+
foreach ($listlanguages as $lg) {
|
312 |
+
$id = $this->get_translated_post($post_id, $lg);
|
313 |
+
if ($lg != $lang && $lg != $language && $id)
|
314 |
+
update_post_meta($this->get_translated_post($post_id, $language), '_lang-'.$lg->slug, $id);
|
315 |
+
}
|
316 |
+
}
|
317 |
+
}
|
318 |
+
|
319 |
+
// called when a post (or page) is deleted
|
320 |
+
function delete_post($post_id) {
|
321 |
+
$id = wp_is_post_revision($post_id);
|
322 |
+
if ($id)
|
323 |
+
$post_id = $id;
|
324 |
+
|
325 |
+
$lang = $this->get_post_language($post_id);
|
326 |
+
if($lang) {
|
327 |
+
$listlanguages = $this->get_languages_list();
|
328 |
+
foreach ($listlanguages as $language) {
|
329 |
+
delete_post_meta($this->get_translated_post($post_id, $language), '_lang-'.$lang->slug); // delete links to this post
|
330 |
+
// WP deletes post metas linked to this post so it is useless to do it before
|
331 |
+
}
|
332 |
+
}
|
333 |
+
}
|
334 |
+
|
335 |
+
// adds the language field in the 'Categories' and 'Post Tags' panels
|
336 |
+
function add_term_form() {
|
337 |
+
$lang = NULL;
|
338 |
+
if (isset($_GET['new_lang']))
|
339 |
+
$lang = $this->get_language($_GET['new_lang']);
|
340 |
+
|
341 |
+
$listlanguages = $this->get_languages_list();
|
342 |
+
|
343 |
+
// displays the language field
|
344 |
+
include(dirname(__FILE__).'/add-term-form.php');
|
345 |
+
}
|
346 |
+
|
347 |
+
// adds the language field and translations tables in the 'Edit Category' and 'Edit Tag' panels
|
348 |
+
function edit_term_form($tag) {
|
349 |
+
$term_id = $tag->term_id;
|
350 |
+
$lang = $this->get_term_language($term_id);
|
351 |
+
|
352 |
+
$listlanguages = $this->get_languages_list();
|
353 |
+
$taxonomy = $tag->taxonomy;
|
354 |
+
|
355 |
+
include(dirname(__FILE__).'/edit-term-form.php');
|
356 |
+
}
|
357 |
+
|
358 |
+
// adds the language column (before the posts column) in the 'Categories' or Post Tags table
|
359 |
+
function add_term_column($columns) {
|
360 |
+
if (array_key_exists('posts', $columns))
|
361 |
+
$end = array_pop($columns);
|
362 |
+
|
363 |
+
$columns['language'] = __('Language', 'polylang');
|
364 |
+
|
365 |
+
if (isset($end))
|
366 |
+
$columns['posts'] = $end;
|
367 |
+
|
368 |
+
return $columns;
|
369 |
+
}
|
370 |
+
|
371 |
+
// fills the language column in the 'Categories' or Post Tags table
|
372 |
+
function term_column($empty, $column, $term_id) {
|
373 |
+
$lang = $this->get_term_language($term_id);
|
374 |
+
if ($lang && $column == 'language')
|
375 |
+
echo $lang->name;
|
376 |
+
}
|
377 |
+
|
378 |
+
// called when a category or post tag is created or edited
|
379 |
+
function save_term($term_id) {
|
380 |
+
if (isset($_POST['lang_choice']) && $_POST['lang_choice'] != -1 ) {
|
381 |
+
update_metadata('term', $term_id, '_language', $_POST['lang_choice'] );
|
382 |
+
$lang = $this->get_language($_POST['lang_choice']);
|
383 |
+
|
384 |
+
$listlanguages = $this->get_languages_list();
|
385 |
+
foreach ($listlanguages as $language) {
|
386 |
+
$slug = '_lang-'.$language->slug;
|
387 |
+
if (isset($_POST[$slug]) && $_POST[$slug] != -1) {
|
388 |
+
update_metadata('term', $term_id, $slug, $_POST[$slug] );
|
389 |
+
update_metadata('term', $_POST[$slug], '_lang-'.$lang->slug, $term_id );
|
390 |
+
}
|
391 |
+
}
|
392 |
+
}
|
393 |
+
|
394 |
+
$qvars = $this->get_referer_vars();
|
395 |
+
if (isset($qvars['from_tag']) && isset($qvars['from_lang']) && isset($qvars['new_lang'])) {
|
396 |
+
$from_lang = $this->get_language($qvars['from_lang']);
|
397 |
+
update_metadata('term', $term_id, '_lang-'.$from_lang->slug, $qvars['from_tag'] );
|
398 |
+
$new_lang = $this->get_language($qvars['new_lang']);
|
399 |
+
update_metadata('term', $qvars['from_tag'], '_lang-'.$new_lang->slug, $term_id );
|
400 |
+
}
|
401 |
+
|
402 |
+
// propagates translations between them
|
403 |
+
foreach ($listlanguages as $language) {
|
404 |
+
foreach ($listlanguages as $lg) {
|
405 |
+
$id = $this->get_translated_term($term_id, $lg);
|
406 |
+
if ($lg != $lang && $lg != $language && $id)
|
407 |
+
update_metadata('term',$this->get_translated_term($term_id, $language), '_lang-'.$lg->slug, $id);
|
408 |
+
}
|
409 |
+
}
|
410 |
+
}
|
411 |
+
|
412 |
+
// called when a category or post tag is deleted
|
413 |
+
function delete_term($term_id) {
|
414 |
+
$lang = $this->get_term_language($term_id);
|
415 |
+
if($lang) {
|
416 |
+
delete_metadata('term', $term_id, '_language' );
|
417 |
+
$listlanguages = $this->get_languages_list();
|
418 |
+
foreach ($listlanguages as $language) {
|
419 |
+
delete_metadata('term', $this->get_translated_term($term_id, $language), '_lang-'.$lang->slug); // delete links to this term
|
420 |
+
}
|
421 |
+
foreach ($listlanguages as $language) {
|
422 |
+
delete_metadata('term', $term_id, '_lang-'.$language->slug);
|
423 |
+
}
|
424 |
+
}
|
425 |
+
}
|
426 |
+
|
427 |
+
// returns all terms in the $taxonomy in the $term_language which have no translation in the $translation_language
|
428 |
+
function get_terms_not_translated($taxonomy, $term_language, $translation_language) {
|
429 |
+
$new_terms = array();
|
430 |
+
$terms = get_terms($taxonomy, 'hide_empty=0');
|
431 |
+
foreach ($terms as $term) {
|
432 |
+
$lang = $this->get_term_language($term->term_id);
|
433 |
+
if ($lang && $lang->name == $term_language->name) {
|
434 |
+
$translated_term = $this->get_translated_term($term->term_id, $translation_language);
|
435 |
+
if (!$translated_term)
|
436 |
+
$new_terms[] = $term;
|
437 |
+
}
|
438 |
+
}
|
439 |
+
return $new_terms;
|
440 |
+
}
|
441 |
+
|
442 |
+
// refresh rewrite rules if the 'page_on_front' option is modified
|
443 |
+
function update_option($option) {
|
444 |
+
global $wp_rewrite;
|
445 |
+
if ($option == 'page_on_front')
|
446 |
+
$wp_rewrite->flush_rules();
|
447 |
+
}
|
448 |
+
} // class Polylang_Admin
|
449 |
+
|
450 |
+
?>
|
base.php
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Polylang_Base {
|
4 |
+
|
5 |
+
// returns the query variables of the referer
|
6 |
+
function get_referer_vars() {
|
7 |
+
$qvars = array();
|
8 |
+
$referer = wp_get_referer();
|
9 |
+
if ($referer) {
|
10 |
+
$urlparts = parse_url($referer);
|
11 |
+
if (isset($urlparts['query'])) {
|
12 |
+
parse_str($urlparts['query'], $qvars);
|
13 |
+
}
|
14 |
+
}
|
15 |
+
return $qvars;
|
16 |
+
}
|
17 |
+
|
18 |
+
// returns the list of available languages
|
19 |
+
function get_languages_list($hide_empty = false) {
|
20 |
+
return get_terms('language', array('hide_empty'=>$hide_empty));
|
21 |
+
}
|
22 |
+
|
23 |
+
// returns the language by its id or its slug
|
24 |
+
function get_language($value) {
|
25 |
+
if (is_numeric($value))
|
26 |
+
$field = 'id';
|
27 |
+
elseif (is_string($value))
|
28 |
+
$field = 'slug';
|
29 |
+
|
30 |
+
return get_term_by($field, $value , 'language');
|
31 |
+
}
|
32 |
+
|
33 |
+
// returns the language of a post
|
34 |
+
function get_post_language($post_id) {
|
35 |
+
$lang = get_the_terms($post_id, 'language' );
|
36 |
+
return ($lang) ? reset($lang) : NULL; // there's only one language per post : first element of the array returned
|
37 |
+
}
|
38 |
+
|
39 |
+
// returns the id of the translation of a post
|
40 |
+
function get_translated_post($post_id, $language) {
|
41 |
+
return get_post_meta($post_id, '_lang-'.$language->slug, true);
|
42 |
+
}
|
43 |
+
|
44 |
+
// among the post and its translations, returns the id of the post which is in $language
|
45 |
+
function get_post($post_id, $language) {
|
46 |
+
$lang = $this->get_post_language($post_id);
|
47 |
+
return $lang->slug == $language->slug ? $post_id : $this->get_translated_post($post_id, $language);
|
48 |
+
}
|
49 |
+
|
50 |
+
// returns the language of a term
|
51 |
+
function get_term_language($term_id) {
|
52 |
+
$value = get_metadata('term', $term_id, '_language', true);
|
53 |
+
return $this->get_language($value);
|
54 |
+
}
|
55 |
+
|
56 |
+
// returns the id of the translation of a term (category or post_tag)
|
57 |
+
function get_translated_term($term_id, $language) {
|
58 |
+
return get_metadata('term', $term_id, '_lang-'.$language->slug, true);
|
59 |
+
}
|
60 |
+
|
61 |
+
} //class Polylang_Base
|
62 |
+
?>
|
edit-term-form.php
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// adds languages related fields in Edit Category and Edit Tag admin panels
|
3 |
+
// unfortunately can't reuse add-term-for.php as WordPress uses here a table instead of div :(
|
4 |
+
|
5 |
+
// displays the language select list
|
6 |
+
?>
|
7 |
+
<tr class="form-field">
|
8 |
+
<th scope="row" valign="top"><label for="lang_choice"><?php _e('Language', 'polylang');?></label></th>
|
9 |
+
<td><select name="lang_choice" id="lang_choice">
|
10 |
+
<option value="-1"></option> <?php
|
11 |
+
foreach ($listlanguages as $language) {
|
12 |
+
printf("<option value='%s' %s>%s</option>\n", $language->term_id, $language == $lang ? 'selected="selected"' : '', $language->name);
|
13 |
+
} ?>
|
14 |
+
</select><br />
|
15 |
+
<span class="description"><?php _e('Sets the language', 'polylang');?></span></td>
|
16 |
+
</tr>
|
17 |
+
|
18 |
+
<?php
|
19 |
+
// displays the translations fields
|
20 |
+
// a table in the WP table is quite ugly but why WordPress does use a table instead of div as in the add term form ?
|
21 |
+
// FIXME inline CSS
|
22 |
+
|
23 |
+
if ($lang) { // do not display translation fields if term language is not set ?>
|
24 |
+
<tr class="form-field">
|
25 |
+
<th scope="row" valign="top"><?php _e('Translations', 'polylang');?></th>
|
26 |
+
<td><table>
|
27 |
+
<thead><tr>
|
28 |
+
<th style="padding: 0px; font-weight: bold"><?php _e('Language', 'polylang');?></th>
|
29 |
+
<th style="padding: 0px; font-weight: bold"><?php _e('Translation', 'polylang');?></th>
|
30 |
+
<th style="padding: 0px; font-weight: bold"><?php _e('Edit', 'polylang');?></th>
|
31 |
+
</tr></thead>
|
32 |
+
<tbody>
|
33 |
+
<?php foreach ($listlanguages as $language) {
|
34 |
+
if ($language != $lang) {
|
35 |
+
$value = $this->get_translated_term($term_id, $language);?>
|
36 |
+
<tr><td style="padding: 0px"><?php echo $language->name;?></td>
|
37 |
+
<?php if (!$value) {
|
38 |
+
$translations = $this->get_terms_not_translated($taxonomy, $language, $lang);
|
39 |
+
if (!empty($translations)) { ?>
|
40 |
+
<td style="padding: 0px">
|
41 |
+
<select name="_lang-<?php echo $language->slug;?>" id="_lang-<?php echo $language->slug;?>">
|
42 |
+
<option value="-1"></option> <?php
|
43 |
+
foreach ($translations as $translation) { ?>
|
44 |
+
<option value="<?php echo $translation->term_id;?>"><?php echo $translation->name;?></option> <?php
|
45 |
+
} ?>
|
46 |
+
</select>
|
47 |
+
</td> <?php
|
48 |
+
}
|
49 |
+
else { ?>
|
50 |
+
<td style="padding: 0px">
|
51 |
+
</td> <?php
|
52 |
+
} ?>
|
53 |
+
<td style="padding: 0px">
|
54 |
+
<?php printf('<a href="edit-tags.php?taxonomy=%s&from_tag=%s&from_lang=%s&new_lang=%s">%s</a>',
|
55 |
+
$taxonomy, $term_id, $lang->slug, $language->slug, __('Add new','polylang')) ?>
|
56 |
+
</td> <?php
|
57 |
+
}
|
58 |
+
else { ?>
|
59 |
+
<td style="padding: 0px"><?php
|
60 |
+
$translation_id = $this->get_translated_term($term_id, $language);
|
61 |
+
$translation = get_term_by('id', $translation_id, $taxonomy);
|
62 |
+
echo $translation->name; ?>
|
63 |
+
</td>
|
64 |
+
<td style="padding: 0px">
|
65 |
+
<?php printf('<a href="edit-tags.php?action=edit&taxonomy=%S&tag_ID=%s">%s</a>', $taxonomy, $value, __('Edit','polylang')) ?>
|
66 |
+
</td> <?php
|
67 |
+
} ?>
|
68 |
+
</tr><?php
|
69 |
+
} // if (!$value)
|
70 |
+
} // foreach ?>
|
71 |
+
</tbody>
|
72 |
+
</table></td>
|
73 |
+
</tr> <?php
|
74 |
+
} // if ($lang) ?>
|
languages-form.php
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php // displays the Languages admin panel
|
2 |
+
|
3 |
+
// I don't use the custom taxonomy form provide by Wordpress because I want to modify the labels below the fields...
|
4 |
+
// There is currently (3.2) no filter to do this
|
5 |
+
|
6 |
+
// The term fields are used as follows :
|
7 |
+
// name -> language name (used only for display)
|
8 |
+
// slug -> language code (ideally 2-letters ISO 639-1 language code but I currently use it only as slug so it doesn't matter)
|
9 |
+
// description -> WordPress Locale for the language. Here if something wrong is used, the .mo files will not be loaded...
|
10 |
+
|
11 |
+
?>
|
12 |
+
<div class="wrap">
|
13 |
+
<?php screen_icon('options-general'); ?>
|
14 |
+
<h2><?php _e('Languages','polylang') ?></h2>
|
15 |
+
|
16 |
+
<div id="col-container">
|
17 |
+
<div id="col-right">
|
18 |
+
<div class="col-wrap">
|
19 |
+
|
20 |
+
<?php $list_table->display(); // displays the language list in a table ?>
|
21 |
+
|
22 |
+
</div> <!-- col-wrap -->
|
23 |
+
</div> <!-- col-right -->
|
24 |
+
|
25 |
+
<div id="col-left">
|
26 |
+
<div class="col-wrap">
|
27 |
+
|
28 |
+
<div class="form-wrap">
|
29 |
+
<h3><?php echo $action=='edit' ? _e('Edit language','polylang') : _e('Add new language','polylang'); ?></h3>
|
30 |
+
|
31 |
+
<?php // displays the add (or edit) language form
|
32 |
+
|
33 |
+
// adds noheader=true in the action url to allow using wp_redirect when processing the form ?>
|
34 |
+
<form id="add-lang" method="post" action="admin.php?page=mlang&noheader=true" class="validate">
|
35 |
+
<?php wp_nonce_field('add-lang', '_wpnonce_add-lang');
|
36 |
+
|
37 |
+
if ($action=='edit') {?>
|
38 |
+
<input type="hidden" name="action" value="update" />
|
39 |
+
<input type="hidden" name="lang" value="<?php echo $edit_lang->term_id;?>" /><?php
|
40 |
+
}
|
41 |
+
else { ?>
|
42 |
+
<input type="hidden" name="action" value="add" /><?php
|
43 |
+
}?>
|
44 |
+
|
45 |
+
<div class="form-field form-required">
|
46 |
+
<label for="name"><?php _e('Full name', 'polylang');?></label>
|
47 |
+
<input name="name" id="name" type="text" value="<?php if ($action=='edit') echo $edit_lang->name;?>" size="40" aria-required="true" />
|
48 |
+
<p><?php _e('The name is how it is displayed on your site (for example: English).', 'polylang');?></p>
|
49 |
+
</div>
|
50 |
+
|
51 |
+
<div class="form-field form-required">
|
52 |
+
<label for="description"><?php _e('Locale', 'polylang');?></label>
|
53 |
+
<input name="description" id="description" type="text" value="<?php if ($action=='edit') echo $edit_lang->description;?>" size="40" aria-required="true" />
|
54 |
+
<p><?php _e('Wordpress Locale for the language (for example: en_US). You will need to install the .mo file for this language.', 'polylang');?></p>
|
55 |
+
</div>
|
56 |
+
|
57 |
+
<div class="form-field">
|
58 |
+
<label for="slug"><?php _e('Language code', 'polylang');?></label>
|
59 |
+
<input name="slug" id="slug" type="text" value="<?php if ($action=='edit') echo $edit_lang->slug;?>" size="40" />
|
60 |
+
<p><?php _e('2-letters ISO 639-1 language code (for example: en)', 'polylang');?></p>
|
61 |
+
</div>
|
62 |
+
|
63 |
+
<?php if ($action=='edit')
|
64 |
+
submit_button(__('Update'), 'button'); // since WP 3.1
|
65 |
+
else
|
66 |
+
submit_button(__('Add new language', 'polylang'), 'button'); // since WP 3.1?>
|
67 |
+
|
68 |
+
</form>
|
69 |
+
</div> <!-- form-wrap -->
|
70 |
+
</div> <!-- col-wrap -->
|
71 |
+
</div> <!-- col-left -->
|
72 |
+
</div> <!-- col-container -->
|
73 |
+
|
74 |
+
<? // displays the Polylang options form
|
75 |
+
//FIXME one inline CSS ?>
|
76 |
+
<div class="form-wrap">
|
77 |
+
<h3><?php _e('Options','polylang');?></h3>
|
78 |
+
|
79 |
+
<form id="options-lang" method="post" action="admin.php?page=mlang" class="validate">
|
80 |
+
<?php wp_nonce_field('options-lang', '_wpnonce_options-lang');?>
|
81 |
+
<input type="hidden" name="action" value="options" />
|
82 |
+
|
83 |
+
<table class="form-table">
|
84 |
+
|
85 |
+
<tr>
|
86 |
+
<th style="width: 300px;"><label><?php printf ('<input name="rewrite" type="radio" value="0" %s /> %s',
|
87 |
+
$options['rewrite'] ? '' : 'checked="checked"', __('Keep /language/ in pretty permalinks', 'polylang')); ?></label></th>
|
88 |
+
<td><code><?php echo home_url('language/en/'); ?></code></td>
|
89 |
+
</tr>
|
90 |
+
|
91 |
+
<tr>
|
92 |
+
<th><label><?php printf ('<input name="rewrite" type="radio" value="1" %s /> %s',
|
93 |
+
$options['rewrite'] ? 'checked="checked"' : '', __('Remove /language/ in pretty permalinks', 'polylang')); ?></label></th>
|
94 |
+
<td><code><?php echo home_url('en/'); ?></code></td>
|
95 |
+
</tr>
|
96 |
+
|
97 |
+
<tr>
|
98 |
+
<th><?php _e('The front page default language is : ', 'polylang');?></th>
|
99 |
+
<td><label><?php printf('<input name="browser" type="checkbox" value="1" %s /> %s',
|
100 |
+
$options['browser'] ? 'checked="checked"' :'', __('set by the browser preference', 'polylang')) ?></label>
|
101 |
+
<label><?php _e('otherwise: ', 'polylang');?><select name="default_lang" id="default_lang">
|
102 |
+
<?php $listlanguages = $this->get_languages_list();
|
103 |
+
foreach ($listlanguages as $language) {
|
104 |
+
printf("<option value=%s %s >%s</option>\n", $language->slug, $options['default_lang'] == $language->slug ? 'selected="selected"' : '', $language->name);
|
105 |
+
} ?>
|
106 |
+
</select></label>
|
107 |
+
</td>
|
108 |
+
</tr>
|
109 |
+
|
110 |
+
</table>
|
111 |
+
|
112 |
+
<?php submit_button(); // since WP 3.1 ?>
|
113 |
+
|
114 |
+
</form>
|
115 |
+
</div> <!-- form-wrap -->
|
116 |
+
|
117 |
+
</div> <!-- wrap -->
|
list-table.php
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Thanks to Matt Van Andel (http://www.mattvanandel.com) for most of this code !
|
4 |
+
|
5 |
+
if(!class_exists('WP_List_Table')){
|
6 |
+
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
|
7 |
+
}
|
8 |
+
|
9 |
+
class Polylang_List_Table extends WP_List_Table {
|
10 |
+
function __construct() {
|
11 |
+
parent::__construct( array(
|
12 |
+
'singular' => __('Language','polylang'),
|
13 |
+
'plural' => __('Languages','polylang'),
|
14 |
+
'ajax'=> false)
|
15 |
+
);
|
16 |
+
}
|
17 |
+
|
18 |
+
function column_default( $item, $column_name){
|
19 |
+
switch($column_name){
|
20 |
+
case 'description':
|
21 |
+
case 'slug':
|
22 |
+
case 'count':
|
23 |
+
return $item[$column_name];
|
24 |
+
default:
|
25 |
+
}
|
26 |
+
}
|
27 |
+
|
28 |
+
function column_name($item){
|
29 |
+
$actions = array(
|
30 |
+
'edit' => sprintf('<a href="?page=mlang&action=edit&lang=%s">%s</a>',$item['term_id'],__('Edit','polylang')),
|
31 |
+
'delete' => '<a href="' . wp_nonce_url('?page=mlang&action=delete&noheader=true&lang=' . $item['term_id'], 'delete-lang') .'">' . __('Delete','polylang') .'</a>'
|
32 |
+
);
|
33 |
+
|
34 |
+
return $item['name'].$this->row_actions($actions);
|
35 |
+
}
|
36 |
+
|
37 |
+
function column_cb($item){
|
38 |
+
return sprintf(
|
39 |
+
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
|
40 |
+
/*$1%s*/ $this->_args['singular'],
|
41 |
+
/*$2%s*/ $item['term_id']
|
42 |
+
);
|
43 |
+
}
|
44 |
+
|
45 |
+
function get_columns(){
|
46 |
+
$columns = array(
|
47 |
+
'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
|
48 |
+
'name' => __('Full name', 'polylang'),
|
49 |
+
'description' => __('Locale', 'polylang'),
|
50 |
+
'slug' => __('Code', 'polylang'),
|
51 |
+
'count' => __('Posts', 'polylang')
|
52 |
+
);
|
53 |
+
return $columns;
|
54 |
+
}
|
55 |
+
|
56 |
+
function get_sortable_columns() {
|
57 |
+
$sortable_columns = array(
|
58 |
+
'name' => array('name',true), // sorted by name by default
|
59 |
+
'description' => array('description',false),
|
60 |
+
'slug' => array('slug',false),
|
61 |
+
'count' => array('count',false)
|
62 |
+
);
|
63 |
+
return $sortable_columns;
|
64 |
+
}
|
65 |
+
|
66 |
+
/*
|
67 |
+
function get_bulk_actions() {
|
68 |
+
return array('delete' => 'Delete');
|
69 |
+
}
|
70 |
+
*/
|
71 |
+
|
72 |
+
function prepare_items($data = array()) {
|
73 |
+
$per_page = 5; // 5 languages per page
|
74 |
+
$columns = $this->get_columns();
|
75 |
+
$hidden = array();
|
76 |
+
$sortable = $this->get_sortable_columns();
|
77 |
+
|
78 |
+
$this->_column_headers = array($columns, $hidden, $sortable);
|
79 |
+
|
80 |
+
function usort_reorder($a,$b){
|
81 |
+
$orderby = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'name'; //If no sort, default to title
|
82 |
+
$order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc'; //If no order, default to asc
|
83 |
+
$result = strcmp($a[$orderby], $b[$orderby]); //Determine sort order
|
84 |
+
return ($order==='asc') ? $result : -$result; //Send final sort direction to usort
|
85 |
+
}
|
86 |
+
usort($data, 'usort_reorder');
|
87 |
+
|
88 |
+
$current_page = $this->get_pagenum();
|
89 |
+
$total_items = count($data);
|
90 |
+
$data = array_slice($data,(($current_page-1)*$per_page),$per_page);
|
91 |
+
$this->items = $data;
|
92 |
+
|
93 |
+
$this->set_pagination_args( array(
|
94 |
+
'total_items' => $total_items, //WE have to calculate the total number of items
|
95 |
+
'per_page' => $per_page, //WE have to determine how many items to show on a page
|
96 |
+
'total_pages' => ceil($total_items/$per_page) //WE have to calculate the total number of pages
|
97 |
+
) );
|
98 |
+
}
|
99 |
+
}
|
100 |
+
?>
|
polylang-fr_FR.mo
ADDED
Binary file
|
polylang-fr_FR.po
ADDED
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
msgid ""
|
2 |
+
msgstr ""
|
3 |
+
"Project-Id-Version: polylang\n"
|
4 |
+
"Report-Msgid-Bugs-To: \n"
|
5 |
+
"POT-Creation-Date: 2011-09-20 17:23+0100\n"
|
6 |
+
"PO-Revision-Date: \n"
|
7 |
+
"Last-Translator: F. Demarle\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: nplural=n>1\n"
|
14 |
+
"X-Poedit-SourceCharset: utf-8\n"
|
15 |
+
"X-Poedit-KeywordsList: _e;__;_c\n"
|
16 |
+
"X-Poedit-Basepath: .\n"
|
17 |
+
"X-Poedit-SearchPath-0: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang\n"
|
18 |
+
|
19 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/edit-term-form.php:3
|
20 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/edit-term-form.php:20
|
21 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/admin.php:211
|
22 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/admin.php:346
|
23 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/post-metabox.php:19
|
24 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/add-term-form.php:2
|
25 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/list-table.php:12
|
26 |
+
msgid "Language"
|
27 |
+
msgstr "Langue"
|
28 |
+
|
29 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/edit-term-form.php:10
|
30 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/add-term-form.php:9
|
31 |
+
msgid "Sets the language"
|
32 |
+
msgstr "Définit la langue"
|
33 |
+
|
34 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/edit-term-form.php:17
|
35 |
+
msgid "Translations"
|
36 |
+
msgstr "Traductions"
|
37 |
+
|
38 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/edit-term-form.php:21
|
39 |
+
msgid "Translation"
|
40 |
+
msgstr "Traduction"
|
41 |
+
|
42 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/edit-term-form.php:22
|
43 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/edit-term-form.php:67
|
44 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/post-metabox.php:21
|
45 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/post-metabox.php:51
|
46 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/list-table.php:30
|
47 |
+
msgid "Edit"
|
48 |
+
msgstr "Modifier"
|
49 |
+
|
50 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/edit-term-form.php:52
|
51 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/post-metabox.php:42
|
52 |
+
msgid "Add new"
|
53 |
+
msgstr "Ajouter"
|
54 |
+
|
55 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/widget.php:5
|
56 |
+
msgid "Displays a language switcher"
|
57 |
+
msgstr "Affiche la liste des langues "
|
58 |
+
|
59 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/widget.php:6
|
60 |
+
msgid "Language Switcher"
|
61 |
+
msgstr "Liste des langues"
|
62 |
+
|
63 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/admin.php:57
|
64 |
+
msgid "Settings"
|
65 |
+
msgstr "Réglages"
|
66 |
+
|
67 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/admin.php:64
|
68 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/admin.php:253
|
69 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/admin.php:254
|
70 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/list-table.php:13
|
71 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:3
|
72 |
+
msgid "Languages"
|
73 |
+
msgstr "Langues"
|
74 |
+
|
75 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/admin.php:244
|
76 |
+
msgid "Show all languages"
|
77 |
+
msgstr "Afficher toutes les langues"
|
78 |
+
|
79 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/post-metabox.php:3
|
80 |
+
msgid "Page's language:"
|
81 |
+
msgstr "Langue de la page"
|
82 |
+
|
83 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/post-metabox.php:5
|
84 |
+
msgid "Post's language:"
|
85 |
+
msgstr "Langue de l'article"
|
86 |
+
|
87 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/post-metabox.php:16
|
88 |
+
msgid "ID of posts in other languages:"
|
89 |
+
msgstr "ID des articles dans les autres langues"
|
90 |
+
|
91 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/post-metabox.php:20
|
92 |
+
msgid "Post ID"
|
93 |
+
msgstr "ID de l'article"
|
94 |
+
|
95 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/list-table.php:31
|
96 |
+
msgid "Delete"
|
97 |
+
msgstr "Supprimer"
|
98 |
+
|
99 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/list-table.php:48
|
100 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:34
|
101 |
+
msgid "Full name"
|
102 |
+
msgstr "Nom"
|
103 |
+
|
104 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/list-table.php:49
|
105 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:40
|
106 |
+
msgid "Locale"
|
107 |
+
msgstr ""
|
108 |
+
|
109 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/list-table.php:50
|
110 |
+
msgid "Code"
|
111 |
+
msgstr "Code"
|
112 |
+
|
113 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/list-table.php:51
|
114 |
+
msgid "Posts"
|
115 |
+
msgstr "Articles"
|
116 |
+
|
117 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:19
|
118 |
+
msgid "Edit language"
|
119 |
+
msgstr "Modifier la langue"
|
120 |
+
|
121 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:21
|
122 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:54
|
123 |
+
msgid "Add new language"
|
124 |
+
msgstr "Ajouter une nouvelle langue"
|
125 |
+
|
126 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:36
|
127 |
+
msgid "The name is how it is displayed on your site (for example: English)."
|
128 |
+
msgstr "Le nom est utilisé un peu partout sur le site (par exemple : Français)"
|
129 |
+
|
130 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:42
|
131 |
+
msgid "Wordpress Locale for the language (for example: en_US). You will need to install the .mo file for this language."
|
132 |
+
msgstr "Code Wordpress pour la langue (par exemple : fr_FR). Vous aurez besoin d'installer les fichiers .mo correspondant"
|
133 |
+
|
134 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:46
|
135 |
+
msgid "Language code"
|
136 |
+
msgstr "Code de la langue"
|
137 |
+
|
138 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:48
|
139 |
+
msgid "2-letters ISO 639-1 language code (for example: en)"
|
140 |
+
msgstr "Code ISO 639-1 à 2 lettres (par exemple : fr)"
|
141 |
+
|
142 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:52
|
143 |
+
msgid "Update"
|
144 |
+
msgstr "Mettre à jour"
|
145 |
+
|
146 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:63
|
147 |
+
msgid "Options"
|
148 |
+
msgstr "Options"
|
149 |
+
|
150 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:72
|
151 |
+
msgid "Keep /language/ in pretty permalinks"
|
152 |
+
msgstr "Conserve /language/ dans les permaliens"
|
153 |
+
|
154 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:77
|
155 |
+
msgid "Remove /language/ in pretty permalinks"
|
156 |
+
msgstr "Supprime /language/ dans les permaliens"
|
157 |
+
|
158 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:81
|
159 |
+
msgid "The front page default language is : "
|
160 |
+
msgstr "La langue par défaut de la page d'accueil est :"
|
161 |
+
|
162 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:83
|
163 |
+
msgid "set by the browser preference"
|
164 |
+
msgstr "définie par les préférences du navigateur"
|
165 |
+
|
166 |
+
#: /home/fred/Documents/Web/test-flabellina.com/wordpress/wp-content/plugins/polylang/languages-form.php:84
|
167 |
+
msgid "otherwise: "
|
168 |
+
msgstr "sinon :"
|
169 |
+
|
170 |
+
#~ msgid "Title:"
|
171 |
+
#~ msgstr "Titre :"
|
172 |
+
|
polylang.php
ADDED
@@ -0,0 +1,654 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Plugin Name: Polylang
|
4 |
+
Plugin URI: http://wordpress.org/extend/plugins/polylang/
|
5 |
+
Version: 0.1
|
6 |
+
Author: F. Demarle
|
7 |
+
Description: Adds multilingual capability to Wordpress
|
8 |
+
*/
|
9 |
+
|
10 |
+
/* Copyright 2011 F. Demarle
|
11 |
+
|
12 |
+
This program is free software; you can redistribute it and/or modify
|
13 |
+
it under the terms of the GNU General Public License, version 2, as
|
14 |
+
published by the Free Software Foundation.
|
15 |
+
|
16 |
+
This program is distributed in the hope that it will be useful,
|
17 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19 |
+
GNU General Public License for more details.
|
20 |
+
|
21 |
+
You should have received a copy of the GNU General Public License
|
22 |
+
along with this program; if not, write to the Free Software
|
23 |
+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
24 |
+
*/
|
25 |
+
|
26 |
+
define('MULTILANG_VERSION', '0.1');
|
27 |
+
require_once(dirname(__FILE__).'/base.php');
|
28 |
+
require_once(dirname(__FILE__).'/admin.php');
|
29 |
+
require_once(dirname(__FILE__).'/widget.php');
|
30 |
+
|
31 |
+
class Polylang extends Polylang_Base {
|
32 |
+
var $curlang;
|
33 |
+
var $list_textdomains = array();
|
34 |
+
var $search_form_filter = false;
|
35 |
+
|
36 |
+
function __construct() {
|
37 |
+
|
38 |
+
// manages plugin activation and deactivation
|
39 |
+
register_activation_hook( __FILE__, array(&$this, 'activate') );
|
40 |
+
register_deactivation_hook( __FILE__, array(&$this, 'deactivate') );
|
41 |
+
|
42 |
+
// plugin and widget initialization
|
43 |
+
add_action('init', array(&$this,'init'));
|
44 |
+
add_action('widgets_init', array(&$this,'widgets_init'));
|
45 |
+
|
46 |
+
// rewrite rules
|
47 |
+
add_filter('rewrite_rules_array', array(&$this,'rewrite_rules_array' ));
|
48 |
+
|
49 |
+
// filters categories and post tags by language
|
50 |
+
add_filter('get_terms', array(&$this,'get_terms'), 10, 3);
|
51 |
+
|
52 |
+
if (is_admin())
|
53 |
+
new Polylang_Admin();
|
54 |
+
else {
|
55 |
+
// text domain management
|
56 |
+
add_filter('locale', array(&$this,'get_locale'));
|
57 |
+
add_filter('override_load_textdomain', array(&$this,'mofile'), 10, 3);
|
58 |
+
add_action('wp', array(&$this,'load_textdomains'));
|
59 |
+
|
60 |
+
// filters posts according to the language
|
61 |
+
add_filter('pre_get_posts', array(&$this,'pre_get_posts'));
|
62 |
+
|
63 |
+
// meta in the html head section
|
64 |
+
remove_action('wp_head', 'rel_canonical');
|
65 |
+
add_action('wp_head', array(&$this,'wp_head'));
|
66 |
+
|
67 |
+
// prevents redirection of the homepage
|
68 |
+
add_filter('redirect_canonical', array(&$this,'redirect_canonical'), 10, 2);
|
69 |
+
|
70 |
+
// adds javascript at the end of the document
|
71 |
+
add_action('wp_print_footer_scripts', array(&$this,'wp_print_footer_scripts'));
|
72 |
+
|
73 |
+
// adds the language information in the search form
|
74 |
+
add_filter('get_search_form', array(&$this,'get_search_form'));
|
75 |
+
|
76 |
+
// filters the pages according to the current language
|
77 |
+
add_filter('get_pages', array(&$this,'get_pages'), 10, 2);
|
78 |
+
|
79 |
+
// rewrites feed links to filter them by language
|
80 |
+
add_filter('feed_link', array(&$this,'feed_link'), 10, 2);
|
81 |
+
|
82 |
+
// rewrites archives links to filter them by language
|
83 |
+
add_filter('getarchives_join', array(&$this,'posts_join'));
|
84 |
+
add_filter('getarchives_where', array(&$this,'posts_where'));
|
85 |
+
add_filter('get_archives_link', array(&$this,'get_archives_link'));
|
86 |
+
|
87 |
+
// rewrites next and previous post links to filter them by language
|
88 |
+
add_filter('get_previous_post_join', array(&$this,'posts_join'));
|
89 |
+
add_filter('get_next_post_join', array(&$this,'posts_join'));
|
90 |
+
add_filter('get_previous_post_where', array(&$this,'posts_where'));
|
91 |
+
add_filter('get_next_post_where', array(&$this,'posts_where'));
|
92 |
+
|
93 |
+
// allows a new value for the 'show' parameter to display the homepage url according to the current language
|
94 |
+
add_filter('bloginfo_url', array(&$this,'bloginfo_url'), 10, 2);
|
95 |
+
|
96 |
+
// Template tags
|
97 |
+
add_action('the_languages', array(&$this,'the_languages'));
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
// plugin activation
|
102 |
+
function activate() {
|
103 |
+
// create the termmeta table - not provided by WP by default - if it does not already exists
|
104 |
+
// uses exactly the same model as other meta tables to be able to use access functions provided by WP
|
105 |
+
global $wpdb;
|
106 |
+
$charset_collate = '';
|
107 |
+
if ( ! empty($wpdb->charset) )
|
108 |
+
$charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
|
109 |
+
if ( ! empty($wpdb->collate) )
|
110 |
+
$charset_collate .= " COLLATE $wpdb->collate";
|
111 |
+
|
112 |
+
$table = $wpdb->prefix . 'termmeta';
|
113 |
+
|
114 |
+
$tables = $wpdb->get_results("show tables like '$table'");
|
115 |
+
if (!count($tables))
|
116 |
+
$wpdb->query("CREATE TABLE $table (
|
117 |
+
meta_id bigint(20) unsigned NOT NULL auto_increment,
|
118 |
+
term_id bigint(20) unsigned NOT NULL default '0',
|
119 |
+
meta_key varchar(255) default NULL,
|
120 |
+
meta_value longtext,
|
121 |
+
PRIMARY KEY (meta_id),
|
122 |
+
KEY term_id (term_id),
|
123 |
+
KEY meta_key (meta_key)
|
124 |
+
) $charset_collate;");
|
125 |
+
|
126 |
+
// codex tells to use the init action to call register_taxonomy but I need it now for my rewrite rules
|
127 |
+
register_taxonomy('language', 'post', array('label' => false, 'query_var'=>'lang'));
|
128 |
+
|
129 |
+
// defines default values for options in case this is the first installation
|
130 |
+
$options = get_option('polylang');
|
131 |
+
if (!$options) {
|
132 |
+
$options['browser'] = 1; // default language for the front page is set by browser preference
|
133 |
+
$options['rewrite'] = 0; // do not remove /language/ in permalinks
|
134 |
+
}
|
135 |
+
$options['version'] = MULTILANG_VERSION; // do not manage versions yet but prepare for it
|
136 |
+
update_option('polylang', $options);
|
137 |
+
|
138 |
+
// add our rewrite rules
|
139 |
+
global $wp_rewrite;
|
140 |
+
$wp_rewrite->flush_rules();
|
141 |
+
}
|
142 |
+
|
143 |
+
// plugin deactivation
|
144 |
+
function deactivate() {
|
145 |
+
// delete our rewrite rules
|
146 |
+
remove_filter('rewrite_rules_array', array(&$this,'rewrite_rules_array' ));
|
147 |
+
global $wp_rewrite;
|
148 |
+
$wp_rewrite->flush_rules();
|
149 |
+
}
|
150 |
+
|
151 |
+
// some initialization
|
152 |
+
function init() {
|
153 |
+
global $wpdb;
|
154 |
+
$wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
|
155 |
+
|
156 |
+
// registers the language taxonomy
|
157 |
+
// codex: use the init action to call this function
|
158 |
+
register_taxonomy('language', 'post', array(
|
159 |
+
'label' => false,
|
160 |
+
'query_var'=>'lang',
|
161 |
+
'update_count_callback' => '_update_post_term_count'));
|
162 |
+
|
163 |
+
// optionaly removes 'language' in permalinks so that we get http://www.myblog/en/ instead of http://www.myblog/language/en/
|
164 |
+
// the simple line of code is inspired by the WP No Category Base plugin : http://wordpresssupplies.com/wordpress-plugins/no-category-base/
|
165 |
+
$options = get_option('polylang');
|
166 |
+
if ($options['rewrite']) {
|
167 |
+
global $wp_rewrite;
|
168 |
+
$wp_rewrite->extra_permastructs['language'][0] = '%language%';
|
169 |
+
}
|
170 |
+
|
171 |
+
load_plugin_textdomain('polylang', false, dirname(plugin_basename( __FILE__ ))); // plugin i18n
|
172 |
+
}
|
173 |
+
|
174 |
+
// registers our widget
|
175 |
+
function widgets_init() {
|
176 |
+
register_widget('Polylang_Widget');
|
177 |
+
}
|
178 |
+
|
179 |
+
// rewrites rules if pretty permalinks are used
|
180 |
+
function rewrite_rules_array($rules) {
|
181 |
+
$options = get_option('polylang');
|
182 |
+
$newrules = array();
|
183 |
+
$listlanguages = $this->get_languages_list();
|
184 |
+
|
185 |
+
// modifies the rules created by WordPress when '/language/' is removed in permalinks
|
186 |
+
if ($options['rewrite']) {
|
187 |
+
foreach ($listlanguages as $language) {
|
188 |
+
$newrules[$language->slug.'/feed/(feed|rdf|rss|rss2|atom)/?$'] = 'index.php?lang='.$language->slug.'&feed=$matches[1]';
|
189 |
+
$newrules[$language->slug.'/(feed|rdf|rss|rss2|atom)/?$'] = 'index.php?lang='.$language->slug.'&feed=$matches[1]';
|
190 |
+
$newrules[$language->slug.'/page/?([0-9]{1,})/?$'] = 'index.php?lang='.$language->slug.'&paged=$matches[1]';
|
191 |
+
$newrules[$language->slug.'/?$'] = 'index.php?lang='.$language->slug;
|
192 |
+
}
|
193 |
+
unset($rules['([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$']); // => index.php?lang=$matches[1]&feed=$matches[2]
|
194 |
+
unset($rules['([^/]+)/(feed|rdf|rss|rss2|atom)/?$']); // => index.php?lang=$matches[1]&feed=$matches[2]
|
195 |
+
unset($rules['([^/]+)/page/?([0-9]{1,})/?$']); // => index.php?lang=$matches[1]&paged=$matches[2]
|
196 |
+
unset($rules['([^/]+)/?$']); // => index.php?lang=$matches[1]
|
197 |
+
}
|
198 |
+
|
199 |
+
$options['rewrite'] ? $base = '' : $base = 'language/';
|
200 |
+
|
201 |
+
// rewrite rules for comments feed filtered by language
|
202 |
+
foreach ($listlanguages as $language) {
|
203 |
+
$newrules[$base.$language->slug.'/comments/feed/(feed|rdf|rss|rss2|atom)/?$'] = 'index.php?lang='.$language->slug.'&feed=$matches[1]&withcomments=1';
|
204 |
+
$newrules[$base.$language->slug.'/comments/(feed|rdf|rss|rss2|atom)/?$'] = 'index.php?lang='.$language->slug.'&feed=$matches[1]&withcomments=1';
|
205 |
+
}
|
206 |
+
unset($rules['comments/feed/(feed|rdf|rss|rss2|atom)/?$']); // => index.php?&feed=$matches[1]&withcomments=1
|
207 |
+
unset($rules['comments/(feed|rdf|rss|rss2|atom)/?$']); // => index.php?&feed=$matches[1]&withcomments=1
|
208 |
+
|
209 |
+
// rewrite rules for archives filtered by language
|
210 |
+
foreach ($rules as $key => $rule) {
|
211 |
+
$is_archive = strpos($rule, 'year=') && !(
|
212 |
+
strpos($rule, 'p=') ||
|
213 |
+
strpos($rule, 'name=') ||
|
214 |
+
strpos($rule, 'page=') ||
|
215 |
+
strpos($rule, 'cpage=') );
|
216 |
+
|
217 |
+
if ($is_archive) {
|
218 |
+
foreach ($listlanguages as $language)
|
219 |
+
$newrules[$base.$language->slug.'/'.$key] = str_replace('?', '?lang='.$language->slug.'&', $rule);
|
220 |
+
|
221 |
+
unset($rules[$key]); // now useless
|
222 |
+
}
|
223 |
+
}
|
224 |
+
|
225 |
+
return $newrules + $rules;
|
226 |
+
}
|
227 |
+
|
228 |
+
// filters categories and post tags by language when needed (both in admin panels and frontend
|
229 |
+
function get_terms($terms, $taxonomies, $args) {
|
230 |
+
if (is_admin()) {
|
231 |
+
$screen = get_current_screen();
|
232 |
+
if (isset($screen))
|
233 |
+
// does nothing in the Categories, Post tags, Languages an Posts* admin panels
|
234 |
+
if ($screen->base == 'edit-tags' || $screen->base == 'toplevel_page_mlang' || $screen->base == 'edit')
|
235 |
+
return $terms;
|
236 |
+
|
237 |
+
// *FIXME I want all categories in the dropdown list and only the ones in the right language in the inline edit
|
238 |
+
// It seems that I need javascript to get the post_id as inline edit data are manipulated in inline-edit-post.js
|
239 |
+
}
|
240 |
+
|
241 |
+
// does nothing except on categories and post tags
|
242 |
+
if ( !in_array('category', $taxonomies) && !in_array('post_tag', $taxonomies) )
|
243 |
+
return $terms;
|
244 |
+
|
245 |
+
$lang = $this->get_current_language();
|
246 |
+
if ($lang) {
|
247 |
+
$slug = $lang->slug;
|
248 |
+
foreach($terms as $key => $term) {
|
249 |
+
$lang = $this->get_term_language($term->term_id);
|
250 |
+
if (!$lang || ($lang->slug) != $slug)
|
251 |
+
unset($terms[$key]); // remove terms with no language set or different language
|
252 |
+
}
|
253 |
+
}
|
254 |
+
return $terms;
|
255 |
+
}
|
256 |
+
|
257 |
+
// returns the language according to browser preference or the default language
|
258 |
+
function get_preferred_language() {
|
259 |
+
// check first is the user was already browsing this site
|
260 |
+
if ($lang = $this->get_language($_COOKIE['wordpress_polylang']))
|
261 |
+
return $lang;
|
262 |
+
|
263 |
+
// sets the browsing language according to the browser preferences
|
264 |
+
// code adapted from http://www.thefutureoftheweb.com/blog/use-accept-language-header
|
265 |
+
$options = get_option('polylang');
|
266 |
+
if ($options['browser']) {
|
267 |
+
$accept_langs = array();
|
268 |
+
|
269 |
+
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
|
270 |
+
// break up string into pieces (languages and q factors)
|
271 |
+
preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $lang_parse);
|
272 |
+
|
273 |
+
if (count($lang_parse[1])) {
|
274 |
+
$accept_langs = array_combine($lang_parse[1], $lang_parse[4]); // create a list like "en" => 0.8
|
275 |
+
// set default to 1 for any without q factor
|
276 |
+
foreach ($accept_langs as $accept_lang => $val) {
|
277 |
+
if ($val === '') $accept_langs[$accept_lang] = 1;
|
278 |
+
}
|
279 |
+
arsort($accept_langs, SORT_NUMERIC); // sort list based on value
|
280 |
+
}
|
281 |
+
}
|
282 |
+
|
283 |
+
// looks through sorted list and use first one that matches our language list
|
284 |
+
$listlanguages = $this->get_languages_list(true); // hides languages with no post
|
285 |
+
foreach ($accept_langs as $accept_lang => $val) {
|
286 |
+
foreach ($listlanguages as $language) {
|
287 |
+
if (strpos($accept_lang, $language->slug) === 0 && !isset($pref_lang)) {
|
288 |
+
$pref_lang = $this->get_language($language->slug);
|
289 |
+
}
|
290 |
+
}
|
291 |
+
}
|
292 |
+
} // options['browser']
|
293 |
+
|
294 |
+
// either there is no preference in the browser or preferences does not match our language list or it is requested not to use the browser preference
|
295 |
+
if (!isset($pref_lang))
|
296 |
+
$pref_lang = $this->get_language($options['default_lang']);
|
297 |
+
|
298 |
+
return $pref_lang;
|
299 |
+
}
|
300 |
+
|
301 |
+
// returns the current language
|
302 |
+
function get_current_language() {
|
303 |
+
global $post_ID;
|
304 |
+
|
305 |
+
if($this->curlang)
|
306 |
+
return $this->curlang;
|
307 |
+
|
308 |
+
if (is_404())
|
309 |
+
return $this->get_preferred_language();
|
310 |
+
|
311 |
+
if (is_admin()) {
|
312 |
+
if (isset($post_ID))
|
313 |
+
$lang = $this->get_post_language($post_ID);
|
314 |
+
|
315 |
+
// trick to get the post number in the Post Tags metabox in the Edit Post screen (as $post_ID not defined)
|
316 |
+
$qvars = $this->get_referer_vars();
|
317 |
+
if (isset($qvars['post']))
|
318 |
+
$lang = $this->get_post_language($qvars['post']);
|
319 |
+
}
|
320 |
+
else {
|
321 |
+
$var = get_query_var('lang');
|
322 |
+
if ($var)
|
323 |
+
$lang = $this->get_language($var);
|
324 |
+
else {
|
325 |
+
$var = get_queried_object_id();
|
326 |
+
if ($var && is_single() || is_page())
|
327 |
+
$lang = $this->get_post_language($var);
|
328 |
+
else {
|
329 |
+
$var = get_query_var('cat');
|
330 |
+
if ($var)
|
331 |
+
$lang = $this->get_term_language($var);
|
332 |
+
else {
|
333 |
+
$var = get_query_var('tag_id');
|
334 |
+
if ($var)
|
335 |
+
$lang = $this->get_term_language($var);
|
336 |
+
}
|
337 |
+
}
|
338 |
+
}
|
339 |
+
}
|
340 |
+
|
341 |
+
return (isset($lang)) ? $lang : NULL;
|
342 |
+
}
|
343 |
+
|
344 |
+
// returns the locale based on current language
|
345 |
+
function get_locale($locale) {
|
346 |
+
if ($this->curlang)
|
347 |
+
$locale = $this->curlang->description;
|
348 |
+
return $locale;
|
349 |
+
}
|
350 |
+
|
351 |
+
// saves all text domains in a table for later usage
|
352 |
+
function mofile( $bool, $domain, $mofile) {
|
353 |
+
$this->list_textdomains[] = array ('mo' => $mofile, 'domain' => $domain);
|
354 |
+
return true; // prevents WP loading text domains as we will load them all later
|
355 |
+
}
|
356 |
+
|
357 |
+
// NOTE : I believe there are two ways for a plugin to force the WP language
|
358 |
+
// as done by xili_language and here : load text domains and reinitialize wp_locale with the action 'wp'
|
359 |
+
// as done by qtranslate : define the locale with the action 'plugins_loaded', but in this case, the language must be specified in the url.
|
360 |
+
function load_textdomains() {
|
361 |
+
// sets the current language and set a cookie to remember it
|
362 |
+
if ($this->curlang = $this->get_current_language())
|
363 |
+
setcookie('wordpress_polylang', $this->curlang->slug, time() + 31536000 /* 1 year */, COOKIEPATH, COOKIE_DOMAIN);
|
364 |
+
|
365 |
+
// our override_load_textdomain has done its job. let's remove it before calling load_textdomain
|
366 |
+
remove_filter('override_load_textdomain', array(&$this,'mofile'));
|
367 |
+
|
368 |
+
// now we can load text domains with the right language
|
369 |
+
foreach ($this->list_textdomains as $textdomain) {
|
370 |
+
$mo = preg_replace('#(.+)\/[a-zA-Z_]+\.mo$#', '$1/'.get_locale().'.mo', $textdomain['mo']); // replace the .mo file
|
371 |
+
load_textdomain( $textdomain['domain'], $mo);
|
372 |
+
}
|
373 |
+
|
374 |
+
global $wp_locale;
|
375 |
+
$wp_locale->init(); // reinitializes wp_locale for weekdays and months
|
376 |
+
}
|
377 |
+
|
378 |
+
// filters posts according to the language
|
379 |
+
function pre_get_posts($query) {
|
380 |
+
|
381 |
+
if (empty($query->query)) {
|
382 |
+
|
383 |
+
// sets the language according to browser preference or default language
|
384 |
+
$this->curlang = $this->get_preferred_language();
|
385 |
+
|
386 |
+
// redirect to the right translated page in case a static page is used as front page
|
387 |
+
$post_id = get_option('page_on_front');
|
388 |
+
if (isset($this->curlang) && $post_id) {
|
389 |
+
// a static page is used as front page
|
390 |
+
$language = $this->get_post_language($post_id);
|
391 |
+
if ($language->slug != $this->curlang->slug) {
|
392 |
+
// but the one defined in the "Reading Settings" panel is not in the right language, so let's redirect to the right one
|
393 |
+
$link_id = $this->get_translated_post($post_id, $this->curlang);
|
394 |
+
if ($link_id) {
|
395 |
+
$url = _get_page_link($link_id);
|
396 |
+
wp_redirect($url);
|
397 |
+
exit;
|
398 |
+
}
|
399 |
+
}
|
400 |
+
}
|
401 |
+
}
|
402 |
+
|
403 |
+
// filters recent posts to the current language
|
404 |
+
if ($query->is_home && $this->curlang)
|
405 |
+
$query->set('lang', $this->curlang->slug);
|
406 |
+
|
407 |
+
// remove pages from archives when the language is set
|
408 |
+
$qvars = $query->query_vars;
|
409 |
+
if (isset($qvars['m']) && isset($qvars['lang']))
|
410 |
+
$query->set('post_type', 'post');
|
411 |
+
}
|
412 |
+
|
413 |
+
function wp_head() {
|
414 |
+
// modifies the canonical link to the homepage
|
415 |
+
if (is_singular()) {
|
416 |
+
global $wp_the_query;
|
417 |
+
|
418 |
+
if ($id = $wp_the_query->get_queried_object_id()) {
|
419 |
+
if (is_page())
|
420 |
+
$link = _get_page_link($id); // ignores page_on_front unlike get_permalink
|
421 |
+
else
|
422 |
+
$link = get_permalink ($id);
|
423 |
+
echo "<link rel='canonical' href='$link' />\n";
|
424 |
+
}
|
425 |
+
}
|
426 |
+
|
427 |
+
// outputs references to translated pages (if exists) in the html head section
|
428 |
+
$listlanguages = $this->get_languages_list();
|
429 |
+
foreach ($listlanguages as $language) {
|
430 |
+
if ($language->slug != $this->curlang->slug) {
|
431 |
+
$url = $this->get_translation_url($language);
|
432 |
+
if ($url)
|
433 |
+
echo "<link hreflang='$language->slug' href='$url' rel='alternate' />\n";
|
434 |
+
}
|
435 |
+
}
|
436 |
+
}
|
437 |
+
|
438 |
+
// prevents redirection of the homepage
|
439 |
+
function redirect_canonical($redirect_url, $requested_url) {
|
440 |
+
if($requested_url == _get_page_link(get_option('page_on_front')))
|
441 |
+
return false;
|
442 |
+
return $redirect_url;
|
443 |
+
}
|
444 |
+
|
445 |
+
// adds some javascript workaround knowing it's not perfect...
|
446 |
+
function wp_print_footer_scripts() {
|
447 |
+
if ($this->curlang) {
|
448 |
+
$js = "<script type='text/javascript'>";
|
449 |
+
|
450 |
+
// modifies links to the homepage to filter by the right language
|
451 |
+
// since filtering home_url breaks things in the core and filtering bloginfo_url is not enough if the template uses home_url()
|
452 |
+
$url = rtrim(home_url(), '/');
|
453 |
+
|
454 |
+
if ($page = get_option('page_on_front'))
|
455 |
+
$newurl = _get_page_link($this->get_post($page, $this->curlang));
|
456 |
+
else
|
457 |
+
$newurl = get_term_link($this->curlang->slug, 'language');
|
458 |
+
|
459 |
+
$js .= "var e = document.getElementsByTagName('a');
|
460 |
+
for (var i = 0; i < e.length; i++) {
|
461 |
+
var href = e[i].href;
|
462 |
+
if (href == '$url' || href == '$url/') {
|
463 |
+
e[i].href = '$newurl';
|
464 |
+
}
|
465 |
+
}";
|
466 |
+
|
467 |
+
// modifies the search form since filtering get_search_form won't work if the template uses searchform.php
|
468 |
+
// don't use directly e[0] just in case there is somewhere else an element named 's'
|
469 |
+
// check before if the hidden input has not already been introduced by get_search_form
|
470 |
+
if (!$this->search_form_filter) {
|
471 |
+
$lang = $this->curlang->slug;
|
472 |
+
$js .= "e = document.getElementsByName('s');
|
473 |
+
for (i = 0; i < e.length; i++) {
|
474 |
+
if (e[i] == '[object HTMLInputElement]') {
|
475 |
+
var ih = document.createElement('input');
|
476 |
+
ih.type = 'hidden';
|
477 |
+
ih.name = 'lang';
|
478 |
+
ih.value = '$lang';
|
479 |
+
e[i].parentNode.appendChild(ih);
|
480 |
+
}
|
481 |
+
}";
|
482 |
+
}
|
483 |
+
|
484 |
+
$js .= "</script>";
|
485 |
+
echo $js;
|
486 |
+
}
|
487 |
+
}
|
488 |
+
|
489 |
+
// adds the language information in the search form
|
490 |
+
// FIXME does not work if searchform.php is used
|
491 |
+
function get_search_form($form) {
|
492 |
+
if ($form) {
|
493 |
+
$this->search_form_filter = true;
|
494 |
+
$form = str_replace('</form>', '<input type="hidden" name="lang" value="'.$this->curlang->slug.'" /></form>', $form);
|
495 |
+
}
|
496 |
+
return $form;
|
497 |
+
}
|
498 |
+
|
499 |
+
// filters the pages according to the current language
|
500 |
+
function get_pages($pages, $r) {
|
501 |
+
if (isset($this->curlang)) {
|
502 |
+
foreach ($pages as $key => $page) {
|
503 |
+
$lang = $this->get_post_language($page->ID);
|
504 |
+
if ($this->curlang != $lang)
|
505 |
+
unset($pages[$key]);
|
506 |
+
}
|
507 |
+
}
|
508 |
+
return $pages;
|
509 |
+
}
|
510 |
+
|
511 |
+
// Modifies the feed link to add the language parameter
|
512 |
+
// FIXME should be an option to do this ?
|
513 |
+
function feed_link($url, $feed) {
|
514 |
+
global $wp_rewrite;
|
515 |
+
$options = get_option('polylang');
|
516 |
+
|
517 |
+
if ($this->curlang) {
|
518 |
+
if ($wp_rewrite->using_permalinks()) {
|
519 |
+
$home = home_url();
|
520 |
+
$options['rewrite'] ? $base = '/' : $base = '/language/';
|
521 |
+
$url = str_replace($home, $home.$base.$this->curlang->slug, $url);
|
522 |
+
}
|
523 |
+
else {
|
524 |
+
if ($feed)
|
525 |
+
$url = home_url('?lang='.$this->curlang->slug.'&feed='.$feed);
|
526 |
+
}
|
527 |
+
}
|
528 |
+
return $url;
|
529 |
+
}
|
530 |
+
|
531 |
+
// modifies the sql request for wp_get_archives an get_adjacent_post to filter by the current language
|
532 |
+
function posts_join($sql) {
|
533 |
+
if ($this->curlang) {
|
534 |
+
global $wpdb;
|
535 |
+
$sql .= " INNER JOIN $wpdb->term_relationships ON object_id = ID";
|
536 |
+
}
|
537 |
+
return $sql;
|
538 |
+
}
|
539 |
+
|
540 |
+
// modifies the sql request for wp_get_archives and get_adjacent_post to filter by the current language
|
541 |
+
function posts_where($sql) {
|
542 |
+
if ($this->curlang) {
|
543 |
+
global $wpdb;
|
544 |
+
$lang_id = $this->curlang->term_id;
|
545 |
+
$sql .= " AND term_taxonomy_id = $lang_id";
|
546 |
+
}
|
547 |
+
return $sql;
|
548 |
+
}
|
549 |
+
|
550 |
+
// modifies the archives link to add the language parameter
|
551 |
+
function get_archives_link($link_html) {
|
552 |
+
if ($this->curlang) {
|
553 |
+
global $wp_rewrite;
|
554 |
+
$options = get_option('polylang');
|
555 |
+
$home = home_url();
|
556 |
+
if ($wp_rewrite->using_permalinks()) {
|
557 |
+
$options['rewrite'] ? $base = '/' : $base = '/language/';
|
558 |
+
$link_html = str_replace($home, $home.$base.$this->curlang->slug, $link_html);
|
559 |
+
}
|
560 |
+
else
|
561 |
+
$link_html = str_replace($home.'/?', $home.'/?lang='.$this->curlang->slug.'&', $link_html);
|
562 |
+
}
|
563 |
+
return $link_html;
|
564 |
+
}
|
565 |
+
|
566 |
+
// returns the url of the translation (if exists) of the current page
|
567 |
+
function get_translation_url($language) {
|
568 |
+
|
569 |
+
if ( is_single()) {
|
570 |
+
$id = $this->get_post(get_the_ID(), $language);
|
571 |
+
if ($id)
|
572 |
+
$url = get_permalink($id);
|
573 |
+
}
|
574 |
+
|
575 |
+
elseif ( is_page() ) {
|
576 |
+
$id = $this->get_post(get_the_ID(), $language);
|
577 |
+
if ($id)
|
578 |
+
$url = _get_page_link($id);
|
579 |
+
}
|
580 |
+
|
581 |
+
elseif ( is_category() || is_tag() ) {
|
582 |
+
$term = get_queried_object();
|
583 |
+
$term_id = $term->term_id;
|
584 |
+
$taxonomy = $term->taxonomy;
|
585 |
+
$lang = $this->get_term_language($term_id);
|
586 |
+
|
587 |
+
if ($language->slug == $lang->slug)
|
588 |
+
$url = get_term_link($term->slug, $taxonomy); // self link
|
589 |
+
else {
|
590 |
+
$link_id = $this->get_translated_term($term_id, $language);
|
591 |
+
if ($link_id) {
|
592 |
+
$term = get_term($link_id,$taxonomy); // We need the slug for get_term_link
|
593 |
+
$url = get_term_link($term->slug, $taxonomy);
|
594 |
+
}
|
595 |
+
}
|
596 |
+
}
|
597 |
+
|
598 |
+
// FIXME for date links, if I simply modify the lang query, there is a risk that there is no posts (if all are not translated at this date)
|
599 |
+
// do nothing for now
|
600 |
+
elseif ( is_year() ) {
|
601 |
+
}
|
602 |
+
|
603 |
+
elseif ( is_month() ) {
|
604 |
+
}
|
605 |
+
|
606 |
+
elseif (is_home() || is_tax('language') )
|
607 |
+
$url = get_term_link($language->slug, 'language');
|
608 |
+
|
609 |
+
return isset($url) ? $url : null;
|
610 |
+
}
|
611 |
+
|
612 |
+
// returns the home url in the right language
|
613 |
+
function get_home_url($language) {
|
614 |
+
$post_id = get_option('page_on_front');
|
615 |
+
if ($post_id) {
|
616 |
+
// a static page is used as front page
|
617 |
+
$id = $this->get_post($post_id, $language);
|
618 |
+
if($id)
|
619 |
+
$url = _get_page_link($id);
|
620 |
+
}
|
621 |
+
return isset($url) ? $url : get_term_link($language->slug, 'language');
|
622 |
+
}
|
623 |
+
|
624 |
+
// adds 'lang_url' as possible value to the 'show' parameter of bloginfo to display the home url in the correct language
|
625 |
+
// FIXME not tested
|
626 |
+
function bloginfo_url($output, $show) {
|
627 |
+
if ($show == 'lang_url' && $this->curlang) {
|
628 |
+
$url = $this->get_home_url($this->curlang);
|
629 |
+
$output = isset($url) ? $url : home_url('/');
|
630 |
+
}
|
631 |
+
return $output;
|
632 |
+
}
|
633 |
+
|
634 |
+
// Template tag : Displays links to the current page in other languages
|
635 |
+
// Usage : do_action('the_languages');
|
636 |
+
function the_languages() {
|
637 |
+
$listlanguages = $this->get_languages_list(true); // hides languages with no posts
|
638 |
+
$output = "<ul>\n";
|
639 |
+
foreach ($listlanguages as $language) {
|
640 |
+
$url = $this->get_translation_url($language);
|
641 |
+
if (!isset($url))
|
642 |
+
$url = $this->get_home_url($language); // if the page is not translated, link to the home page
|
643 |
+
$output .= "<li><a href='$url'>".$language->name."</a></li>\n";
|
644 |
+
}
|
645 |
+
$output .= "</ul>\n";
|
646 |
+
echo $output;
|
647 |
+
}
|
648 |
+
|
649 |
+
} // class Polylang
|
650 |
+
|
651 |
+
if (class_exists("Polylang"))
|
652 |
+
new Polylang();
|
653 |
+
|
654 |
+
?>
|
post-metabox.php
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php // allowing to choose the post's language ?>
|
2 |
+
<p><em><?php $post_type == 'page' ? _e('Page\'s language:', 'polylang') : _e('Post\'s language:', 'polylang');?></em></p>
|
3 |
+
<p><?php
|
4 |
+
$listlanguages = $this->get_languages_list();
|
5 |
+
foreach ($listlanguages as $language) {
|
6 |
+
printf('<input type="radio" name="lang_choice" value="%s" id="%s" %s />', $language->slug, $language->slug, $language == $lang ? 'checked="checked"' : '');
|
7 |
+
printf('<label for %s"> %s</label><br />', $language->slug, $language->name);
|
8 |
+
} ?>
|
9 |
+
</p>
|
10 |
+
|
11 |
+
<?php // allowing to determine the linked posts
|
12 |
+
// FIXME inline CSS ! ?>
|
13 |
+
<p><em><?php _e('ID of posts in other languages:', 'polylang');?></em></p>
|
14 |
+
<table style="width: 100%; text-align: left; font-size: 11px; margin: 0 6px;">
|
15 |
+
<thead><tr>
|
16 |
+
<th><?php _e('Language', 'polylang');?></th>
|
17 |
+
<th><?php _e('Post ID', 'polylang');?></th>
|
18 |
+
<th><?php _e('Edit', 'polylang');?></th>
|
19 |
+
</tr></thead>
|
20 |
+
|
21 |
+
<tbody>
|
22 |
+
<?php foreach ($listlanguages as $language) {
|
23 |
+
if ($language != $lang) {
|
24 |
+
$value = $this->get_translated_post($post_ID, $language);
|
25 |
+
if (isset($_GET['from_post']))
|
26 |
+
$value = $this->get_post($_GET['from_post'], $language); ?>
|
27 |
+
<tr>
|
28 |
+
<td style="font-size: 11px;"><?php echo $language->name;?></td>
|
29 |
+
<td><input name="<?php echo $language->slug;?>" id="<?php echo $language->slug;?>" type="text" value="<?php echo $value;?>" size="6"/></td><?php
|
30 |
+
if ($lang) {
|
31 |
+
$link = $value ?
|
32 |
+
sprintf('<a href="post.php?action=edit&post=%s">%s</a>', $value, __('Edit','polylang')) :
|
33 |
+
sprintf('<a href="post-new.php?from_post=%s&new_lang=%s">%s</a>',$post_ID, $language->slug, __('Add new','polylang')); ?>
|
34 |
+
<td style="font-size: 11px;"><?php echo $link ?><td><?php
|
35 |
+
}?>
|
36 |
+
</tr><?php
|
37 |
+
}
|
38 |
+
} ?>
|
39 |
+
</tbody>
|
40 |
+
</table>
|
readme.txt
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== Plugin Name ===
|
2 |
+
Contributors: Chouby
|
3 |
+
Tags: bilingual, multilingual, language, i18n, l10n, international
|
4 |
+
Requires at least: 3.1
|
5 |
+
Tested up to: 3.2.1
|
6 |
+
Stable tag: 0.1
|
7 |
+
|
8 |
+
Adds multilingual support to WordPress.
|
9 |
+
|
10 |
+
== Description ==
|
11 |
+
|
12 |
+
This plugin will not make the translation for you ! I you are looking for automatic translation, look for another plugin. Unlike some other plugins, Polylang does not integrate professionnal translation.
|
13 |
+
|
14 |
+
You write posts, pages and create categories and post tags as usual. You just have to define the language and it will be displayed only if the visitor is browsing this language. Optionaly, you can mark each post, page, category and post tag to be the translation of another one. Thus if, for example, your visitor is reading a post, it can switch (using the simple language switcher widget provided with the plugin) to the same post translated in another language (provided that you translated it !). There is no limit for the number of language.
|
15 |
+
|
16 |
+
Of course, the plugin itself is internationalized but is currently available only in English and in French.
|
17 |
+
|
18 |
+
Unlike some other plugins, if you deactivate Polylang, your blog will go on working as smoothly as possible. All your posts, pages, category and post tags would be accessible without language filter.
|
19 |
+
|
20 |
+
The tests have been made with WordPress 3.2.1 and with the Twenty Eleven theme (see FAQ). Although I did not test previous versions, I see no reason why it should not work with WordPress 3.1. However the plugin should not work with WordPress 3.0.5 and lower. Multisite has not been tested.
|
21 |
+
|
22 |
+
This is the initial version. Although I tested it carefully, there are probably still bugs. There are also lacking features. Remember that it is always better to test locally (or on a test server) that a plugin is fitting your needs before going in production. Note also that you must deactivate other multilingual plugins before activating Polylang. Otherwise, you may get unexpected results !
|
23 |
+
|
24 |
+
== Installation ==
|
25 |
+
|
26 |
+
1. Download the plugin
|
27 |
+
1. Extract all the files.
|
28 |
+
1. Upload everything (keeping the directory structure) to the `/wp-content/plugins/` directory.
|
29 |
+
1. Activate the plugin through the 'Plugins' menu in WordPress.
|
30 |
+
1. Add the 'language switcher' Widget to let your visitors switch the language.
|
31 |
+
1. Go to the languages settings page and create the languages you need
|
32 |
+
1. Upload corresponding .mo files in WordPress languages directory (no need for English). You can download it from [here](http://svn.automattic.com/wordpress-i18n/). Take care that your theme must come with the corresponding .mo file too.
|
33 |
+
|
34 |
+
== Frequently Asked Questions ==
|
35 |
+
|
36 |
+
= Why using Polylang and not other well established equivalent plugins ? =
|
37 |
+
|
38 |
+
WPML: I tested only the last non-commercial version with WP 3.0.5. The plugin looks quite complete. It's however very heavy (almost 30000 lines of code !). The fact that it has turned commercial is probably adapted to companies or very active bloggers but not well adapted to small blogs.
|
39 |
+
|
40 |
+
Xili language: I tested the version 2.2.0. It looks too complex. For example you need to install 3 different plugins to manage post tags translation. If managing post translations is quite easy (and inspired Polylang...), the way to manage categories and post tags translations is not enough user friendly is my opinion. As WPML it's very heavy (about 12000 lines of code).
|
41 |
+
|
42 |
+
qtranslate: I tested the version 2.5.23. As claimed by its author, it's probably the best existing plugin... when using it. However, you must know that it is very difficult to come back to a clean site if you deactivate it (as, for example, one post in the database contains all translations). Moreover, it modifies urls so again, if you deactivate it, all links to your internal urls would be broken (not good for SEO).
|
43 |
+
|
44 |
+
In comparison to these plugins, Polylang tries to keep things simple and light, and does not mess your blog if you deactivate it. But it is still very young so be indulgent ;-)
|
45 |
+
|
46 |
+
= Language filter is lost when using the search form =
|
47 |
+
|
48 |
+
Your theme uses the template searchform.php (as Twenty Eleven does) or hardcoded the search form and javascript is disabled. Unfortunately Polylang currently does not support this. So you have the following alternatives to get the things work well:
|
49 |
+
|
50 |
+
* Use the 'get_search_form' function and place your custom search form in functions.php as described in the [codex](http://codex.wordpress.org/Function_Reference/get_search_form). The plugin also works well if you use the default search form provided by WordPress.
|
51 |
+
* Enable javascript (unfortunately you can't control this for your visitors so the first solution is better)
|
52 |
+
|
53 |
+
= Language filter is lost when using the calendar widget =
|
54 |
+
|
55 |
+
The plugin is not compatible with the calendar widget. The calendar displays well but it does not link to posts filtered in the right language. Consider using the Archives widget instead.
|
56 |
+
|
57 |
+
= The homepage link always send to the homepage in the default language =
|
58 |
+
|
59 |
+
Your theme has not been adapted to Polylang and both javascript and cookies are disabled. Unfortunately, it seems impossible (or too complex for me !) to correctly filter home_url (or bloginfo('url') and be sure that all things work. So you have the following alternatives:
|
60 |
+
|
61 |
+
* Use 'bloginfo('lang_url)' in your theme whenever you want to link to the homepage in the right language. Don't use this template tag for the search form action.
|
62 |
+
* Enable javascript and/or cookies (unfortunately you can't control this for your visitors so the first solution is better)
|
63 |
+
|
64 |
+
= I activated the plugin and my posts are not displayed any more =
|
65 |
+
|
66 |
+
You MUST define a language for all your posts and pages otherwise they will not pass the language filter...
|
67 |
+
|
68 |
+
= I activated the plugin and my categories and post tags are not displayed any more =
|
69 |
+
|
70 |
+
You MUST define a language for all your categories and post tags otherwise they will not pass the language filter...
|
71 |
+
|
72 |
+
== Changelog ==
|
73 |
+
|
74 |
+
= 0.1 =
|
75 |
+
* Initial release
|
76 |
+
|
uninstall.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
global $wpdb;
|
4 |
+
$wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
|
5 |
+
register_taxonomy('language', 'post', array('label' => false, 'query_var'=>'lang')); // temporarily register the language taxonomy
|
6 |
+
|
7 |
+
$languages = get_terms('language', array('hide_empty'=>false));
|
8 |
+
foreach ($languages as $lang) {
|
9 |
+
// delete references to this language in all posts
|
10 |
+
$args = array('numberposts'=> -1, 'post_type'=>'any', 'post_status'=>'any');
|
11 |
+
$posts = get_posts($args);
|
12 |
+
foreach ($posts as $post) {
|
13 |
+
delete_post_meta($post->ID, '_lang-'.$lang->slug);
|
14 |
+
}
|
15 |
+
// delete references to this language in categories & post tags
|
16 |
+
$terms = get_terms(array('category', 'post_tag'), 'get=all');
|
17 |
+
foreach ($terms as $term) {
|
18 |
+
delete_metadata('term', $term->term_id, '_language');
|
19 |
+
delete_metadata('term', $term->term_id, '_lang-'.$lang->slug);
|
20 |
+
}
|
21 |
+
// finally delete the language itself
|
22 |
+
wp_delete_term($lang->term_id, 'language');
|
23 |
+
}
|
24 |
+
|
25 |
+
// delete the termmeta table only if it is empty as other plugins may use it
|
26 |
+
$table = $wpdb->termmeta;
|
27 |
+
$count = $wpdb->get_var("SELECT COUNT(*) FROM $table;");
|
28 |
+
if (!$count) {
|
29 |
+
$wpdb->query("DROP TABLE $table;");
|
30 |
+
unset($wpdb->termmeta);
|
31 |
+
}
|
32 |
+
|
33 |
+
// finally delete options
|
34 |
+
delete_option('polylang');
|
35 |
+
delete_option('widget_polylang_widget');
|
36 |
+
?>
|
widget.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Polylang_Widget extends WP_Widget {
|
4 |
+
function __construct() {
|
5 |
+
$widget_ops = array( 'description' => __( 'Displays a language switcher', 'polylang') );
|
6 |
+
parent::__construct('polylang', __('Language Switcher', 'polylang'), $widget_ops);
|
7 |
+
}
|
8 |
+
|
9 |
+
function widget($args, $instance) {
|
10 |
+
extract( $args );
|
11 |
+
|
12 |
+
echo "$before_widget\n";
|
13 |
+
do_action('the_languages');
|
14 |
+
echo "$after_widget\n";
|
15 |
+
}
|
16 |
+
|
17 |
+
} // Class Polylang_Widget
|
18 |
+
|
19 |
+
?>
|