Version Description
(2015-06-22) =
- Released on June 22, 2015
=
Download this release
Release Info
Developer | smithworx |
Plugin | Lingotek Translation |
Version | 1.0 |
Comparing to | |
See all releases |
Version 1.0
- admin/actions.php +457 -0
- admin/admin.php +500 -0
- admin/content-table.php +200 -0
- admin/filters-columns.php +165 -0
- admin/filters-media.php +56 -0
- admin/filters-post.php +183 -0
- admin/filters-term.php +131 -0
- admin/manage/view-string-groups.php +36 -0
- admin/manage/view-strings.php +49 -0
- admin/post-actions.php +193 -0
- admin/profiles-table.php +133 -0
- admin/settings.php +64 -0
- admin/settings/connect-account.php +31 -0
- admin/settings/view-account.php +120 -0
- admin/settings/view-content.php +93 -0
- admin/settings/view-defaults.php +141 -0
- admin/settings/view-edit-profile.php +200 -0
- admin/settings/view-preferences.php +84 -0
- admin/settings/view-profiles.php +95 -0
- admin/settings/view-utilities.php +78 -0
- admin/string-actions.php +144 -0
- admin/strings-table.php +170 -0
- admin/table-string.php +31 -0
- admin/term-actions.php +184 -0
- admin/tutorial/content.php +95 -0
- admin/tutorial/credits.php +61 -0
- admin/tutorial/faq.php +64 -0
- admin/tutorial/features.php +39 -0
- admin/tutorial/img/add-languages.png +0 -0
- admin/tutorial/img/add-page.png +0 -0
- admin/tutorial/img/add-page2.png +0 -0
- admin/tutorial/img/automatic-translation.gif +0 -0
- admin/tutorial/img/automatic-translation.png +0 -0
- admin/tutorial/img/check-status.png +0 -0
- admin/tutorial/img/content-types.png +0 -0
- admin/tutorial/img/dashboard.png +0 -0
- admin/tutorial/img/polylang-compatible.png +0 -0
- admin/tutorial/img/pro-translation.png +0 -0
- admin/tutorial/img/professional-translation.png +0 -0
- admin/tutorial/img/ready-to-upload.png +0 -0
- admin/tutorial/img/request-translations.png +0 -0
- admin/tutorial/img/translation-profiles.png +0 -0
- admin/tutorial/img/translations-downloaded.png +0 -0
- admin/tutorial/img/translations-ready-for-download.png +0 -0
- admin/tutorial/img/translations-underway.png +0 -0
- admin/tutorial/img/workbench-full.png +0 -0
- admin/tutorial/img/workbench.png +0 -0
- admin/utilities.php +132 -0
- admin/view-dashboard.php +9 -0
- admin/view-manage.php +39 -0
- admin/view-network.php +167 -0
- admin/view-tutorial.php +49 -0
- css/admin.css +77 -0
- img/lingotek-chevrons-blue.png +0 -0
- img/lingotek-icon.png +0 -0
- img/lingotek-white.png +0 -0
- include/api.php +292 -0
- include/callback.php +85 -0
- include/dashboard.php +307 -0
- include/group-post.php +219 -0
- include/group-string.php +188 -0
- include/group-term.php +167 -0
- include/group.php +294 -0
- include/http.php +94 -0
- include/model.php +563 -0
- include/pointer.php +107 -0
- js/defaults.js +18 -0
- js/progress.js +39 -0
- languages/wp-lingotek-fr_FR.mo +0 -0
- languages/wp-lingotek-fr_FR.po +1203 -0
- lingotek.php +524 -0
- readme.txt +98 -0
- uninstall.php +47 -0
admin/actions.php
ADDED
@@ -0,0 +1,457 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* Base class to add row and bulk actions to posts, media and terms list
|
5 |
+
* Bulk actions management is inspired by http://www.foxrunsoftware.net/articles/wordpress/add-custom-bulk-action/
|
6 |
+
*
|
7 |
+
* @since 0.2
|
8 |
+
*/
|
9 |
+
abstract class Lingotek_Actions {
|
10 |
+
public $pllm, $lgtm; // Polylang and Lingotek models
|
11 |
+
public $type; // *must* be defined in child class: 'post' or 'term'
|
12 |
+
public static $actions, $icons, $confirm_message;
|
13 |
+
|
14 |
+
/*
|
15 |
+
* Constructor
|
16 |
+
*
|
17 |
+
* @since 0.2
|
18 |
+
*/
|
19 |
+
public function __construct($type) {
|
20 |
+
// confirm message
|
21 |
+
self::$confirm_message = sprintf(' onclick = "return confirm(\'%s\');"', __('You are about to overwrite existing translations. Are you sure?', 'wp-lingotek'));
|
22 |
+
|
23 |
+
// row actions
|
24 |
+
self::$actions = array(
|
25 |
+
'upload' => array(
|
26 |
+
'action' => __('Upload to Lingotek', 'wp-lingotek'),
|
27 |
+
'progress' => __('Uploading...', 'wp-lingotek'),
|
28 |
+
'description' => __('Upload this item to Lingotek TMS', 'wp-lingotek' ),
|
29 |
+
),
|
30 |
+
|
31 |
+
'request' => array(
|
32 |
+
'action' => __('Request translations', 'wp-lingotek'),
|
33 |
+
'progress' => __('Requesting translations...', 'wp-lingotek'),
|
34 |
+
'description' => __('Request translations of this item to Lingotek TMS', 'wp-lingotek' ),
|
35 |
+
),
|
36 |
+
|
37 |
+
'status' => array(
|
38 |
+
'action' => __('Update translations status', 'wp-lingotek'),
|
39 |
+
'progress' => __('Updating translations status...', 'wp-lingotek'),
|
40 |
+
'description' => __('Update translations status of this item in Lingotek TMS', 'wp-lingotek' ),
|
41 |
+
),
|
42 |
+
|
43 |
+
'download' => array(
|
44 |
+
'action' => __('Download translations', 'wp-lingotek'),
|
45 |
+
'progress' => __('Downloading translations...', 'wp-lingotek'),
|
46 |
+
'description' => __('Download translations of this item from Lingotek TMS', 'wp-lingotek' ),
|
47 |
+
),
|
48 |
+
|
49 |
+
'delete' => array(
|
50 |
+
'action' => __('Disassociate translations', 'wp-lingotek'),
|
51 |
+
'progress' => __('Disassociating translations...', 'wp-lingotek'),
|
52 |
+
'description' => __('Disassociate the translations of this item from Lingotek TMS', 'wp-lingotek' ),
|
53 |
+
),
|
54 |
+
);
|
55 |
+
|
56 |
+
// action icons
|
57 |
+
self::$icons = array(
|
58 |
+
'upload' => array(
|
59 |
+
'title' => __('Upload Now', 'wp-lingotek'),
|
60 |
+
'icon' => 'upload'
|
61 |
+
),
|
62 |
+
|
63 |
+
'importing' => array(
|
64 |
+
'title' => __('Importing source', 'wp-lingotek'),
|
65 |
+
'icon' => 'clock'
|
66 |
+
),
|
67 |
+
|
68 |
+
'uploaded' => array(
|
69 |
+
'title' => __('Source uploaded', 'wp-lingotek'),
|
70 |
+
'icon' => 'yes'
|
71 |
+
),
|
72 |
+
|
73 |
+
'request' => array(
|
74 |
+
'title' => __('Request a translation', 'wp-lingotek'),
|
75 |
+
'icon' => 'plus'
|
76 |
+
),
|
77 |
+
|
78 |
+
'pending' => array(
|
79 |
+
'title' => __('In Progress', 'wp-lingotek'),
|
80 |
+
'icon' => 'clock'
|
81 |
+
),
|
82 |
+
|
83 |
+
'ready' => array(
|
84 |
+
'title' => __('Ready to download', 'wp-lingotek'),
|
85 |
+
'icon' => 'download'
|
86 |
+
),
|
87 |
+
|
88 |
+
'current' => array(
|
89 |
+
'title' => __('current', 'wp-lingotek'),
|
90 |
+
'icon' => 'edit'
|
91 |
+
),
|
92 |
+
|
93 |
+
'not-current' => array(
|
94 |
+
'title' => __('The target translation is no longer current as the source content has been updated', 'wp-lingotek'),
|
95 |
+
'icon' => 'edit'
|
96 |
+
),
|
97 |
+
);
|
98 |
+
|
99 |
+
$this->type = $type;
|
100 |
+
$this->pllm = $GLOBALS['polylang']->model;
|
101 |
+
$this->lgtm = $GLOBALS['wp_lingotek']->model;
|
102 |
+
|
103 |
+
add_action('admin_enqueue_scripts', array(&$this, 'admin_enqueue_scripts'));
|
104 |
+
|
105 |
+
foreach (array_keys(self::$actions) as $action)
|
106 |
+
add_action('wp_ajax_lingotek_progress_' . $this->type . '_'. $action , array(&$this, 'ajax_' . $action));
|
107 |
+
}
|
108 |
+
|
109 |
+
/*
|
110 |
+
* generates a workbench link
|
111 |
+
*
|
112 |
+
* @since 0.1
|
113 |
+
*
|
114 |
+
* @param string $document_id
|
115 |
+
* @param string $locale Lingotek locale
|
116 |
+
* @return string workbench link
|
117 |
+
*/
|
118 |
+
public static function workbench_link($document_id, $locale) {
|
119 |
+
$client_id = Lingotek_API::CLIENT_ID;
|
120 |
+
$token_details = get_option('lingotek_token');
|
121 |
+
$user = wp_get_current_user();
|
122 |
+
$base_url = get_option('lingotek_base_url');
|
123 |
+
|
124 |
+
$acting_login_id = $user->user_email; //user_nicename;
|
125 |
+
|
126 |
+
return self::generate_workbench_link(
|
127 |
+
$document_id,
|
128 |
+
$locale,
|
129 |
+
$client_id,
|
130 |
+
$token_details['access_token'],
|
131 |
+
$token_details['login_id'],
|
132 |
+
$acting_login_id,
|
133 |
+
$base_url
|
134 |
+
);
|
135 |
+
}
|
136 |
+
|
137 |
+
/*
|
138 |
+
* generates a workbench link
|
139 |
+
* function provided by Matt Smith from Lingotek
|
140 |
+
*
|
141 |
+
* @since 0.1
|
142 |
+
*
|
143 |
+
* @param string $document_id
|
144 |
+
* @param string $locale_code
|
145 |
+
* @param string $client_id
|
146 |
+
* @param string $access_token
|
147 |
+
* @param string $login_id
|
148 |
+
* @param string $acting_login_id
|
149 |
+
* @param string $base_url
|
150 |
+
* @param int|null $expiration
|
151 |
+
* @return string workbench link
|
152 |
+
*/
|
153 |
+
public static function generate_workbench_link($document_id, $locale_code, $client_id, $access_token, $login_id, $acting_login_id = "anonymous", $base_url = "https://myaccount.lingotek.com", $expiration = NULL) {
|
154 |
+
$expiration_default = time() + (60 * 30); // 30-minute default, otherwise use $expiration as passed in
|
155 |
+
$expiration = is_null($expiration) ? $expiration_default : $expiration;
|
156 |
+
$data = array(
|
157 |
+
'document_id' => $document_id,
|
158 |
+
'locale_code' => $locale_code,
|
159 |
+
'client_id' => $client_id,
|
160 |
+
'login_id' => $login_id,
|
161 |
+
'acting_login_id' => $acting_login_id,
|
162 |
+
'expiration' => $expiration
|
163 |
+
);
|
164 |
+
$query_data = utf8_encode(http_build_query($data));
|
165 |
+
$hmac = urlencode(base64_encode(hash_hmac('sha1', $query_data, $access_token, TRUE)));
|
166 |
+
$workbench_url = $base_url . '/lingopoint/portal/wb.action?' . $query_data . "&hmac=" . $hmac;
|
167 |
+
return $workbench_url;
|
168 |
+
}
|
169 |
+
|
170 |
+
/*
|
171 |
+
* outputs an action icon
|
172 |
+
*
|
173 |
+
* @since 0.2
|
174 |
+
*
|
175 |
+
* @param string $name
|
176 |
+
* @param string $link
|
177 |
+
* @param string $additional parameters to add (js, target)
|
178 |
+
*/
|
179 |
+
public static function display_icon($name, $link, $additional = '') {
|
180 |
+
return sprintf('<a class="lingotek-color dashicons dashicons-%s" title="%s" href="%s"%s></a>',
|
181 |
+
self::$icons[$name]['icon'], self::$icons[$name]['title'], esc_url($link), $additional);
|
182 |
+
}
|
183 |
+
|
184 |
+
/*
|
185 |
+
* outputs an upload icon
|
186 |
+
*
|
187 |
+
* @since 0.2
|
188 |
+
*
|
189 |
+
* @param int|string $object_id
|
190 |
+
* @param bool $warning
|
191 |
+
*/
|
192 |
+
public function upload_icon($object_id, $confirm = false) {
|
193 |
+
$args = array($this->type => $object_id, 'action' => 'lingotek-upload', 'noheader' => true);
|
194 |
+
$link = wp_nonce_url(defined('DOING_AJAX') && DOING_AJAX ? add_query_arg($args, wp_get_referer()) : add_query_arg($args), 'lingotek-upload');
|
195 |
+
return self::display_icon('upload', $link, $confirm ? self::$confirm_message : '');
|
196 |
+
}
|
197 |
+
|
198 |
+
/*
|
199 |
+
* outputs an importing icon
|
200 |
+
*
|
201 |
+
* @since 0.2
|
202 |
+
*
|
203 |
+
* @param object $document
|
204 |
+
*/
|
205 |
+
public static function importing_icon($document) {
|
206 |
+
$args = array('document_id' => $document->document_id, 'action' => 'lingotek-status', 'noheader' => true);
|
207 |
+
$link = wp_nonce_url(defined('DOING_AJAX') && DOING_AJAX ? add_query_arg($args, wp_get_referer()) : add_query_arg($args), 'lingotek-status');
|
208 |
+
return self::display_icon('importing', $link);
|
209 |
+
}
|
210 |
+
|
211 |
+
/*
|
212 |
+
* outputs icons for translations
|
213 |
+
*
|
214 |
+
* @since 0.2
|
215 |
+
*
|
216 |
+
* @param object $document
|
217 |
+
* @param object $language
|
218 |
+
*/
|
219 |
+
public static function translation_icon($document, $language) {
|
220 |
+
if (isset($document->translations[$language->locale])) {
|
221 |
+
if ('ready' == $document->translations[$language->locale]) {
|
222 |
+
$link = wp_nonce_url(add_query_arg(array('document_id' => $document->document_id, 'locale' => $language->locale, 'action' => 'lingotek-download', 'noheader' => true)), 'lingotek-download');
|
223 |
+
return self::display_icon($document->translations[$language->locale], $link);
|
224 |
+
}
|
225 |
+
else {
|
226 |
+
$link = self::workbench_link($document->document_id, $language->lingotek_locale);
|
227 |
+
return self::display_icon($document->translations[$language->locale], $link, ' target="_blank"');
|
228 |
+
}
|
229 |
+
|
230 |
+
}
|
231 |
+
else {
|
232 |
+
$link = wp_nonce_url(add_query_arg(array('document_id' => $document->document_id, 'locale' => $language->locale, 'action' => 'lingotek-request', 'noheader' => true)), 'lingotek-request');
|
233 |
+
return self::display_icon('request', $link);
|
234 |
+
}
|
235 |
+
}
|
236 |
+
|
237 |
+
/*
|
238 |
+
* creates an html action link
|
239 |
+
*
|
240 |
+
* @since 0.2
|
241 |
+
*
|
242 |
+
* @param array $args parameters to add to the link
|
243 |
+
* @param bool $warning whether to display an alert or not, optional, defaults to false
|
244 |
+
* @return string
|
245 |
+
*/
|
246 |
+
protected function get_action_link($args, $warning = false) {
|
247 |
+
$action = $args['action'];
|
248 |
+
$args['action'] = 'lingotek-' . $action;
|
249 |
+
$args['noheader'] = true;
|
250 |
+
|
251 |
+
return sprintf(
|
252 |
+
'<a class="lingotek-color" title="%s" href="%s"%s>%s</a>',
|
253 |
+
self::$actions[$action]['description'],
|
254 |
+
wp_nonce_url(add_query_arg($args, defined('DOING_AJAX') && DOING_AJAX ? wp_get_referer() : ''), 'lingotek-' .$action),
|
255 |
+
empty($warning) ? '' : self::$confirm_message,
|
256 |
+
self::$actions[$action]['action']
|
257 |
+
);
|
258 |
+
}
|
259 |
+
|
260 |
+
/*
|
261 |
+
* adds a row action link
|
262 |
+
*
|
263 |
+
* @since 0.2
|
264 |
+
*
|
265 |
+
* @param array $actions list of action links
|
266 |
+
* @param $id object id
|
267 |
+
* @return array
|
268 |
+
*/
|
269 |
+
protected function _row_actions($actions, $id) {
|
270 |
+
// first check that a language is associated to this object
|
271 |
+
if (!$this->get_language($id))
|
272 |
+
return $actions;
|
273 |
+
|
274 |
+
$document = $this->lgtm->get_group($this->type, $id);
|
275 |
+
|
276 |
+
if ($this->lgtm->can_upload($this->type, $id) || (isset($document->source) && 'string' != $this->type && $this->lgtm->can_upload($this->type, $document->source))) {
|
277 |
+
$actions['lingotek-upload'] = $this->get_action_link(array($this->type => $id, 'action' => 'upload'));
|
278 |
+
}
|
279 |
+
|
280 |
+
elseif (isset($document->translations)) {
|
281 |
+
// translations to download ?
|
282 |
+
if ($document->has_translation_status('ready'))
|
283 |
+
$actions['lingotek-download'] = $this->get_action_link(array('document_id' => $document->document_id, 'action' => 'download'));
|
284 |
+
|
285 |
+
// need to request translations ?
|
286 |
+
$language = $this->get_language($document->source);
|
287 |
+
$all_locales = array_flip($this->pllm->get_languages_list(array('fields' => 'locale')));
|
288 |
+
if (!empty($language)) // in case a language has been deleted
|
289 |
+
unset($all_locales[$language->locale]);
|
290 |
+
$untranslated = array_diff_key($all_locales, $document->translations);
|
291 |
+
|
292 |
+
// remove disabled target language from untranslated languages list
|
293 |
+
foreach ($untranslated as $k => $v) {
|
294 |
+
if ($document->is_disabled_target($this->pllm->get_language($k)))
|
295 |
+
unset($untranslated[$k]);
|
296 |
+
}
|
297 |
+
|
298 |
+
if ('current' == $document->status && !empty($untranslated))
|
299 |
+
$actions['lingotek-request'] = $this->get_action_link(array('document_id' => $document->document_id, 'action' => 'request'));
|
300 |
+
|
301 |
+
// offers to update translations status
|
302 |
+
if ('importing' == $document->status || $document->has_translation_status('pending'))
|
303 |
+
$actions['lingotek-status'] = $this->get_action_link(array('document_id' => $document->document_id, 'action' => 'status'));
|
304 |
+
}
|
305 |
+
|
306 |
+
elseif (empty($document->source)) {
|
307 |
+
$actions['lingotek-upload'] = $this->get_action_link(array($this->type => $id, 'action' => 'upload'), true);
|
308 |
+
}
|
309 |
+
|
310 |
+
// offers to disassociate translations
|
311 |
+
if (!empty($document->translations))
|
312 |
+
$actions['lingotek-delete'] = $this->get_action_link(array('document_id' => $document->document_id, 'action' => 'delete'));
|
313 |
+
|
314 |
+
return $actions;
|
315 |
+
}
|
316 |
+
|
317 |
+
/*
|
318 |
+
* adds actions to bulk dropdown list table using a javascript hack
|
319 |
+
* as the existing filter does not allow to *add* actions
|
320 |
+
* also displays the progress dialog placeholder
|
321 |
+
*
|
322 |
+
* @since 0.2
|
323 |
+
*/
|
324 |
+
protected function _add_bulk_actions() {
|
325 |
+
$js = '';
|
326 |
+
|
327 |
+
foreach (self::$actions as $action => $strings) {
|
328 |
+
foreach (array('', '2') as $i)
|
329 |
+
$js .= sprintf('jQuery("<option>").val("bulk-lingotek-%s").text("%s").appendTo("select[name=\'action%s\']");', $action, $strings['action'], $i);
|
330 |
+
|
331 |
+
if (!empty($_GET['bulk-lingotek-' . $action]))
|
332 |
+
$text = $strings['progress'];
|
333 |
+
}
|
334 |
+
|
335 |
+
echo '<script type="text/javascript">jQuery(document).ready(function() {' . $js . '});</script>';
|
336 |
+
|
337 |
+
if (!empty($text))
|
338 |
+
printf('<div id="lingotek-progressdialog" title="%s"><div id="lingotek-progressbar"></div></div>', $text);
|
339 |
+
}
|
340 |
+
|
341 |
+
/*
|
342 |
+
* outputs javascript data for progress.js
|
343 |
+
*
|
344 |
+
* @since 0.1
|
345 |
+
*/
|
346 |
+
public function admin_enqueue_scripts() {
|
347 |
+
foreach (array_keys(self::$actions) as $action) {
|
348 |
+
if (!empty($_GET['bulk-lingotek-' . $action])) {
|
349 |
+
wp_localize_script('lingotek_progress', 'lingotek_data', array(
|
350 |
+
'action' => empty($_GET['page']) ? (empty($_GET['taxonomy']) ? 'post_' . $action : 'term_' . $action) : 'string_' . $action,
|
351 |
+
'taxonomy' => empty($_GET['taxonomy']) || !taxonomy_exists($_GET['taxonomy']) ? '' : $_GET['taxonomy'],
|
352 |
+
'sendback' => remove_query_arg( array('bulk-lingotek-' . $action, 'ids', 'lingotek_warning'), wp_get_referer() ),
|
353 |
+
'ids' => array_map('intval', explode(',', $_GET['ids'])),
|
354 |
+
'warning' => empty($_GET['lingotek_warning']) ? '' : __('You are about to overwrite existing translations. Are you sure?', 'wp-lingotek'),
|
355 |
+
'nonce' => wp_create_nonce('lingotek_progress')
|
356 |
+
));
|
357 |
+
return;
|
358 |
+
}
|
359 |
+
}
|
360 |
+
}
|
361 |
+
|
362 |
+
/*
|
363 |
+
* manages actions driven by dcoument_id
|
364 |
+
*
|
365 |
+
* @since 0.2
|
366 |
+
*
|
367 |
+
* @param string $action action name
|
368 |
+
* @return bool true if the action was managed, false otherwise
|
369 |
+
*/
|
370 |
+
protected function _manage_actions($action) {
|
371 |
+
if (!empty($_GET['document_id']))
|
372 |
+
$document = $this->lgtm->get_group_by_id($_GET['document_id']);
|
373 |
+
|
374 |
+
switch($action) {
|
375 |
+
case 'lingotek-status':
|
376 |
+
check_admin_referer('lingotek-status');
|
377 |
+
$document->source_status();
|
378 |
+
$document->translations_status();
|
379 |
+
break;
|
380 |
+
|
381 |
+
case 'lingotek-request':
|
382 |
+
check_admin_referer('lingotek-request');
|
383 |
+
isset($_GET['locale']) ? $document->request_translation($_GET['locale']) : $document->request_translations();
|
384 |
+
break;
|
385 |
+
|
386 |
+
case 'lingotek-download':
|
387 |
+
check_admin_referer('lingotek-download');
|
388 |
+
isset($_GET['locale']) ? $document->create_translation($_GET['locale']) : $document->create_translations();
|
389 |
+
break;
|
390 |
+
|
391 |
+
case 'lingotek-delete':
|
392 |
+
check_admin_referer('lingotek-delete');
|
393 |
+
$document->disassociate();
|
394 |
+
break;
|
395 |
+
|
396 |
+
default:
|
397 |
+
return false;
|
398 |
+
}
|
399 |
+
|
400 |
+
return true;
|
401 |
+
}
|
402 |
+
|
403 |
+
/*
|
404 |
+
* ajax response to download translations and showing progress
|
405 |
+
*
|
406 |
+
* @since 0.1
|
407 |
+
*/
|
408 |
+
public function ajax_download() {
|
409 |
+
check_ajax_referer('lingotek_progress', '_lingotek_nonce');
|
410 |
+
|
411 |
+
if ($document = $this->lgtm->get_group($this->type, $_POST['id'])) {
|
412 |
+
foreach ($document->translations as $locale => $status) {
|
413 |
+
if ('pending' == $status || 'ready' == $status)
|
414 |
+
$document->create_translation($locale);
|
415 |
+
}
|
416 |
+
}
|
417 |
+
die();
|
418 |
+
}
|
419 |
+
|
420 |
+
/*
|
421 |
+
* ajax response to request translations and showing progress
|
422 |
+
*
|
423 |
+
* @since 0.2
|
424 |
+
*/
|
425 |
+
public function ajax_request() {
|
426 |
+
check_ajax_referer('lingotek_progress', '_lingotek_nonce');
|
427 |
+
if ($document = $this->lgtm->get_group($this->type, $_POST['id']))
|
428 |
+
$document->request_translations();
|
429 |
+
die();
|
430 |
+
}
|
431 |
+
|
432 |
+
/*
|
433 |
+
* ajax response to check translation status and showing progress
|
434 |
+
*
|
435 |
+
* @since 0.1
|
436 |
+
*/
|
437 |
+
public function ajax_status() {
|
438 |
+
check_ajax_referer('lingotek_progress', '_lingotek_nonce');
|
439 |
+
if ($document = $this->lgtm->get_group($this->type, $_POST['id'])) {
|
440 |
+
$document->source_status();
|
441 |
+
$document->translations_status();
|
442 |
+
}
|
443 |
+
die();
|
444 |
+
}
|
445 |
+
|
446 |
+
/*
|
447 |
+
* ajax response disassociate translations and showing progress
|
448 |
+
*
|
449 |
+
* @since 0.2
|
450 |
+
*/
|
451 |
+
public function ajax_delete() {
|
452 |
+
check_ajax_referer('lingotek_progress', '_lingotek_nonce');
|
453 |
+
if ($document = $this->lgtm->get_group($this->type, $_POST['id']))
|
454 |
+
$document->disassociate();
|
455 |
+
die();
|
456 |
+
}
|
457 |
+
}
|
admin/admin.php
ADDED
@@ -0,0 +1,500 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Lingotek_Admin {
|
4 |
+
private $ajax_dashboard_language_endpoint = "lingotek_language";
|
5 |
+
/*
|
6 |
+
* setups filters and action needed on all admin pages and on plugins page
|
7 |
+
*
|
8 |
+
* @since 0.1
|
9 |
+
*/
|
10 |
+
public function __construct() {
|
11 |
+
|
12 |
+
$plugin = Lingotek::get_instance();
|
13 |
+
$this->plugin_slug = $plugin->get_plugin_slug();
|
14 |
+
$this->dashboard = new Lingotek_Dashboard($plugin);
|
15 |
+
|
16 |
+
$this->pllm = $GLOBALS['polylang']->model;
|
17 |
+
|
18 |
+
add_action('admin_enqueue_scripts', array(&$this, 'admin_enqueue_scripts'));
|
19 |
+
|
20 |
+
// adds a 'settings' link in the plugins table
|
21 |
+
add_filter('plugin_action_links_' . LINGOTEK_BASENAME, array(&$this, 'plugin_action_links'));
|
22 |
+
|
23 |
+
// adds the link to the languages panel in the wordpress admin menu
|
24 |
+
add_action('admin_menu', array(&$this, 'add_menus'));
|
25 |
+
|
26 |
+
add_action('load-translation_page_wp-lingotek_manage', array(&$this, 'load_manage_page'));
|
27 |
+
add_filter('set-screen-option', array($this, 'set_screen_option'), 10, 3);
|
28 |
+
|
29 |
+
add_action('wp_ajax_'.$this->ajax_dashboard_language_endpoint, array(&$this->dashboard, 'ajax_language_dashboard'));
|
30 |
+
|
31 |
+
//Network admin menu
|
32 |
+
add_action('network_admin_menu', array($this, 'add_network_admin_menu'));
|
33 |
+
}
|
34 |
+
|
35 |
+
public function get_dashboard_endpoint(){
|
36 |
+
return site_url("wp-admin/admin-ajax.php?action=".$this->ajax_dashboard_language_endpoint);
|
37 |
+
}
|
38 |
+
|
39 |
+
/*
|
40 |
+
* setup js scripts & css styles (only on the relevant pages)
|
41 |
+
*
|
42 |
+
* @since 0.1
|
43 |
+
*/
|
44 |
+
public function admin_enqueue_scripts() {
|
45 |
+
$screen = get_current_screen();
|
46 |
+
|
47 |
+
// FIXME no minified file for now
|
48 |
+
$suffix = '';
|
49 |
+
// $suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min';
|
50 |
+
|
51 |
+
// for each script:
|
52 |
+
// 0 => the pages on which to load the script
|
53 |
+
// 1 => the scripts it needs to work
|
54 |
+
// 2 => 1 if loaded in footer
|
55 |
+
// FIXME: check if I can load more scripts in footer
|
56 |
+
$scripts = array(
|
57 |
+
'progress' => array(array('edit', 'upload', 'edit-tags', 'translation_page_wp-lingotek_manage', 'translation_page_wp-lingotek_settings'), array('jquery-ui-progressbar', 'jquery-ui-dialog', 'wp-ajax-response'), 1),
|
58 |
+
);
|
59 |
+
|
60 |
+
$styles = array(
|
61 |
+
'admin' => array(array('edit', 'upload', 'edit-tags', 'translation_page_wp-lingotek_manage', 'translation_page_wp-lingotek_settings'), array('wp-jquery-ui-dialog')),
|
62 |
+
);
|
63 |
+
|
64 |
+
foreach ($scripts as $script => $v)
|
65 |
+
if (in_array($screen->base, $v[0]))
|
66 |
+
wp_enqueue_script('lingotek_'.$script, LINGOTEK_URL .'/js/'.$script.$suffix.'.js', $v[1], LINGOTEK_VERSION, $v[2]);
|
67 |
+
|
68 |
+
foreach ($styles as $style => $v)
|
69 |
+
if (in_array($screen->base, $v[0]))
|
70 |
+
wp_enqueue_style('lingotek_'.$style, LINGOTEK_URL .'/css/'.$style.$suffix.'.css', $v[1], LINGOTEK_VERSION);
|
71 |
+
}
|
72 |
+
|
73 |
+
/*
|
74 |
+
* adds a 'settings' link in the plugins table
|
75 |
+
*
|
76 |
+
* @since 0.1
|
77 |
+
*
|
78 |
+
* @param array $links list of links associated to the plugin
|
79 |
+
* @return array modified list of links
|
80 |
+
*/
|
81 |
+
public function plugin_action_links($links) {
|
82 |
+
array_unshift($links, '<a href="admin.php?page=wp-lingotek">' . __('Settings', 'wp-lingotek') . '</a>');
|
83 |
+
return $links;
|
84 |
+
}
|
85 |
+
|
86 |
+
/*
|
87 |
+
* adds the links to the Lingotek panels in the wordpress admin menu
|
88 |
+
*
|
89 |
+
* @since 0.0.1
|
90 |
+
*/
|
91 |
+
public function add_menus() {
|
92 |
+
add_menu_page(
|
93 |
+
$title = __('Translation', 'wp-lingotek'),
|
94 |
+
$title,
|
95 |
+
'manage_options',
|
96 |
+
$this->plugin_slug,
|
97 |
+
array($this, 'display_dashboard_page'), 'dashicons-translation'
|
98 |
+
);
|
99 |
+
|
100 |
+
add_submenu_page($this->plugin_slug, __('Translation Dashboard', 'wp-lingotek'), __('Dashboard', 'wp-lingotek'), 'manage_options', $this->plugin_slug, array($this, 'display_dashboard_page'));
|
101 |
+
add_submenu_page($this->plugin_slug, __('Translation Management', 'wp-lingotek'), __('Manage', 'wp-lingotek'), 'manage_options', $this->plugin_slug . '_manage', array($this, 'display_manage_page'));
|
102 |
+
add_submenu_page($this->plugin_slug, __('Translation Settings', 'wp-lingotek'), __('Settings', 'wp-lingotek'), 'manage_options', $this->plugin_slug . '_settings', array($this, 'display_settings_page'));
|
103 |
+
add_submenu_page($this->plugin_slug, __('Lingotek Tutorial', 'wp-lingotek'), __('Tutorial', 'wp-lingotek'), 'manage_options', $this->plugin_slug . '_tutorial', array($this, 'display_tutorial_page'));
|
104 |
+
}
|
105 |
+
|
106 |
+
/*
|
107 |
+
* displays the settings page
|
108 |
+
*
|
109 |
+
* @since 0.0.1
|
110 |
+
*/
|
111 |
+
public function display_settings_page() {
|
112 |
+
|
113 |
+
// disconnect Lingotek account
|
114 |
+
if (array_key_exists('delete_access_token', $_GET) && $_GET['delete_access_token']) {
|
115 |
+
delete_option('lingotek_token');
|
116 |
+
delete_option('lingotek_community');
|
117 |
+
delete_option('lingotek_defaults');
|
118 |
+
}
|
119 |
+
|
120 |
+
// connect Lingotek account
|
121 |
+
if (array_key_exists('access_token', $_GET)) {
|
122 |
+
// set and get token details
|
123 |
+
$client = new Lingotek_API();
|
124 |
+
$token_details = $client->get_token_details($_GET['access_token']);
|
125 |
+
if ($token_details && strlen($token_details->login_id)) {
|
126 |
+
update_option('lingotek_token', array('access_token' => $_GET['access_token'], 'login_id' => $token_details->login_id));
|
127 |
+
add_settings_error( 'lingotek_token', 'account-connection', __('Your Lingotek account has been successfully connected.', 'wp-lingotek'), 'updated' );
|
128 |
+
}
|
129 |
+
else {
|
130 |
+
add_settings_error('lingotek_token', 'account-connection', __('Your Lingotek account was not connected. The Access Token received was invalid.', 'wp-lingotek'), 'error');
|
131 |
+
}
|
132 |
+
}
|
133 |
+
|
134 |
+
// set page key primarily used for form submissions
|
135 |
+
$page_key = $this->plugin_slug.'_settings';
|
136 |
+
if(isset($_GET['sm'])){
|
137 |
+
$page_key .= '&sm='.$_GET['sm'];
|
138 |
+
}
|
139 |
+
|
140 |
+
// set community
|
141 |
+
if (!empty($_POST) && key_exists('lingotek_community', $_POST) && strlen($_POST['lingotek_community'])) {
|
142 |
+
check_admin_referer($page_key, '_wpnonce_' . $page_key);
|
143 |
+
update_option('lingotek_community', $_POST['lingotek_community']);
|
144 |
+
add_settings_error('lingotek_community', 'update', __('Your community has been successfully saved.', 'wp-lingotek'), 'updated');
|
145 |
+
$this->set_community_resources($_POST['lingotek_community']);
|
146 |
+
}
|
147 |
+
$community_id = get_option('lingotek_community');
|
148 |
+
if (!$community_id) {
|
149 |
+
add_settings_error('lingotek_community', 'error', __('Select and save the community that you would like to use.', 'wp-lingotek'), 'error');
|
150 |
+
}
|
151 |
+
|
152 |
+
$token_details = self::has_token_details();
|
153 |
+
$redirect_url = admin_url('admin.php?page=' . $this->plugin_slug . '_settings&sm=account');
|
154 |
+
|
155 |
+
if($token_details){
|
156 |
+
$access_token = $token_details['access_token'];
|
157 |
+
$login_id = $token_details['login_id'];
|
158 |
+
$base_url = get_option('lingotek_base_url');
|
159 |
+
include(LINGOTEK_ADMIN_INC . '/settings.php');
|
160 |
+
}
|
161 |
+
else {
|
162 |
+
$connect_url = "";
|
163 |
+
// connect cloak redirect
|
164 |
+
if(isset($_GET['connect'])){
|
165 |
+
// set sandbox or production (after button clicked)
|
166 |
+
if(strcasecmp($_GET['connect'],'sandbox')==0) {
|
167 |
+
update_option('lingotek_base_url', Lingotek_API::SANDBOX_URL);
|
168 |
+
}
|
169 |
+
else {
|
170 |
+
update_option('lingotek_base_url', Lingotek_API::PRODUCTION_URL);
|
171 |
+
}
|
172 |
+
$client = new Lingotek_API();
|
173 |
+
echo '<div class="wrap"><p class="description">'.__("Redirecting to Lingotek to connect your account...",'wp-lingotek').'</p></div>';
|
174 |
+
|
175 |
+
$connect_url = (strcasecmp($_GET['connect'],'new')==0) ? $client->get_new_url($redirect_url) : $client->get_connect_url($redirect_url);
|
176 |
+
}
|
177 |
+
$connect_account_cloak_url_new = admin_url('admin.php?page=' . $this->plugin_slug . '_settings&connect=new');
|
178 |
+
$connect_account_cloak_url_test = admin_url('admin.php?page=' . $this->plugin_slug . '_settings&connect=sandbox');
|
179 |
+
$connect_account_cloak_url_prod = admin_url('admin.php?page=' . $this->plugin_slug . '_settings&connect=production');
|
180 |
+
include(LINGOTEK_ADMIN_INC . '/settings/connect-account.php');
|
181 |
+
}
|
182 |
+
}
|
183 |
+
|
184 |
+
/*
|
185 |
+
* get possible settings for defaults or translation profiles
|
186 |
+
*
|
187 |
+
* @since 0.2
|
188 |
+
*
|
189 |
+
* @return array
|
190 |
+
*/
|
191 |
+
public function get_profiles_settings($defaults = false) {
|
192 |
+
$resources = get_option('lingotek_community_resources');
|
193 |
+
$options = array(
|
194 |
+
'manual' => __('Manual', 'wp-lingotek'),
|
195 |
+
'automatic' => __('Automatic', 'wp-lingotek')
|
196 |
+
);
|
197 |
+
|
198 |
+
return array(
|
199 |
+
'upload' => array(
|
200 |
+
'label' => __('Upload content', 'wp-lingotek'),
|
201 |
+
'options' => $options,
|
202 |
+
'description' => __('How should new and modified content be uploaded to Lingotek?', 'wp-lingotek')
|
203 |
+
),
|
204 |
+
'download' => array(
|
205 |
+
'label' => __('Download translations', 'wp-lingotek'),
|
206 |
+
'options' => $options,
|
207 |
+
'description' => __('How should completed translations be downloaded to WordPress?', 'wp-lingotek')
|
208 |
+
),
|
209 |
+
'project_id' => array(
|
210 |
+
'label' => $defaults ? __('Default Project', 'wp-lingotek') : __('Project', 'wp-lingotek'),
|
211 |
+
'options' => $resources['projects'],
|
212 |
+
'description' => __('Changes will affect new entities only', 'wp-lingotek')
|
213 |
+
),
|
214 |
+
'workflow_id' => array(
|
215 |
+
'label' => $defaults ? __('Default Workflow', 'wp-lingotek') : __('Workflow', 'wp-lingotek'),
|
216 |
+
'options' => $resources['workflows'],
|
217 |
+
),
|
218 |
+
'primary_filter_id' => array(
|
219 |
+
'label' => $defaults ? __('Primary Filter', 'wp-lingotek') : __('Primary Filter', 'wp-lingotek'),
|
220 |
+
'options' => $resources['filters'],
|
221 |
+
),
|
222 |
+
'secondary_filter_id' => array(
|
223 |
+
'label' => $defaults ? __('Secondary Filter', 'wp-lingotek') : __('Secondary Filter', 'wp-lingotek'),
|
224 |
+
'options' => $resources['filters'],
|
225 |
+
),
|
226 |
+
);
|
227 |
+
}
|
228 |
+
|
229 |
+
/*
|
230 |
+
* get usage for all profiles
|
231 |
+
*
|
232 |
+
* @since 0.2
|
233 |
+
*
|
234 |
+
* @param arry $profiles
|
235 |
+
* @return array profiles with added usage column
|
236 |
+
*/
|
237 |
+
public function get_profiles_usage($profiles) {
|
238 |
+
$content_types = get_option('lingotek_content_type');
|
239 |
+
|
240 |
+
// initialize usage column
|
241 |
+
foreach ($profiles as $key => $profile)
|
242 |
+
$profiles[$key]['usage'] = 0;
|
243 |
+
|
244 |
+
// fill usage column
|
245 |
+
foreach (array_merge($this->pllm->get_translated_post_types(), $this->pllm->get_translated_taxonomies(), array('string')) as $type) {
|
246 |
+
if (isset($content_types[$type]['profile']))
|
247 |
+
$profiles[$content_types[$type]['profile']]['usage'] += 1;
|
248 |
+
elseif ('post' == $type)
|
249 |
+
$profiles['automatic']['usage'] += 1;
|
250 |
+
else
|
251 |
+
$profiles['manual']['usage'] += 1;
|
252 |
+
|
253 |
+
if (isset($content_types[$type]['sources'])) {
|
254 |
+
foreach ($content_types[$type]['sources'] as $profile)
|
255 |
+
$profiles[$profile]['usage'] +=1;
|
256 |
+
}
|
257 |
+
}
|
258 |
+
return $profiles;
|
259 |
+
}
|
260 |
+
|
261 |
+
/*
|
262 |
+
* store community options and set any missing defaults to the first available option
|
263 |
+
*
|
264 |
+
* @since 0.1.0
|
265 |
+
*/
|
266 |
+
public function set_community_resources($community_id, $update_first_project_callback = FALSE) {
|
267 |
+
$client = new Lingotek_API();
|
268 |
+
$refresh_success = array(
|
269 |
+
'projects' => FALSE,
|
270 |
+
'workflows' => FALSE,
|
271 |
+
);
|
272 |
+
|
273 |
+
$api_data = $client->get_projects($community_id);
|
274 |
+
$projects = array();
|
275 |
+
if ($api_data && $api_data != 'empty') {
|
276 |
+
foreach ($api_data->entities as $project) {
|
277 |
+
$projects[$project->properties->id] = $project->properties->title;
|
278 |
+
}
|
279 |
+
if($update_first_project_callback){
|
280 |
+
$client = new Lingotek_API();
|
281 |
+
$project_id = current(array_keys($projects));//update callback for 1st project
|
282 |
+
$client->update_callback_url($project_id);
|
283 |
+
}
|
284 |
+
natcasesort($projects); //order by title (case-insensitive)
|
285 |
+
$refresh_success['projects'] = TRUE;
|
286 |
+
}
|
287 |
+
else if ($api_data == 'empty') {
|
288 |
+
add_settings_error('lingotek_community_resources', 'error', __('Your Community currently has no projects.', 'wp-lingotek'), 'error');
|
289 |
+
}
|
290 |
+
else {
|
291 |
+
add_settings_error('lingotek_community_resources', 'error', __('Projects could not be refreshed', 'wp-lingotek'), 'error');
|
292 |
+
}
|
293 |
+
|
294 |
+
$api_data = $client->get_workflows($community_id);
|
295 |
+
$workflows = array();
|
296 |
+
if ($api_data) {
|
297 |
+
foreach ($api_data->entities as $workflow) {
|
298 |
+
$workflows[$workflow->properties->id] = $workflow->properties->title;
|
299 |
+
}
|
300 |
+
natcasesort($workflows); //order by title (case-insensitive)
|
301 |
+
$refresh_success['workflows'] = TRUE;
|
302 |
+
}
|
303 |
+
else {
|
304 |
+
add_settings_error('lingotek_community_resources', 'error', __('Workflows could not be refreshed', 'wp-lingotek'), 'error');
|
305 |
+
}
|
306 |
+
|
307 |
+
$api_data = $client->get_filters();
|
308 |
+
$filters = array();
|
309 |
+
if ($api_data->properties->total > 0) {
|
310 |
+
foreach ($api_data->entities as $filter) {
|
311 |
+
if (!$filter->properties->is_public) {
|
312 |
+
$filters[$filter->properties->id] = $filter->properties->title;
|
313 |
+
}
|
314 |
+
if ($filter->properties->title == 'okf_json@with-html-subfilter.fprm' || $filter->properties->title == 'okf_html@wordpress.fprm') {
|
315 |
+
$filters[$filter->properties->id] = $filter->properties->title;
|
316 |
+
}
|
317 |
+
}
|
318 |
+
$primary_filter_id = array_search('okf_json@with-html-subfilter.fprm', $filters);
|
319 |
+
$secondary_filter_id = array_search('okf_html@wordpress.fprm', $filters);
|
320 |
+
$defaults = get_option('lingotek_defaults');
|
321 |
+
if($defaults == NULL) {
|
322 |
+
$defaults['primary_filter_id'] = $primary_filter_id;
|
323 |
+
$defaults['secondary_filter_id'] = $secondary_filter_id;
|
324 |
+
update_option('lingotek_defaults', $defaults);
|
325 |
+
}
|
326 |
+
}
|
327 |
+
|
328 |
+
$resources = array(
|
329 |
+
'projects' => $projects,
|
330 |
+
'workflows' => $workflows,
|
331 |
+
'filters' => $filters,
|
332 |
+
);
|
333 |
+
|
334 |
+
if ($refresh_success['projects'] == TRUE || $refresh_success['workflows'] == TRUE) {
|
335 |
+
update_option('lingotek_community_resources', $resources);
|
336 |
+
$this->ensure_valid_defaults();
|
337 |
+
}
|
338 |
+
return $refresh_success;
|
339 |
+
}
|
340 |
+
|
341 |
+
public function ensure_valid_defaults() {
|
342 |
+
$resources = get_option('lingotek_community_resources');
|
343 |
+
$defaults = get_option('lingotek_defaults');
|
344 |
+
$valid_default = array();
|
345 |
+
foreach ($resources as $resource_key => $options) {
|
346 |
+
$key = substr($resource_key,0,strlen($resource_key)-1)."_id";
|
347 |
+
$valid_default[$key] = 0;
|
348 |
+
if(!is_array($defaults)) {
|
349 |
+
continue;
|
350 |
+
}
|
351 |
+
foreach ($options as $option_key => $option_val) {
|
352 |
+
if(!array_key_exists($key, $defaults)){
|
353 |
+
continue;
|
354 |
+
}
|
355 |
+
if ($option_key === $defaults[$key]) {
|
356 |
+
$valid_default[$key] = 1;
|
357 |
+
break;
|
358 |
+
}
|
359 |
+
}
|
360 |
+
}
|
361 |
+
foreach ($valid_default as $key => $valid) {
|
362 |
+
$resource_key = substr($key,0,strpos($key,'_'))."s";
|
363 |
+
if ($valid) {
|
364 |
+
continue;
|
365 |
+
}
|
366 |
+
else {
|
367 |
+
$defaults[$key] = current(array_keys($resources[$resource_key]));
|
368 |
+
}
|
369 |
+
}
|
370 |
+
$num_valid_defaults = array_sum($valid_default);
|
371 |
+
|
372 |
+
if($num_valid_defaults < count($valid_default)){
|
373 |
+
add_settings_error( 'lingotek_defaults', 'community-selected', sprintf(__('Your <a href="%s"><i>Defaults</i></a> have been updated to valid options for this community.', 'wp-lingotek'), admin_url('admin.php?page=wp-lingotek_settings&sm=defaults')), 'updated' );
|
374 |
+
}
|
375 |
+
unset($defaults['filter_id']);
|
376 |
+
update_option('lingotek_defaults', $defaults);
|
377 |
+
}
|
378 |
+
|
379 |
+
/*
|
380 |
+
* displays the admin manage page
|
381 |
+
*
|
382 |
+
* @since 0.1.0
|
383 |
+
*/
|
384 |
+
public function display_manage_page() {
|
385 |
+
if (self::has_token_details()) {
|
386 |
+
include(LINGOTEK_ADMIN_INC . '/view-manage.php');
|
387 |
+
}
|
388 |
+
else {
|
389 |
+
$this->display_settings_page();
|
390 |
+
}
|
391 |
+
}
|
392 |
+
|
393 |
+
/*
|
394 |
+
* add screen option on translations->manage page
|
395 |
+
*
|
396 |
+
* @since 0.2
|
397 |
+
*/
|
398 |
+
public function load_manage_page() {
|
399 |
+
add_screen_option('per_page', array(
|
400 |
+
'label' => __('Strings groups', 'wp-lingotek'),
|
401 |
+
'default' => 10,
|
402 |
+
'option' => 'lingotek_strings_per_page'
|
403 |
+
));
|
404 |
+
}
|
405 |
+
|
406 |
+
/*
|
407 |
+
* save screen option from translations->manage page
|
408 |
+
*
|
409 |
+
* @since 0.2
|
410 |
+
*/
|
411 |
+
public function set_screen_option($status, $option, $value) {
|
412 |
+
if ('lingotek_strings_per_page' == $option)
|
413 |
+
return $value;
|
414 |
+
return $status;
|
415 |
+
}
|
416 |
+
|
417 |
+
/*
|
418 |
+
* displays the admin manage page
|
419 |
+
*
|
420 |
+
* @since 0.1.0
|
421 |
+
*/
|
422 |
+
public function display_dashboard_page() {
|
423 |
+
$token_details = self::has_token_details();
|
424 |
+
if ($token_details) {
|
425 |
+
$community_id = get_option('lingotek_community');
|
426 |
+
$defaults = get_option('lingotek_defaults');
|
427 |
+
$user = wp_get_current_user();
|
428 |
+
|
429 |
+
// The data that will be passed to the Lingotek GMC dashboard
|
430 |
+
$cms_data = array(
|
431 |
+
// lingotek
|
432 |
+
"community_id"=> $community_id,
|
433 |
+
"external_id"=> $token_details['login_id'],
|
434 |
+
//"vault_id"=> $defaults['vault_id'],
|
435 |
+
"workflow_id"=> $defaults['workflow_id'],
|
436 |
+
"project_id"=> $defaults['project_id'],
|
437 |
+
"first_name"=> $user->display_name,
|
438 |
+
"last_name"=> '',
|
439 |
+
"email"=> get_bloginfo('admin_email'),
|
440 |
+
// cms
|
441 |
+
"cms_site_id"=> site_url(),
|
442 |
+
"cms_site_key"=> site_url(),
|
443 |
+
"cms_site_name"=> get_bloginfo('name'),
|
444 |
+
"cms_type"=> "Wordpress",
|
445 |
+
"cms_version"=> get_bloginfo('version'),
|
446 |
+
"cms_tag"=> LINGOTEK_PLUGIN_SLUG,
|
447 |
+
"locale"=> pll_current_language('lingotek_locale'),
|
448 |
+
"module_version"=> LINGOTEK_VERSION,
|
449 |
+
"endpoint_url" => $this->get_dashboard_endpoint()
|
450 |
+
);
|
451 |
+
include(LINGOTEK_ADMIN_INC . '/view-dashboard.php');
|
452 |
+
}
|
453 |
+
else {
|
454 |
+
$this->display_settings_page();
|
455 |
+
}
|
456 |
+
}
|
457 |
+
|
458 |
+
/*
|
459 |
+
* returns the access token when present, otherwise returns FALSE
|
460 |
+
*
|
461 |
+
* @since 0.1.0
|
462 |
+
*/
|
463 |
+
public static function has_token_details() {
|
464 |
+
$token_details = get_option('lingotek_token');
|
465 |
+
$has_token = FALSE;
|
466 |
+
if ($token_details !== FALSE && key_exists('access_token', $token_details) && key_exists('login_id', $token_details) && strlen($token_details['access_token']) && strlen($token_details['login_id'])) {
|
467 |
+
$has_token = TRUE;
|
468 |
+
return $token_details;
|
469 |
+
}
|
470 |
+
return $has_token;
|
471 |
+
}
|
472 |
+
|
473 |
+
public function display_network_settings_page() {
|
474 |
+
if (is_multisite() && self::has_token_details()) {
|
475 |
+
include(LINGOTEK_ADMIN_INC . '/view-network.php');
|
476 |
+
}
|
477 |
+
else {
|
478 |
+
$this->display_settings_page();
|
479 |
+
}
|
480 |
+
}
|
481 |
+
|
482 |
+
/*
|
483 |
+
* adds a Lingotek settings option in the network admin page
|
484 |
+
*
|
485 |
+
* @since 0.1.0
|
486 |
+
*/
|
487 |
+
public function add_network_admin_menu() {
|
488 |
+
add_submenu_page('settings.php', __('Lingotek Settings', 'wp-lingotek'), __('Lingotek Settings', 'wp-lingotek'), 'manage_network_options', $this->plugin_slug . '_network', array($this, 'display_network_settings_page'), 'dashicons-translation');
|
489 |
+
}
|
490 |
+
|
491 |
+
public function display_tutorial_page() {
|
492 |
+
if (self::has_token_details()) {
|
493 |
+
include(LINGOTEK_ADMIN_INC . '/view-tutorial.php');
|
494 |
+
}
|
495 |
+
else {
|
496 |
+
$this->display_settings_page();
|
497 |
+
}
|
498 |
+
}
|
499 |
+
|
500 |
+
}
|
admin/content-table.php
ADDED
@@ -0,0 +1,200 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if(!class_exists('WP_List_Table')){
|
4 |
+
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' ); // since WP 3.1
|
5 |
+
}
|
6 |
+
|
7 |
+
class Lingotek_Content_Table extends WP_List_Table {
|
8 |
+
protected $profiles, $content_types;
|
9 |
+
|
10 |
+
/*
|
11 |
+
* constructor
|
12 |
+
*
|
13 |
+
* @since 0.2
|
14 |
+
*/
|
15 |
+
function __construct($content_types) {
|
16 |
+
parent::__construct(array(
|
17 |
+
'plural' => 'lingotek-content', // do not translate (used for css class)
|
18 |
+
'ajax' => false
|
19 |
+
));
|
20 |
+
|
21 |
+
$this->profiles = Lingotek::get_profiles();
|
22 |
+
$this->content_types = $content_types;
|
23 |
+
}
|
24 |
+
|
25 |
+
/*
|
26 |
+
* displays the item information in a column (default case)
|
27 |
+
*
|
28 |
+
* @since 0.2
|
29 |
+
*
|
30 |
+
* @param array $item
|
31 |
+
* @param string $column_name
|
32 |
+
* @return string
|
33 |
+
*/
|
34 |
+
function column_name($item) {
|
35 |
+
global $polylang;
|
36 |
+
|
37 |
+
printf('<span class="content-type-name">%s</span>', esc_html($item['name']));
|
38 |
+
|
39 |
+
// the source language for strings is always the default language
|
40 |
+
if ('string' != $item['type']) {
|
41 |
+
printf('<a id="id[%s]" class="dashicons dashicons-arrow-right" onclick="%s" href="#"></a>',
|
42 |
+
esc_attr($item['type']),
|
43 |
+
"
|
44 |
+
d1 = document.getElementById('sources-name[{$item['type']}]');
|
45 |
+
d2 = document.getElementById('sources-profile[{$item['type']}]');
|
46 |
+
c = 'dashicons dashicons-arrow-';
|
47 |
+
if (c+'right' == this.className) {
|
48 |
+
this.className = c+'down';
|
49 |
+
d1.style.display = d2.style.display = '';
|
50 |
+
}
|
51 |
+
else {
|
52 |
+
this.className = c+'right';
|
53 |
+
d1.style.display = d2.style.display = 'none';
|
54 |
+
}
|
55 |
+
return false;
|
56 |
+
"
|
57 |
+
);
|
58 |
+
|
59 |
+
printf('<ul class="sources-name" id="sources-name[%s]" style="display:none;">', $item['type']);
|
60 |
+
foreach ($polylang->model->get_languages_list() as $language) {
|
61 |
+
printf('<li>%s</li>', sprintf(__('%s source', 'wp-lingotek'), esc_html($language->name)));
|
62 |
+
}
|
63 |
+
echo '</ul>';
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
+
/*
|
68 |
+
* displays the item profile dropdown list
|
69 |
+
*
|
70 |
+
* @since 0.2
|
71 |
+
*
|
72 |
+
* @param array $item
|
73 |
+
* @return string
|
74 |
+
*/
|
75 |
+
function column_profile($item) {
|
76 |
+
global $polylang;
|
77 |
+
|
78 |
+
printf('<select class="content-type-profile" name="%1$s" id="%1$s">', $item['type'] . '[profile]');
|
79 |
+
foreach ($this->profiles as $key => $profile) {
|
80 |
+
$selected = (isset($item['profile']) && $key == $item['profile']) ? 'selected="selected"' : '';
|
81 |
+
echo "\n\t<option value='" . esc_attr($key) . "' $selected>" . esc_html($profile['name']) . '</option>';
|
82 |
+
}
|
83 |
+
echo '</select>';
|
84 |
+
|
85 |
+
$options = array_merge(array('default' => array('name' => __('Use content type default', 'wp-lingotek'))), $this->profiles);
|
86 |
+
|
87 |
+
// the source language for strings is always the default language
|
88 |
+
if ('string' != $item['type']) {
|
89 |
+
printf('<ul class="sources-profile" id="sources-profile[%s]" style="display:none;">', $item['type']);
|
90 |
+
foreach ($polylang->model->get_languages_list() as $language) {
|
91 |
+
printf('<li><select name="%1$s" id="%1$s">', $item['type'] . '[sources][' . $language->slug . ']' );
|
92 |
+
foreach ($options as $key => $profile) {
|
93 |
+
$selected = (isset($item['sources'][$language->slug]) && $key == $item['sources'][$language->slug]) ? 'selected="selected"' : '';
|
94 |
+
echo "\n\t<option value='" . esc_attr($key) . "' $selected>" . esc_html($profile['name']) . '</option>';
|
95 |
+
}
|
96 |
+
echo '</select></li>';
|
97 |
+
}
|
98 |
+
echo '</ul>';
|
99 |
+
}
|
100 |
+
}
|
101 |
+
|
102 |
+
/*
|
103 |
+
* displays checkboxes in fields columns
|
104 |
+
* can handle fields with one or two keys
|
105 |
+
*
|
106 |
+
* @since 0.2
|
107 |
+
*
|
108 |
+
* @param array $labels
|
109 |
+
* @param array $values
|
110 |
+
* @param string $parent
|
111 |
+
*/
|
112 |
+
protected function display_fields($labels, $values, $name) {
|
113 |
+
foreach ($labels as $key => $str) {
|
114 |
+
if (is_array($str)) {
|
115 |
+
$this->display_fields($str, isset($values[$key]) ? $values[$key] : array(), $name . "[$key]");
|
116 |
+
}
|
117 |
+
else {
|
118 |
+
printf(
|
119 |
+
'<li><label><input name="%s" type="checkbox" value="1" %s /> %s</label></li>',
|
120 |
+
esc_attr($name . "[$key]"),
|
121 |
+
empty($values[$key]) ? 'checked="checked"' : '',
|
122 |
+
esc_html($str)
|
123 |
+
);
|
124 |
+
}
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
/*
|
129 |
+
* displays the item fields checkboxes
|
130 |
+
*
|
131 |
+
* @since 0.2
|
132 |
+
*
|
133 |
+
* @param array $item
|
134 |
+
* @return string
|
135 |
+
*/
|
136 |
+
function column_fields($item) {
|
137 |
+
if (!empty($item['fields'])) {
|
138 |
+
echo '<ul class="content-type-fields">';
|
139 |
+
$this->display_fields($item['fields']['label'], isset($item['fields']['value']) ? $item['fields']['value'] : array() , $item['type'] . '[fields]');
|
140 |
+
echo '</ul>';
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
/*
|
145 |
+
* gets the list of columns
|
146 |
+
*
|
147 |
+
* @since 0.2
|
148 |
+
*
|
149 |
+
* @return array the list of column titles
|
150 |
+
*/
|
151 |
+
function get_columns() {
|
152 |
+
return array(
|
153 |
+
'name' => __('Content Type', 'wp-lingotek'),
|
154 |
+
'profile' => __('Profile', 'wp-lingotek'),
|
155 |
+
'fields' => __('Fields', 'wp-lingotek'),
|
156 |
+
);
|
157 |
+
}
|
158 |
+
|
159 |
+
/*
|
160 |
+
* gets the list of sortable columns
|
161 |
+
*
|
162 |
+
* @since 0.2
|
163 |
+
*
|
164 |
+
* @return array
|
165 |
+
*/
|
166 |
+
function get_sortable_columns() {
|
167 |
+
return array(
|
168 |
+
'name' => array('name', false),
|
169 |
+
);
|
170 |
+
}
|
171 |
+
|
172 |
+
/*
|
173 |
+
* prepares the list of items ofr displaying
|
174 |
+
*
|
175 |
+
* @since 0.2
|
176 |
+
*
|
177 |
+
* @param array $data
|
178 |
+
*/
|
179 |
+
function prepare_items($data = array()) {
|
180 |
+
$per_page = $this->get_items_per_page('lingotek_content_per_page');
|
181 |
+
$this->_column_headers = array($this->get_columns(), array(), $this->get_sortable_columns());
|
182 |
+
|
183 |
+
function usort_reorder($a, $b){
|
184 |
+
$result = strcmp($a[$_REQUEST['orderby']], $b[$_REQUEST['orderby']]); // determine sort order
|
185 |
+
return (empty($_REQUEST['order']) || $_REQUEST['order'] == 'asc') ? $result : -$result; // send final sort direction to usort
|
186 |
+
};
|
187 |
+
|
188 |
+
if (!empty($_REQUEST['orderby'])) // no sort by default
|
189 |
+
usort($data, 'usort_reorder');
|
190 |
+
|
191 |
+
$total_items = count($data);
|
192 |
+
$this->items = array_slice($data, ($this->get_pagenum() - 1) * $per_page, $per_page);
|
193 |
+
|
194 |
+
$this->set_pagination_args(array(
|
195 |
+
'total_items' => $total_items,
|
196 |
+
'per_page' => $per_page,
|
197 |
+
'total_pages' => ceil($total_items/$per_page)
|
198 |
+
));
|
199 |
+
}
|
200 |
+
}
|
admin/filters-columns.php
ADDED
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* Modifies Polylang filters
|
5 |
+
*
|
6 |
+
* @since 0.1
|
7 |
+
*/
|
8 |
+
class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
|
9 |
+
public $lgtm; // Lingotek model
|
10 |
+
|
11 |
+
/*
|
12 |
+
* cosntructor
|
13 |
+
*
|
14 |
+
* @since 0.1
|
15 |
+
*
|
16 |
+
* @param object $polylang Polylang object
|
17 |
+
*/
|
18 |
+
public function __construct(&$polylang) {
|
19 |
+
parent::__construct($polylang);
|
20 |
+
|
21 |
+
$this->lgtm = &$GLOBALS['wp_lingotek']->model;
|
22 |
+
|
23 |
+
// FIXME remove quick edit and bulk edit for now waiting for a solution to remove it only for uploaded documents
|
24 |
+
remove_filter('quick_edit_custom_box', array(&$this, 'quick_edit_custom_box'), 10, 2);
|
25 |
+
remove_filter('bulk_edit_custom_box', array(&$this, 'quick_edit_custom_box'), 10, 2);
|
26 |
+
}
|
27 |
+
|
28 |
+
/*
|
29 |
+
* adds languages and translations columns in posts, pages, media, categories and tags tables
|
30 |
+
* overrides Polylang method to display all languages including the filtered one
|
31 |
+
* as well as displaying a tooltip with the language name and locale when there is no flag
|
32 |
+
*
|
33 |
+
* @since 0.2
|
34 |
+
*
|
35 |
+
* @param array $columns list of table columns
|
36 |
+
* @param string $before the column before which we want to add our languages
|
37 |
+
* @return array modified list of columns
|
38 |
+
*/
|
39 |
+
protected function add_column($columns, $before) {
|
40 |
+
if ($n = array_search($before, array_keys($columns))) {
|
41 |
+
$end = array_slice($columns, $n);
|
42 |
+
$columns = array_slice($columns, 0, $n);
|
43 |
+
}
|
44 |
+
|
45 |
+
foreach ($this->model->get_languages_list() as $language) {
|
46 |
+
$columns['language_'.$language->slug] = $language->flag ? $language->flag :
|
47 |
+
sprintf('<a href="" title="%s">%s</a>',
|
48 |
+
esc_html("$language->name ($language->locale)"),
|
49 |
+
esc_html($language->slug)
|
50 |
+
);
|
51 |
+
}
|
52 |
+
|
53 |
+
return isset($end) ? array_merge($columns, $end) : $columns;
|
54 |
+
}
|
55 |
+
|
56 |
+
/*
|
57 |
+
* fills the language and translations columns in the posts and taxonomies lists tables
|
58 |
+
* take care that when doing ajax inline edit, the post or term may not be updated in database yet
|
59 |
+
*
|
60 |
+
* @since 0.2
|
61 |
+
*
|
62 |
+
* @param string $type 'post' or 'term'
|
63 |
+
* @param string $column column name
|
64 |
+
* @param int $object_id id of the current object in row
|
65 |
+
*/
|
66 |
+
protected function _column($type, $column, $object_id) {
|
67 |
+
$action = 'post' == $type ? 'inline-save' : 'inline-save-tax';
|
68 |
+
$inline = defined('DOING_AJAX') && $_REQUEST['action'] == $action && isset($_POST['inline_lang_choice']);
|
69 |
+
$lang = $inline ?
|
70 |
+
$this->model->get_language($_POST['inline_lang_choice']) :
|
71 |
+
call_user_func(array($this->model, 'get_' . $type . '_language'), $object_id);
|
72 |
+
|
73 |
+
if (false === strpos($column, 'language_') || !$lang)
|
74 |
+
return '';
|
75 |
+
|
76 |
+
$language = $this->model->get_language(substr($column, 9));
|
77 |
+
|
78 |
+
// FIXME should I suppress quick edit?
|
79 |
+
// yes for uploaded posts, but I will need js as the field is built for all posts
|
80 |
+
// /!\ also take care not add this field two times when translations are managed by Polylang
|
81 |
+
|
82 |
+
// hidden field containing the post language for quick edit (used to filter categories since Polylang 1.7)
|
83 |
+
if ($column == $this->get_first_language_column() /*&& !$this->model->get_translation_id('post', $post_id)*/)
|
84 |
+
printf('<div class="hidden" id="lang_%d">%s</div>', esc_attr($object_id), esc_html($lang->slug));
|
85 |
+
|
86 |
+
$id = ($inline && $lang->slug != $this->model->get_language($_POST['old_lang'])->slug) ?
|
87 |
+
($language->slug == $lang->slug ? $object_id : 0) :
|
88 |
+
call_user_func(array($this->model, 'get_' . $type), $object_id, $language);
|
89 |
+
|
90 |
+
$document = $this->lgtm->get_group($type, $object_id);
|
91 |
+
|
92 |
+
// FIXME not very clean
|
93 |
+
$actions = 'post' == $type ? $GLOBALS['wp_lingotek']->post_actions : $GLOBALS['wp_lingotek']->term_actions;
|
94 |
+
|
95 |
+
$profile = Lingotek_Model::get_profile($this->content_type, $language);
|
96 |
+
$disabled = 'disabled' == $profile['profile'];
|
97 |
+
|
98 |
+
// post ready for upload
|
99 |
+
if ($this->lgtm->can_upload($type, $object_id) && $object_id == $id)
|
100 |
+
return $disabled ?
|
101 |
+
('post' == $type ? parent::post_column($column, $object_id) : parent::term_column('', $column, $object_id)) :
|
102 |
+
$actions->upload_icon($object_id);
|
103 |
+
|
104 |
+
// translation disabled
|
105 |
+
elseif (isset($document->source) && $document->is_disabled_target($language))
|
106 |
+
return 'post' == $type ? parent::post_column($column, $object_id) : parent::term_column('', $column, $object_id);
|
107 |
+
|
108 |
+
// source post is uploaded
|
109 |
+
elseif (isset($document->source) && $document->source == $id) {
|
110 |
+
// source ready for upload
|
111 |
+
if ($this->lgtm->can_upload($type, $id))
|
112 |
+
return $actions->upload_icon($id);
|
113 |
+
|
114 |
+
// importing source
|
115 |
+
if ($id == $object_id && 'importing' == $document->status)
|
116 |
+
return Lingotek_Actions::importing_icon($document);
|
117 |
+
|
118 |
+
// uploaded
|
119 |
+
return 'post' == $type ? Lingotek_Post_actions::uploaded_icon($id) : Lingotek_Term_actions::uploaded_icon($id);
|
120 |
+
}
|
121 |
+
|
122 |
+
// translations
|
123 |
+
elseif (isset($document->translations[$language->locale]) || (isset($document->source) && 'current' == $document->status))
|
124 |
+
return Lingotek_Actions::translation_icon($document, $language);
|
125 |
+
|
126 |
+
// translations exist but are not managed by Lingotek TMS
|
127 |
+
elseif (empty($document->source))
|
128 |
+
return $object_id == $id && !$disabled ?
|
129 |
+
$actions->upload_icon($object_id, true) :
|
130 |
+
('post' == $type ? parent::post_column($column, $object_id) : parent::term_column('', $column, $object_id));
|
131 |
+
|
132 |
+
// no translation
|
133 |
+
else
|
134 |
+
return '<div class="lingotek-color dashicons dashicons-no"></div>';
|
135 |
+
}
|
136 |
+
|
137 |
+
/*
|
138 |
+
* fills the language and translations columns in the posts, pages and media library tables
|
139 |
+
* take care that when doing ajax inline edit, the post may not be updated in database yet
|
140 |
+
*
|
141 |
+
* @since 0.1
|
142 |
+
*
|
143 |
+
* @param string $column column name
|
144 |
+
* @param int $post_id
|
145 |
+
*/
|
146 |
+
public function post_column($column, $post_id) {
|
147 |
+
$this->content_type = get_post_type($post_id);
|
148 |
+
echo $this->_column('post', $column, $post_id);
|
149 |
+
}
|
150 |
+
|
151 |
+
/*
|
152 |
+
* fills the language and translations columns in the categories and post tags tables
|
153 |
+
* take care that when doing ajax inline edit, the term may not be updated in database yet
|
154 |
+
*
|
155 |
+
* @since 0.2
|
156 |
+
*
|
157 |
+
* @param string $empty not used
|
158 |
+
* @param string $column column name
|
159 |
+
* @param int term_id
|
160 |
+
*/
|
161 |
+
public function term_column($empty, $column, $term_id) {
|
162 |
+
$this->content_type = $GLOBALS['taxonomy'];
|
163 |
+
return $this->_column('term', $column, $term_id);
|
164 |
+
}
|
165 |
+
}
|
admin/filters-media.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* Manages automatic upload
|
5 |
+
*
|
6 |
+
* @since 0.2
|
7 |
+
*/
|
8 |
+
class Lingotek_Filters_Media extends PLL_Admin_Filters_Media {
|
9 |
+
public $lgtm; // Lingotek model
|
10 |
+
|
11 |
+
/*
|
12 |
+
* Constructor
|
13 |
+
*
|
14 |
+
* @since 0.2
|
15 |
+
*/
|
16 |
+
public function __construct(&$polylang) {
|
17 |
+
parent::__construct($polylang);
|
18 |
+
|
19 |
+
$this->lgtm = &$GLOBALS['wp_lingotek']->model;
|
20 |
+
|
21 |
+
add_action('edit_attachment', array(&$this, 'edit_attachment'));
|
22 |
+
add_action('add_attachment', array(&$this, 'add_attachment'), 11); // after Polylang
|
23 |
+
}
|
24 |
+
|
25 |
+
/*
|
26 |
+
* marks the attachment as edited if needed
|
27 |
+
*
|
28 |
+
* @since 0.2
|
29 |
+
*
|
30 |
+
* @param int $post_id
|
31 |
+
*/
|
32 |
+
public function edit_attachment($post_id) {
|
33 |
+
$document = $this->lgtm->get_group('post', $post_id);
|
34 |
+
|
35 |
+
// FIXME how to check if the attachment is really modified?
|
36 |
+
if ($document && $post_id == $document->source) {
|
37 |
+
$document->source_edited();
|
38 |
+
|
39 |
+
if ($document->is_automatic_upload()) {
|
40 |
+
$this->lgtm->upload_post($post_id);
|
41 |
+
}
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
/*
|
46 |
+
* uploads an attachment when saved for the first time
|
47 |
+
*
|
48 |
+
* @since 0.2
|
49 |
+
|
50 |
+
* @param int $post_id
|
51 |
+
*/
|
52 |
+
public function add_attachment($post_id) {
|
53 |
+
if ($this->model->is_translated_post_type('attachment') && 'automatic' == Lingotek_Model::get_profile_option('upload', 'attachment', $this->model->get_post_language($post_id)) && $this->lgtm->can_upload('post', $post_id))
|
54 |
+
$this->lgtm->upload_post($post_id);
|
55 |
+
}
|
56 |
+
}
|
admin/filters-post.php
ADDED
@@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* Modifies Polylang filters
|
5 |
+
* Manages automatic upload
|
6 |
+
* Manages delete / trash sync
|
7 |
+
*
|
8 |
+
* @since 0.1
|
9 |
+
*/
|
10 |
+
class Lingotek_Filters_Post extends PLL_Admin_Filters_Post {
|
11 |
+
public $lgtm; // Lingotek model
|
12 |
+
|
13 |
+
/*
|
14 |
+
* Constructor
|
15 |
+
*
|
16 |
+
* @since 0.1
|
17 |
+
*/
|
18 |
+
public function __construct(&$polylang) {
|
19 |
+
parent::__construct($polylang);
|
20 |
+
|
21 |
+
$this->lgtm = &$GLOBALS['wp_lingotek']->model;
|
22 |
+
|
23 |
+
// automatic upload
|
24 |
+
add_action('post_updated', array(&$this, 'post_updated'), 10, 3);
|
25 |
+
|
26 |
+
// trash sync
|
27 |
+
add_action('trashed_post', array(&$this, 'trash_post'));
|
28 |
+
add_action('untrashed_post', array(&$this, 'untrash_post'));
|
29 |
+
}
|
30 |
+
|
31 |
+
/*
|
32 |
+
* controls whether to display the language metabox or not
|
33 |
+
*
|
34 |
+
* @since 0.1
|
35 |
+
*/
|
36 |
+
public function add_meta_boxes($post_type) {
|
37 |
+
global $post_ID;
|
38 |
+
if ($this->model->is_translated_post_type($post_type)) {
|
39 |
+
$document = $this->lgtm->get_group('post', $post_ID);
|
40 |
+
if (empty($document->source))
|
41 |
+
parent::add_meta_boxes($post_type);
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
/*
|
46 |
+
* uploads a post when saved for the first time
|
47 |
+
*
|
48 |
+
* @since 0.2
|
49 |
+
|
50 |
+
* @param int $post_id
|
51 |
+
* @param object $post
|
52 |
+
* @param bool $update whether it is an update or not
|
53 |
+
*/
|
54 |
+
public function save_post($post_id, $post, $update) {
|
55 |
+
if (!$this->model->is_translated_post_type($post->post_type))
|
56 |
+
return;
|
57 |
+
|
58 |
+
parent::save_post($post_id, $post, $update);
|
59 |
+
|
60 |
+
if (!wp_is_post_revision($post_id) && 'auto-draft' != $post->post_status && Lingotek_Group_Post::is_valid_auto_upload_post_status($post->post_status) && 'automatic' == Lingotek_Model::get_profile_option('upload', $post->post_type, $this->model->get_post_language($post_id)) && !(isset($_POST['action']) && 'heartbeat' == $_POST['action']) && $this->lgtm->can_upload('post', $post_id)) {
|
61 |
+
$this->lgtm->upload_post($post_id);
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
/*
|
66 |
+
* checks if we can act when saving a post
|
67 |
+
*
|
68 |
+
* @since 0.1
|
69 |
+
*
|
70 |
+
* @param int $post_id
|
71 |
+
* @param object $post
|
72 |
+
* @param bool $update whether it is an update or not
|
73 |
+
* @return bool
|
74 |
+
*/
|
75 |
+
protected function can_save_post_data($post_id, $post, $update) {
|
76 |
+
// does nothing except on post types which are filterable
|
77 |
+
// also don't act on revisions
|
78 |
+
if (!$this->model->is_translated_post_type($post->post_type) || wp_is_post_revision($post_id))
|
79 |
+
return false;
|
80 |
+
|
81 |
+
// capability check
|
82 |
+
// as 'wp_insert_post' can be called from outside WP admin
|
83 |
+
$post_type_object = get_post_type_object($post->post_type);
|
84 |
+
if (($update && !current_user_can($post_type_object->cap->edit_post, $post_id)) || (!$update && !current_user_can($post_type_object->cap->create_posts)))
|
85 |
+
return false;
|
86 |
+
|
87 |
+
return true;
|
88 |
+
}
|
89 |
+
|
90 |
+
/*
|
91 |
+
* marks the post as edited if needed
|
92 |
+
*
|
93 |
+
* @since 0.1
|
94 |
+
*
|
95 |
+
* @param int $post_id
|
96 |
+
* @param object $post_after
|
97 |
+
* @param object $post_before
|
98 |
+
*/
|
99 |
+
public function post_updated($post_id, $post_after, $post_before) {
|
100 |
+
if ($this->can_save_post_data($post_id, $post_after, true)) {
|
101 |
+
$document = $this->lgtm->get_group('post', $post_id);
|
102 |
+
|
103 |
+
if ($document && $post_id == $document->source && md5(Lingotek_Group_Post::get_content($post_after)) != md5(Lingotek_Group_Post::get_content($post_before))) {
|
104 |
+
$document->source_edited();
|
105 |
+
|
106 |
+
if ($document->is_automatic_upload() && Lingotek_Group_Post::is_valid_auto_upload_post_status($post_after->post_status)) {
|
107 |
+
$this->lgtm->upload_post($post_id);
|
108 |
+
}
|
109 |
+
}
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
/*
|
114 |
+
* get translations ids to sync for delete / trash / untrash
|
115 |
+
* since we can't sync all translations as we get conflicts when attempting to act two times on the same
|
116 |
+
*
|
117 |
+
* @since 0.2
|
118 |
+
*
|
119 |
+
* @param int $post_id
|
120 |
+
* @return array
|
121 |
+
*/
|
122 |
+
protected function get_translations_to_sync($post_id) {
|
123 |
+
// don't synchronize disassociated posts
|
124 |
+
$group = $this->lgtm->get_group('post', $post_id);
|
125 |
+
if (empty($group->source))
|
126 |
+
return array();
|
127 |
+
|
128 |
+
if (isset($_REQUEST['media']) && is_array($_REQUEST['media']))
|
129 |
+
$post_ids = array_map('intval', $_REQUEST['media']);
|
130 |
+
elseif (!empty($_REQUEST['post']) && is_array($_REQUEST['post']))
|
131 |
+
$post_ids = array_map('intval', $_REQUEST['post']);
|
132 |
+
|
133 |
+
$post_ids[] = $post_id;
|
134 |
+
return array_diff($this->model->get_translations('post', $post_id), $post_ids);
|
135 |
+
}
|
136 |
+
|
137 |
+
/*
|
138 |
+
* deletes the Lingotek document when a source document is deleted
|
139 |
+
*
|
140 |
+
* @since 0.1
|
141 |
+
*
|
142 |
+
* @param int $post_id
|
143 |
+
*/
|
144 |
+
public function delete_post($post_id) {
|
145 |
+
static $avoid_recursion = array();
|
146 |
+
|
147 |
+
if (!wp_is_post_revision($post_id) && !in_array($post_id, $avoid_recursion)) {
|
148 |
+
// sync delete is not needed when emptying the bin as trash is synced
|
149 |
+
if (empty($_REQUEST['delete_all'])) {
|
150 |
+
$tr_ids = $this->get_translations_to_sync($post_id);
|
151 |
+
$avoid_recursion = array_merge($avoid_recursion, array_values($tr_ids));
|
152 |
+
foreach ($tr_ids as $tr_id) {
|
153 |
+
wp_delete_post($tr_id, true); // forces deletion for the translations which are not already in the list
|
154 |
+
}
|
155 |
+
}
|
156 |
+
$this->lgtm->delete_post($post_id);
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
/*
|
161 |
+
* sync trash
|
162 |
+
*
|
163 |
+
* @since 0.1
|
164 |
+
*
|
165 |
+
* @param int $post_id
|
166 |
+
*/
|
167 |
+
public function trash_post($post_id) {
|
168 |
+
foreach ($this->get_translations_to_sync($post_id) as $tr_id)
|
169 |
+
wp_trash_post($tr_id);
|
170 |
+
}
|
171 |
+
|
172 |
+
/*
|
173 |
+
* sync untrash
|
174 |
+
*
|
175 |
+
* @since 0.1
|
176 |
+
*
|
177 |
+
* @param int $post_id
|
178 |
+
*/
|
179 |
+
public function untrash_post($post_id) {
|
180 |
+
foreach ($this->get_translations_to_sync($post_id) as $tr_id)
|
181 |
+
wp_untrash_post($tr_id);
|
182 |
+
}
|
183 |
+
}
|
admin/filters-term.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* Modifies Polylang filters
|
5 |
+
* Manages automatic upload
|
6 |
+
*
|
7 |
+
* @since 0.2
|
8 |
+
*/
|
9 |
+
class Lingotek_Filters_Term extends PLL_Admin_Filters_Term {
|
10 |
+
public $lgtm; // Lingotek model
|
11 |
+
protected $old_term; // used to save old md5sum of a term when it is edited
|
12 |
+
|
13 |
+
/*
|
14 |
+
* Constructor
|
15 |
+
*
|
16 |
+
* @since 0.2
|
17 |
+
*/
|
18 |
+
public function __construct(&$polylang) {
|
19 |
+
parent::__construct($polylang);
|
20 |
+
|
21 |
+
$this->lgtm = &$GLOBALS['wp_lingotek']->model;
|
22 |
+
|
23 |
+
add_action('edit_terms', array(&$this, 'save_old_term'), 10, 2);
|
24 |
+
add_action('edited_term', array(&$this, 'edited_term'), 10, 3);
|
25 |
+
}
|
26 |
+
|
27 |
+
/*
|
28 |
+
* controls whether to display the language metabox or not
|
29 |
+
*
|
30 |
+
* @since 0.2
|
31 |
+
*/
|
32 |
+
public function edit_term_form($tag) {
|
33 |
+
if ($this->model->is_translated_taxonomy($tag->taxonomy)) {
|
34 |
+
$document = $this->lgtm->get_group('term', $tag->term_id);
|
35 |
+
if (empty($document->source))
|
36 |
+
parent::edit_term_form($tag);
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
/*
|
41 |
+
* uploads a term when saved for the first time
|
42 |
+
*
|
43 |
+
* @since 0.2
|
44 |
+
|
45 |
+
* @param int $term_id
|
46 |
+
* @param int $tt_id term taxononomy id
|
47 |
+
* @param string $taxonomy
|
48 |
+
*/
|
49 |
+
public function save_term($term_id, $tt_id, $taxonomy) {
|
50 |
+
if (!$this->model->is_translated_taxonomy($taxonomy))
|
51 |
+
return;
|
52 |
+
|
53 |
+
parent::save_term($term_id, $tt_id, $taxonomy);
|
54 |
+
|
55 |
+
if ('automatic' == Lingotek_Model::get_profile_option('upload', $taxonomy, $this->model->get_term_language($term_id)) && $this->lgtm->can_upload('term', $term_id))
|
56 |
+
$this->lgtm->upload_term($term_id, $taxonomy);
|
57 |
+
}
|
58 |
+
|
59 |
+
/*
|
60 |
+
* saves the md5sum of a term before it is edited
|
61 |
+
*
|
62 |
+
* @since 0.2
|
63 |
+
*
|
64 |
+
* @param int $term_id
|
65 |
+
* @param string $taxonomy
|
66 |
+
*/
|
67 |
+
public function save_old_term($term_id, $taxonomy) {
|
68 |
+
if (pll_is_translated_taxonomy($taxonomy))
|
69 |
+
$this->old_term = md5(Lingotek_Group_Term::get_content(get_term($term_id, $taxonomy)));
|
70 |
+
}
|
71 |
+
|
72 |
+
/*
|
73 |
+
* marks the term as edited if needed
|
74 |
+
*
|
75 |
+
* @since 0.2
|
76 |
+
*
|
77 |
+
* @param int $term_id
|
78 |
+
* @param int $tt_id not used
|
79 |
+
* @param string $taxonomy
|
80 |
+
*/
|
81 |
+
public function edited_term($term_id, $tt_id, $taxonomy) {
|
82 |
+
if (pll_is_translated_taxonomy($taxonomy)) {
|
83 |
+
$document = $this->lgtm->get_group('term', $term_id);
|
84 |
+
|
85 |
+
if ($document && $term_id == $document->source && md5(Lingotek_Group_Term::get_content(get_term($term_id, $taxonomy))) != $this->old_term) {
|
86 |
+
$document->source_edited();
|
87 |
+
|
88 |
+
if ($document->is_automatic_upload()) {
|
89 |
+
$this->lgtm->upload_term($term_id, $taxonomy);
|
90 |
+
}
|
91 |
+
}
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
/*
|
96 |
+
* get translations ids to sync for delete
|
97 |
+
* since we can't sync all translations as we get conflicts when attempting to act two times on the same
|
98 |
+
*
|
99 |
+
* @since 0.2
|
100 |
+
*
|
101 |
+
* @param int $term_id
|
102 |
+
* @return array
|
103 |
+
*/
|
104 |
+
protected function get_translations_to_sync($term_id) {
|
105 |
+
// don't synchronize disassociated terms
|
106 |
+
$group = $this->lgtm->get_group('term', $term_id);
|
107 |
+
if (empty($group->source))
|
108 |
+
return array();
|
109 |
+
|
110 |
+
if (isset($_REQUEST['delete_tags']) && is_array($_REQUEST['delete_tags']))
|
111 |
+
$term_ids = array_map('intval', $_REQUEST['delete_tags']);
|
112 |
+
|
113 |
+
$term_ids[] = $term_id;
|
114 |
+
return array_diff($this->model->get_translations('term', $term_id), $term_ids);
|
115 |
+
}
|
116 |
+
|
117 |
+
/*
|
118 |
+
* deletes the Lingotek document when a source document is deleted
|
119 |
+
*
|
120 |
+
* @since 0.2
|
121 |
+
*
|
122 |
+
* @param int $term_id
|
123 |
+
*/
|
124 |
+
public function delete_term($term_id) {
|
125 |
+
$taxonomy = substr(current_filter(), 7);
|
126 |
+
foreach ($this->get_translations_to_sync($term_id) as $tr_id) {
|
127 |
+
wp_delete_term($tr_id, $taxonomy); // forces deletion for the translations which are not already in the list
|
128 |
+
}
|
129 |
+
$this->lgtm->delete_term($term_id);
|
130 |
+
}
|
131 |
+
}
|
admin/manage/view-string-groups.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<h3><?php _e('String Groups', 'wp-lingotek'); ?></h3>
|
2 |
+
<p class="description"><?php printf(__('Manage group translation of system, widget, and plugin-specific strings. View individual strings on the <a href="%s"><b>Strings</b></a> page.', 'wp-lingotek'), 'admin.php?page=wp-lingotek_manage&sm=strings'); ?></p>
|
3 |
+
<?php
|
4 |
+
|
5 |
+
$profile = Lingotek_Model::get_profile('string', $this->pllm->get_language($this->pllm->options['default_lang']));
|
6 |
+
|
7 |
+
if ('disabled' == $profile['profile']) {
|
8 |
+
printf('<div class="error" style="border-left: 4px solid #ffba00;"><p>%s</p></div>', // no warning class in WP 4.0, color form .update-nag
|
9 |
+
sprintf(__('The strings translation is disabled in %sContent Type Configuration%s.', 'wp-lingotek'),
|
10 |
+
'<a href="' . admin_url('admin.php?page=wp-lingotek_settings&sm=content') . '">',
|
11 |
+
'</a>'
|
12 |
+
)
|
13 |
+
);
|
14 |
+
}
|
15 |
+
else {
|
16 |
+
$string_actions = $GLOBALS['wp_lingotek']->string_actions;
|
17 |
+
$table = new Lingotek_Strings_Table($string_actions);
|
18 |
+
$action = $table->current_action();
|
19 |
+
if (!empty($action))
|
20 |
+
$string_actions->manage_actions($action);
|
21 |
+
|
22 |
+
$data = Lingotek_Model::get_strings();
|
23 |
+
foreach ($data as $key => $row)
|
24 |
+
$data[$key]['row'] = $key; // store the row number for convenience
|
25 |
+
|
26 |
+
$table->prepare_items($data); ?>
|
27 |
+
|
28 |
+
<form id="lingotek-strings" method="post" action="admin.php?page=wp-lingotek_manage&noheader=true"><?php
|
29 |
+
$table->display(); ?>
|
30 |
+
</form><?php
|
31 |
+
|
32 |
+
foreach (Lingotek_String_actions::$actions as $action => $strings) {
|
33 |
+
if (!empty($_GET['bulk-lingotek-' . $action]))
|
34 |
+
printf('<div id="lingotek-progressdialog" title="%s"><div id="lingotek-progressbar"></div></div>', $strings['progress']);
|
35 |
+
}
|
36 |
+
}
|
admin/manage/view-strings.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<h3 style="padding-top:0; margin-top:0; margin-bottom:-25px;"><?php _e('Strings', 'wp-lingotek'); ?> <a href="options-general.php?page=mlang&tab=strings" title="<?php _e('Edit on Polylang Strings Translation page', 'wp-lingotek'); ?>" class="dashicons dashicons-edit"></a></h3>
|
2 |
+
|
3 |
+
<?php
|
4 |
+
$listlanguages = $GLOBALS['polylang']->model->get_languages_list();
|
5 |
+
|
6 |
+
// FIXME now mainly copy paste of Polylang
|
7 |
+
|
8 |
+
// get the strings to translate
|
9 |
+
$data = PLL_Admin_Strings::get_strings();
|
10 |
+
|
11 |
+
$selected = empty($_REQUEST['group']) ? -1 : $_REQUEST['group'];
|
12 |
+
foreach ($data as $key=>$row) {
|
13 |
+
$groups[] = $row['context']; // get the groups
|
14 |
+
|
15 |
+
// filter for search string
|
16 |
+
if (($selected !=-1 && $row['context'] != $selected) || (!empty($_REQUEST['s']) && stripos($row['name'], $_REQUEST['s']) === false && stripos($row['string'], $_REQUEST['s']) === false))
|
17 |
+
unset ($data[$key]);
|
18 |
+
}
|
19 |
+
|
20 |
+
$groups = array_unique($groups);
|
21 |
+
|
22 |
+
// load translations
|
23 |
+
foreach ($listlanguages as $language) {
|
24 |
+
// filters by language if requested
|
25 |
+
if (($lg = get_user_meta(get_current_user_id(), 'pll_filter_content', true)) && $language->slug != $lg)
|
26 |
+
continue;
|
27 |
+
|
28 |
+
$mo = new PLL_MO();
|
29 |
+
$mo->import_from_db($language);
|
30 |
+
foreach ($data as $key=>$row) {
|
31 |
+
$data[$key]['translations'][$language->slug] = $mo->translate($row['string']);
|
32 |
+
$data[$key]['row'] = $key; // store the row number for convenience
|
33 |
+
}
|
34 |
+
}
|
35 |
+
|
36 |
+
// get an array with language slugs as keys, names as values
|
37 |
+
$languages = array_combine(wp_list_pluck($listlanguages, 'slug'), wp_list_pluck($listlanguages, 'name'));
|
38 |
+
|
39 |
+
$string_table = new Lingotek_Table_String(compact('languages', 'groups', 'selected'));
|
40 |
+
$string_table->prepare_items($data); ?>
|
41 |
+
|
42 |
+
<div class="form-wrap">
|
43 |
+
<form id="string-translation" method="post" action="admin.php?page=mlang&tab=strings&noheader=true">
|
44 |
+
<input type="hidden" name="pll_action" value="string-translation" /><?php
|
45 |
+
$string_table->search_box(__('Search translations', 'wp-lingotek'), 'translations' );
|
46 |
+
wp_nonce_field('string-translation', '_wpnonce_string-translation');
|
47 |
+
$string_table->display(); ?>
|
48 |
+
</form>
|
49 |
+
</div>
|
admin/post-actions.php
ADDED
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* Adds row and bulk actions to posts, pages and media list
|
5 |
+
* Manages actions which trigger communication with Lingotek TMS
|
6 |
+
|
7 |
+
*
|
8 |
+
* @since 0.2
|
9 |
+
*/
|
10 |
+
class Lingotek_Post_actions extends Lingotek_Actions {
|
11 |
+
|
12 |
+
/*
|
13 |
+
* Constructor
|
14 |
+
*
|
15 |
+
* @since 0.2
|
16 |
+
*/
|
17 |
+
public function __construct() {
|
18 |
+
parent::__construct('post');
|
19 |
+
|
20 |
+
// row actions
|
21 |
+
add_filter('post_row_actions', array(&$this, 'post_row_actions'), 10, 2);
|
22 |
+
add_filter('page_row_actions', array(&$this, 'post_row_actions'), 10, 2); // hierarchical post types
|
23 |
+
add_filter('media_row_actions', array(&$this, 'post_row_actions'), 10, 2);
|
24 |
+
|
25 |
+
// add bulk actions
|
26 |
+
add_action('admin_footer-edit.php', array(&$this, 'add_bulk_actions')); // FIXME admin_print_footer_scripts instead?
|
27 |
+
add_action('admin_footer-upload.php', array(&$this, 'add_bulk_actions'));
|
28 |
+
|
29 |
+
// manage bulk actions, row actions and icon actions
|
30 |
+
add_action('load-edit.php', array(&$this, 'manage_actions'));
|
31 |
+
add_action('load-upload.php', array(&$this, 'manage_actions'));
|
32 |
+
}
|
33 |
+
|
34 |
+
/*
|
35 |
+
* get the language of a post
|
36 |
+
*
|
37 |
+
* @since 0.2
|
38 |
+
*
|
39 |
+
* @param int $post_id
|
40 |
+
* @return object
|
41 |
+
*/
|
42 |
+
protected function get_language($post_id) {
|
43 |
+
return $this->pllm->get_post_language($post_id);
|
44 |
+
}
|
45 |
+
|
46 |
+
/*
|
47 |
+
* displays the icon of an uploaded post with the relevant link
|
48 |
+
*
|
49 |
+
* @since 0.2
|
50 |
+
*
|
51 |
+
* @param int $id
|
52 |
+
*/
|
53 |
+
public static function uploaded_icon($id) {
|
54 |
+
return self::display_icon('uploaded', get_edit_post_link($id));
|
55 |
+
}
|
56 |
+
|
57 |
+
/*
|
58 |
+
* adds a row action link
|
59 |
+
*
|
60 |
+
* @since 0.1
|
61 |
+
*
|
62 |
+
* @param array $actions list of action links
|
63 |
+
* @param object $post
|
64 |
+
* @return array
|
65 |
+
*/
|
66 |
+
public function post_row_actions($actions, $post) {
|
67 |
+
if ($this->pllm->is_translated_post_type($post->post_type)) {
|
68 |
+
$actions = $this->_row_actions($actions, $post->ID);
|
69 |
+
|
70 |
+
$language = $this->pllm->get_post_language($post->ID);
|
71 |
+
if (!empty($language)) {
|
72 |
+
$profile = Lingotek_Model::get_profile($post->post_type, $language);
|
73 |
+
if ('disabled' == $profile['profile'])
|
74 |
+
unset($actions['lingotek-upload']);
|
75 |
+
}
|
76 |
+
}
|
77 |
+
return $actions;
|
78 |
+
}
|
79 |
+
|
80 |
+
/*
|
81 |
+
* adds actions to bulk dropdown in posts list table
|
82 |
+
*
|
83 |
+
* @since 0.1
|
84 |
+
*/
|
85 |
+
public function add_bulk_actions() {
|
86 |
+
if (isset($GLOBALS['post_type']) && $this->pllm->is_translated_post_type($GLOBALS['post_type']))
|
87 |
+
$this->_add_bulk_actions();
|
88 |
+
}
|
89 |
+
|
90 |
+
/*
|
91 |
+
* manages Lingotek specific actions before WordPress acts
|
92 |
+
*
|
93 |
+
* @since 0.1
|
94 |
+
*/
|
95 |
+
public function manage_actions() {
|
96 |
+
global $typenow;
|
97 |
+
$post_type = 'load-upload.php' == current_filter() ? 'attachment' : $typenow;
|
98 |
+
|
99 |
+
if (!$this->pllm->is_translated_post_type($post_type))
|
100 |
+
return;
|
101 |
+
|
102 |
+
// get the action
|
103 |
+
// $typenow is empty for media
|
104 |
+
$wp_list_table = _get_list_table(empty($typenow) ? 'WP_Media_List_Table' : 'WP_Posts_List_Table');
|
105 |
+
$action = $wp_list_table->current_action();
|
106 |
+
|
107 |
+
if (empty($action))
|
108 |
+
return;
|
109 |
+
|
110 |
+
$redirect = remove_query_arg( array('action', 'action2', 'tags_input', 'post_author', 'comment_status', 'ping_status', '_status', 'post', 'bulk_edit', 'post_view'), wp_get_referer() );
|
111 |
+
if (!$redirect)
|
112 |
+
$redirect = admin_url("edit.php?post_type=$typenow");
|
113 |
+
|
114 |
+
switch($action) {
|
115 |
+
case 'bulk-lingotek-upload':
|
116 |
+
$type = empty($typenow) ? 'media' : 'post';
|
117 |
+
if (empty($_REQUEST[$type]))
|
118 |
+
return;
|
119 |
+
|
120 |
+
$post_ids = array();
|
121 |
+
|
122 |
+
foreach (array_map('intval', $_REQUEST[$type]) as $post_id) {
|
123 |
+
// safe upload
|
124 |
+
if ($this->lgtm->can_upload('post', $post_id))
|
125 |
+
$post_ids[] = $post_id;
|
126 |
+
|
127 |
+
// the document is already translated so will be overwritten
|
128 |
+
elseif(($document = $this->lgtm->get_group('post', $post_id)) && empty($document->source)) {
|
129 |
+
// take care to upload only one post in a translation group
|
130 |
+
$intersect = array_intersect($post_ids, $this->pllm->get_translations('post', $post_id));
|
131 |
+
if (empty($intersect)) {
|
132 |
+
$post_ids[] = $post_id;
|
133 |
+
$redirect = add_query_arg('lingotek_warning', 1, $redirect);
|
134 |
+
}
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
// check if translation is disabled
|
139 |
+
if (!empty($post_ids)) {
|
140 |
+
foreach ($post_ids as $key => $post_id) {
|
141 |
+
$language = $this->pllm->get_post_language($post_id);
|
142 |
+
$profile = Lingotek_Model::get_profile($post_type, $language);
|
143 |
+
if ('disabled' == $profile['profile'])
|
144 |
+
unset($post_ids[$key]);
|
145 |
+
}
|
146 |
+
}
|
147 |
+
|
148 |
+
case 'bulk-lingotek-request':
|
149 |
+
case 'bulk-lingotek-download':
|
150 |
+
case 'bulk-lingotek-status':
|
151 |
+
case 'bulk-lingotek-delete':
|
152 |
+
if (empty($post_ids)) {
|
153 |
+
$type = empty($typenow) ? 'media' : 'post';
|
154 |
+
if (empty($_REQUEST[$type]))
|
155 |
+
return;
|
156 |
+
|
157 |
+
$post_ids = array_map('intval', $_REQUEST[$type]);
|
158 |
+
}
|
159 |
+
|
160 |
+
empty($typenow) ? check_admin_referer('bulk-media') : check_admin_referer('bulk-posts');
|
161 |
+
|
162 |
+
$redirect = add_query_arg($action, 1, $redirect);
|
163 |
+
$redirect = add_query_arg('ids', implode(',', $post_ids), $redirect);
|
164 |
+
|
165 |
+
break;
|
166 |
+
|
167 |
+
case 'lingotek-upload':
|
168 |
+
check_admin_referer('lingotek-upload');
|
169 |
+
$this->lgtm->upload_post((int) $_GET['post']);
|
170 |
+
break;
|
171 |
+
|
172 |
+
default:
|
173 |
+
if (!$this->_manage_actions($action))
|
174 |
+
return; // do not redirect if this is not one of our actions
|
175 |
+
|
176 |
+
}
|
177 |
+
|
178 |
+
wp_redirect($redirect);
|
179 |
+
exit();
|
180 |
+
|
181 |
+
}
|
182 |
+
|
183 |
+
/*
|
184 |
+
* ajax response to upload documents and showing progress
|
185 |
+
*
|
186 |
+
* @since 0.1
|
187 |
+
*/
|
188 |
+
public function ajax_upload() {
|
189 |
+
check_ajax_referer('lingotek_progress', '_lingotek_nonce');
|
190 |
+
$this->lgtm->upload_post((int) $_POST['id']);
|
191 |
+
die();
|
192 |
+
}
|
193 |
+
}
|
admin/profiles-table.php
ADDED
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if(!class_exists('WP_List_Table')){
|
4 |
+
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' ); // since WP 3.1
|
5 |
+
}
|
6 |
+
|
7 |
+
class Lingotek_Profiles_Table extends WP_List_Table {
|
8 |
+
|
9 |
+
/*
|
10 |
+
* constructor
|
11 |
+
*
|
12 |
+
* @since 0.2
|
13 |
+
*/
|
14 |
+
function __construct() {
|
15 |
+
parent::__construct(array(
|
16 |
+
'plural' => 'lingotek-profiles', // do not translate (used for css class)
|
17 |
+
'ajax' => false
|
18 |
+
));
|
19 |
+
}
|
20 |
+
|
21 |
+
/*
|
22 |
+
* displays the item information in a column (default case)
|
23 |
+
*
|
24 |
+
* @since 0.2
|
25 |
+
*
|
26 |
+
* @param array $item
|
27 |
+
* @param string $column_name
|
28 |
+
* @return string
|
29 |
+
*/
|
30 |
+
function column_default($item, $column_name) {
|
31 |
+
return isset($item[$column_name]) ? esc_html($item[$column_name]) : '';
|
32 |
+
}
|
33 |
+
|
34 |
+
/*
|
35 |
+
* displays the edit link in actions column
|
36 |
+
*
|
37 |
+
* @since 0.2
|
38 |
+
*
|
39 |
+
* @param array $item
|
40 |
+
* @return string
|
41 |
+
*/
|
42 |
+
function column_usage($item){
|
43 |
+
return empty($item['usage']) ?
|
44 |
+
__('No content types', 'wp-lingotek') :
|
45 |
+
sprintf(_n('1 content type', '%d content types', $item['usage'], 'wp-lingotek'), number_format_i18n($item['usage']));
|
46 |
+
}
|
47 |
+
|
48 |
+
/*
|
49 |
+
* displays the edit link in actions column
|
50 |
+
*
|
51 |
+
* @since 0.2
|
52 |
+
*
|
53 |
+
* @param array $item
|
54 |
+
* @return string
|
55 |
+
*/
|
56 |
+
function column_actions($item){
|
57 |
+
$actions = array();
|
58 |
+
|
59 |
+
if ('disabled' != $item['profile'])
|
60 |
+
$actions[] = sprintf(
|
61 |
+
'<a href=%s>%s</a>',
|
62 |
+
esc_url(admin_url('admin.php?page=wp-lingotek_settings&sm=edit-profile&profile='.$item['profile'])),
|
63 |
+
__('Edit', 'wp-lingotek')
|
64 |
+
);
|
65 |
+
|
66 |
+
if (!in_array($item['profile'], array('automatic', 'manual', 'disabled')) && empty($item['usage']))
|
67 |
+
$actions[] = sprintf(
|
68 |
+
'<a href="%s" onclick = "return confirm(\'%s\');">%s</a>',
|
69 |
+
esc_url(wp_nonce_url('admin.php?page=wp-lingotek_settings&sm=profiles&lingotek_action=delete-profile&noheader=true&profile='.$item['profile'], 'delete-profile')),
|
70 |
+
__('You are about to permanently delete this profile. Are you sure?', 'wp-lingotek'),
|
71 |
+
__('Delete', 'wp-lingotek')
|
72 |
+
);
|
73 |
+
|
74 |
+
return implode(' | ', $actions);
|
75 |
+
}
|
76 |
+
|
77 |
+
/*
|
78 |
+
* gets the list of columns
|
79 |
+
*
|
80 |
+
* @since 0.2
|
81 |
+
*
|
82 |
+
* @return array the list of column titles
|
83 |
+
*/
|
84 |
+
function get_columns() {
|
85 |
+
return array(
|
86 |
+
'name' => __('Profile name', 'wp-lingotek'),
|
87 |
+
'usage' => __('Usage', 'wp-lingotek'),
|
88 |
+
'actions' => __('Actions', 'wp-lingotek'),
|
89 |
+
);
|
90 |
+
}
|
91 |
+
|
92 |
+
/*
|
93 |
+
* gets the list of sortable columns
|
94 |
+
*
|
95 |
+
* @since 0.2
|
96 |
+
*
|
97 |
+
* @return array
|
98 |
+
*/
|
99 |
+
function get_sortable_columns() {
|
100 |
+
return array(
|
101 |
+
'name' => array('name', false),
|
102 |
+
);
|
103 |
+
}
|
104 |
+
|
105 |
+
/*
|
106 |
+
* prepares the list of items ofr displaying
|
107 |
+
*
|
108 |
+
* @since 0.2
|
109 |
+
*
|
110 |
+
* @param array $data
|
111 |
+
*/
|
112 |
+
function prepare_items($data = array()) {
|
113 |
+
$per_page = $this->get_items_per_page('lingotek_profiles_per_page');
|
114 |
+
$this->_column_headers = array($this->get_columns(), array(), $this->get_sortable_columns());
|
115 |
+
|
116 |
+
function usort_reorder($a, $b){
|
117 |
+
$result = strcmp($a[$_REQUEST['orderby']], $b[$_REQUEST['orderby']]); // determine sort order
|
118 |
+
return (empty($_REQUEST['order']) || $_REQUEST['order'] == 'asc') ? $result : -$result; // send final sort direction to usort
|
119 |
+
};
|
120 |
+
|
121 |
+
if (!empty($_REQUEST['orderby'])) // no sort by default
|
122 |
+
usort($data, 'usort_reorder');
|
123 |
+
|
124 |
+
$total_items = count($data);
|
125 |
+
$this->items = array_slice($data, ($this->get_pagenum() - 1) * $per_page, $per_page);
|
126 |
+
|
127 |
+
$this->set_pagination_args(array(
|
128 |
+
'total_items' => $total_items,
|
129 |
+
'per_page' => $per_page,
|
130 |
+
'total_pages' => ceil($total_items/$per_page)
|
131 |
+
));
|
132 |
+
}
|
133 |
+
}
|
admin/settings.php
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="wrap">
|
2 |
+
<h2><?php _e('Settings', 'wp-lingotek'); ?></h2>
|
3 |
+
|
4 |
+
<?php
|
5 |
+
if (strlen($access_token)) {
|
6 |
+
?>
|
7 |
+
|
8 |
+
<?php
|
9 |
+
|
10 |
+
$menu_items = array(
|
11 |
+
'account' => __('Account', 'wp-lingotek'),
|
12 |
+
);
|
13 |
+
|
14 |
+
$community_required_menu_items = array(
|
15 |
+
'defaults' => __('Defaults', 'wp-lingotek'),
|
16 |
+
'profiles' => __('Translation Profiles', 'wp-lingotek'),
|
17 |
+
'content' => __('Content Type Configuration', 'wp-lingotek'),
|
18 |
+
'preferences' => __('Preferences', 'wp-lingotek'),
|
19 |
+
//'advanced' => __('Advanced', 'wp-lingotek'),
|
20 |
+
//'logging' => __('Logging', 'wp-lingotek'),
|
21 |
+
'utilities' => __('Utilities', 'wp-lingotek'),
|
22 |
+
);
|
23 |
+
|
24 |
+
if($community_id !== FALSE){
|
25 |
+
$menu_items = array_merge($menu_items, $community_required_menu_items);
|
26 |
+
}
|
27 |
+
|
28 |
+
?>
|
29 |
+
|
30 |
+
<h3 class="nav-tab-wrapper">
|
31 |
+
<?php
|
32 |
+
$menu_item_index = 0;
|
33 |
+
foreach ($menu_items as $menu_item_key => $menu_item_label) {
|
34 |
+
$use_as_default = ($menu_item_index === 0 && !isset($_GET['sm'])) ? TRUE : FALSE;
|
35 |
+
$alias = NULL;
|
36 |
+
// custom sub sub-menus
|
37 |
+
if(isset($_GET['sm']) && $_GET['sm'] == "edit-profile") {
|
38 |
+
$alias = "profiles";
|
39 |
+
}
|
40 |
+
?>
|
41 |
+
|
42 |
+
<a class="nav-tab <?php if ($use_as_default || (isset($_GET['sm']) && $_GET['sm'] == $menu_item_key) || $alias == $menu_item_key): ?> nav-tab-active<?php endif; ?>"
|
43 |
+
href="admin.php?page=<?php echo $_GET['page']; ?>&sm=<?php echo $menu_item_key; ?>"><?php echo $menu_item_label; ?></a>
|
44 |
+
<?php
|
45 |
+
$menu_item_index++;
|
46 |
+
}
|
47 |
+
?>
|
48 |
+
</h3>
|
49 |
+
|
50 |
+
<?php
|
51 |
+
settings_errors();
|
52 |
+
$submenu = isset($_GET['sm']) ? $_GET['sm'] : 'account';
|
53 |
+
$dir = dirname(__FILE__) . '/settings/';
|
54 |
+
$filename = $dir . 'view-' . $submenu . ".php";
|
55 |
+
if (file_exists($filename))
|
56 |
+
include $filename;
|
57 |
+
else
|
58 |
+
echo "TO-DO: create <i>" . 'settings/view-' . $submenu . ".php</i>";
|
59 |
+
?>
|
60 |
+
|
61 |
+
<?php
|
62 |
+
}
|
63 |
+
?>
|
64 |
+
</div>
|
admin/settings/connect-account.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php /* Redirect Access Token */ ?>
|
2 |
+
<script>
|
3 |
+
var hash = window.location.hash;
|
4 |
+
if (hash.length && hash.indexOf("access_token") !== -1) {
|
5 |
+
var parts = hash.substring(1).split('=');
|
6 |
+
var access_token = parts[1];
|
7 |
+
var url_with_access_token = window.location.origin + window.location.pathname + window.location.search + '&access_token=' + access_token;
|
8 |
+
window.location.href = url_with_access_token;
|
9 |
+
}
|
10 |
+
else if (window.location.search.indexOf("connect") != -1) {
|
11 |
+
window.location.href = "<?php echo $connect_url ?>";
|
12 |
+
}
|
13 |
+
</script>
|
14 |
+
<?php /* Connect Your Account Button */ ?>
|
15 |
+
<div class="wrap">
|
16 |
+
<h2><?php _e('Connect Your Account', 'wp-lingotek') ?></h2>
|
17 |
+
<div>
|
18 |
+
<p class="description">
|
19 |
+
<?php _e('Get started by clicking the button below to connect your Lingotek account to this Wordpress installation.', 'wp-lingotek') ?>
|
20 |
+
</p>
|
21 |
+
<hr/>
|
22 |
+
<p>
|
23 |
+
<a class="button button-large button-hero" href="<?php echo $connect_account_cloak_url_new ?>">
|
24 |
+
<img src="<?php echo LINGOTEK_URL; ?>/img/lingotek-icon.png" style="padding: 0 4px 2px 0;" align="absmiddle"/> <?php _e('Connect New Account', 'wp-lingotek') ?>
|
25 |
+
</a>
|
26 |
+
</p>
|
27 |
+
<hr/>
|
28 |
+
<p class="description"><?php echo sprintf( __('Do you already have a Lingotek account? <a href="%s">Connect Lingotek Account</a>', 'wp-lingotek'), esc_attr($connect_account_cloak_url_prod)) ?></p>
|
29 |
+
<p class="description"><?php echo sprintf( __('Do you have a Lingotek sandbox account? <a href="%s">Connect Sandbox Account</a>', 'wp-lingotek'), esc_attr($connect_account_cloak_url_test)) ?></p>
|
30 |
+
</div>
|
31 |
+
</div>
|
admin/settings/view-account.php
ADDED
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if (!$community_id) {
|
3 |
+
$ltk_client = new Lingotek_API();
|
4 |
+
$ltk_communities = $ltk_client->get_communities();
|
5 |
+
$ltk_num_communities = $ltk_communities->properties->total;
|
6 |
+
if ($ltk_num_communities == 1) {
|
7 |
+
$ltk_community_id = $ltk_communities->entities[0]->properties->id;
|
8 |
+
$this->set_community_resources($ltk_community_id, TRUE);
|
9 |
+
echo '<script type="text/javascript">document.body.innerHTML = ""; window.location = "admin.php?page=wp-lingotek_tutorial";</script>';
|
10 |
+
}
|
11 |
+
}
|
12 |
+
?>
|
13 |
+
|
14 |
+
<h3><?php _e('Account', 'wp-lingotek'); ?></h3>
|
15 |
+
<p class="description"><?php _e('Lingotek account connection and community selection.', 'wp-lingotek'); ?></p>
|
16 |
+
|
17 |
+
<table class="form-table">
|
18 |
+
<tr>
|
19 |
+
<th scope="row">
|
20 |
+
<?php _e('Connected', 'wp-lingotek') ?>
|
21 |
+
<a id="cd-show-link" class="dashicons dashicons-arrow-right" onclick="document.getElementById('connection-details').style.display = ''; document.getElementById('cd-hide-link').style.display = ''; this.style.display = 'none'; return false;"></a>
|
22 |
+
<a id="cd-hide-link" class="dashicons dashicons-arrow-down" onclick="document.getElementById('connection-details').style.display = 'none'; document.getElementById('cd-show-link').style.display = ''; this.style.display = 'none'; return false;" style="display: none;"></a>
|
23 |
+
</th>
|
24 |
+
<td>
|
25 |
+
<?php _e('Yes', 'wp-lingotek') ?><span title="<?php _e('Connected', 'wp-lingotek') ?>" class="dashicons dashicons-yes" style="color: green;"></span>
|
26 |
+
</td>
|
27 |
+
</tr>
|
28 |
+
<tbody id="connection-details" style="display: none;">
|
29 |
+
<tr>
|
30 |
+
<th scope="row"><?php echo __('Login ID', 'wp-lingotek') ?></th>
|
31 |
+
<td>
|
32 |
+
<label>
|
33 |
+
<?php
|
34 |
+
printf(
|
35 |
+
'<input name="%s" class="regular-text" type="text" value="%s" disabled="disabled" />', 'login_id', $token_details['login_id']
|
36 |
+
);
|
37 |
+
?>
|
38 |
+
</label>
|
39 |
+
</td>
|
40 |
+
</tr>
|
41 |
+
<tr>
|
42 |
+
<th scope="row"><?php echo __('Access Token', 'wp-lingotek') ?></th>
|
43 |
+
<td>
|
44 |
+
<label>
|
45 |
+
<?php
|
46 |
+
printf(
|
47 |
+
'<input name="%s" class="regular-text" type="password" value="%s" disabled="disabled" style="display: none;" />', 'access_token', $token_details['access_token']
|
48 |
+
);
|
49 |
+
printf(
|
50 |
+
'<input name="%s" class="regular-text" type="text" value="%s" disabled="disabled" />', 'access_token', $token_details['access_token']
|
51 |
+
);
|
52 |
+
?>
|
53 |
+
</label>
|
54 |
+
</td>
|
55 |
+
</tr>
|
56 |
+
<tr>
|
57 |
+
<th scope="row"><?php echo __('API Endpoint', 'wp-lingotek') ?></th>
|
58 |
+
<td>
|
59 |
+
<label>
|
60 |
+
<?php
|
61 |
+
printf(
|
62 |
+
'<input name="%s" class="regular-text" type="text" value="%s" disabled="disabled" />', 'base_url', $base_url
|
63 |
+
);
|
64 |
+
?>
|
65 |
+
</label>
|
66 |
+
</td>
|
67 |
+
</tr>
|
68 |
+
<tr>
|
69 |
+
<th></th>
|
70 |
+
<td>
|
71 |
+
<?php
|
72 |
+
$confirm_message = __('Are you sure you would like to disconnect your Lingotek account? \n\nAfter disconnecting, you will need to re-connect an account to continue using Lingotek.', 'wp-lingotek');
|
73 |
+
echo '<a class="button" href="' . $redirect_url . '&delete_access_token=true" onclick="return confirm(\'' . $confirm_message . '\')">' . __('Disconnect', 'wp-lingotek') . '</a>';
|
74 |
+
?>
|
75 |
+
</td>
|
76 |
+
</tr>
|
77 |
+
</tbody>
|
78 |
+
</table>
|
79 |
+
|
80 |
+
<hr/>
|
81 |
+
|
82 |
+
<form method="post" action="admin.php?page=<?php echo $page_key; ?>" class="validate"> <?php /* &noheader=true */ ?>
|
83 |
+
<?php wp_nonce_field($page_key, '_wpnonce_' . $page_key); ?>
|
84 |
+
|
85 |
+
<table class="form-table">
|
86 |
+
<tr>
|
87 |
+
<th scope="row"><label for="lingotek_community"><?php _e('Community', 'wp-lingotek') ?></label></th>
|
88 |
+
<td>
|
89 |
+
<select name="lingotek_community" id="lingotek_community">
|
90 |
+
<?php
|
91 |
+
$default_community_id = $community_id;
|
92 |
+
|
93 |
+
$client = new Lingotek_API();
|
94 |
+
|
95 |
+
// Community
|
96 |
+
$api_communities = $client->get_communities();
|
97 |
+
$communities = array();
|
98 |
+
foreach ($api_communities->entities as $community) {
|
99 |
+
$communities[$community->properties->id] = $community->properties->title; // . ' (' . $community->properties->id . ')';
|
100 |
+
}
|
101 |
+
|
102 |
+
$num_communities = count($communities);
|
103 |
+
if($num_communities == 1 && !$community_id){
|
104 |
+
update_option('lingotek_community', current(array_keys($communities)));
|
105 |
+
}
|
106 |
+
if(!$community_id && $num_communities > 1) {
|
107 |
+
echo "\n\t" . '<option value="">'.__('Select', 'wp-lingotek').'...</option>';
|
108 |
+
}
|
109 |
+
foreach ($communities as $community_id_option => $community_title) {
|
110 |
+
$selected = ($default_community_id == $community_id_option) ? 'selected="selected"' : '';
|
111 |
+
echo "\n\t" . '<option value="' . esc_attr($community_id_option) . '" '.$selected.'>' . $community_title . '</option>';
|
112 |
+
}
|
113 |
+
?>
|
114 |
+
</select>
|
115 |
+
</td>
|
116 |
+
</tr>
|
117 |
+
</table>
|
118 |
+
|
119 |
+
<?php submit_button(__('Save Changes', 'wp-lingotek'), 'primary', 'submit', false); ?>
|
120 |
+
</form>
|
admin/settings/view-content.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
global $polylang;
|
4 |
+
|
5 |
+
foreach ($polylang->model->get_translated_post_types() as $post_type) {
|
6 |
+
$post_type_object = get_post_type_object($post_type);
|
7 |
+
$data[$post_type] = array(
|
8 |
+
'type' => $post_type,
|
9 |
+
'name' => $post_type_object->labels->name,
|
10 |
+
'fields' => array(
|
11 |
+
'label' => Lingotek_Group_Post::get_content_type_fields($post_type)
|
12 |
+
)
|
13 |
+
);
|
14 |
+
}
|
15 |
+
|
16 |
+
foreach ($polylang->model->get_translated_taxonomies() as $tax) {
|
17 |
+
$taxonomy = get_taxonomy($tax);
|
18 |
+
$data[$tax] = array(
|
19 |
+
'type' => $tax,
|
20 |
+
'name' => $taxonomy->labels->name,
|
21 |
+
'fields' => array(
|
22 |
+
'label' => Lingotek_Group_Term::get_content_type_fields($tax)
|
23 |
+
)
|
24 |
+
);
|
25 |
+
}
|
26 |
+
|
27 |
+
$data['string'] = array(
|
28 |
+
'type' => 'string',
|
29 |
+
'name' => __('Strings', 'wp-lingotek'),
|
30 |
+
);
|
31 |
+
|
32 |
+
if (empty($_POST)) {
|
33 |
+
$content_types = get_option('lingotek_content_type');
|
34 |
+
}
|
35 |
+
|
36 |
+
else {
|
37 |
+
check_admin_referer('lingotek-content-types', '_wpnonce_lingotek-content-types');
|
38 |
+
|
39 |
+
$profiles = array_keys(get_option('lingotek_profiles'));
|
40 |
+
|
41 |
+
foreach ($data as $key => $item) {
|
42 |
+
if (isset($data[$key]['name'])) {
|
43 |
+
if (in_array($_POST[$key]['profile'], $profiles))
|
44 |
+
$content_types[$key]['profile'] = $_POST[$key]['profile'];
|
45 |
+
|
46 |
+
foreach ($polylang->model->get_languages_list() as $language) {
|
47 |
+
if (isset($_POST[$key]['sources'][$language->slug]) && in_array($_POST[$key]['sources'][$language->slug], $profiles))
|
48 |
+
$content_types[$key]['sources'][$language->slug] = $_POST[$key]['sources'][$language->slug];
|
49 |
+
}
|
50 |
+
|
51 |
+
}
|
52 |
+
if (isset($data[$key]['fields'])) {
|
53 |
+
foreach ($data[$key]['fields']['label'] as $key1 => $arr) {
|
54 |
+
if (is_array($arr)) {
|
55 |
+
foreach (array_keys($arr) as $key2) {
|
56 |
+
if(empty($_POST[$key]['fields'][$key1][$key2]))
|
57 |
+
$content_types[$key]['fields'][$key1][$key2] = 1;
|
58 |
+
}
|
59 |
+
}
|
60 |
+
elseif (empty($_POST[$key]['fields'][$key1])) {
|
61 |
+
$content_types[$key]['fields'][$key1] = 1;
|
62 |
+
}
|
63 |
+
}
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
+
update_option('lingotek_content_type', $content_types);
|
68 |
+
add_settings_error('lingotek_content_types', 'default', __('Your content types were sucessfully saved.', 'wp-lingotek'), 'updated');
|
69 |
+
settings_errors();
|
70 |
+
}
|
71 |
+
|
72 |
+
foreach ($data as $key => $item) {
|
73 |
+
// default profile is manual except for post
|
74 |
+
$data[$key]['profile'] = empty($content_types[$key]['profile']) ? ('post' == $key ? 'automatic' : 'manual') : $content_types[$key]['profile'];
|
75 |
+
$data[$key]['sources'] = empty($content_types[$key]['sources']) ? array() : $content_types[$key]['sources'];
|
76 |
+
if (!empty($content_types[$key]['fields']))
|
77 |
+
$data[$key]['fields']['value'] = $content_types[$key]['fields'];
|
78 |
+
}
|
79 |
+
|
80 |
+
?>
|
81 |
+
<h3><?php _e('Content Type Configuration', 'wp-lingotek'); ?></h3>
|
82 |
+
<p class="description"><?php _e('Content types can be configured to use any translation profile. Additionally, translation profiles can be set based on the language the content was authored in.', 'wp-lingotek'); ?></p>
|
83 |
+
|
84 |
+
<form id="lingotek-content-types" method="post" action="admin.php?page=wp-lingotek_settings&sm=content" class="validate"><?php
|
85 |
+
wp_nonce_field('lingotek-content-types', '_wpnonce_lingotek-content-types');
|
86 |
+
|
87 |
+
$table = new Lingotek_Content_Table($content_types);
|
88 |
+
$table->prepare_items($data);
|
89 |
+
$table->display();
|
90 |
+
|
91 |
+
submit_button(__('Save Changes', 'wp-lingotek'), 'primary', 'submit', false);
|
92 |
+
?>
|
93 |
+
</form>
|
admin/settings/view-defaults.php
ADDED
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$page_key = $this->plugin_slug . '_settings&sm=defaults';
|
4 |
+
|
5 |
+
wp_enqueue_script('defaults', LINGOTEK_URL . '/js/defaults.js');
|
6 |
+
|
7 |
+
if (!empty($_POST)) {
|
8 |
+
check_admin_referer($page_key, '_wpnonce_' . $page_key);
|
9 |
+
|
10 |
+
if (array_key_exists('refresh', $_POST)) {
|
11 |
+
$refresh_success = $this->set_community_resources($community_id);
|
12 |
+
if ($refresh_success['projects'] == TRUE && $refresh_success['workflows'] == TRUE) {
|
13 |
+
add_settings_error('lingotek_community_resources', 'options', __('Resources from Lingotek were successfully updated for projects and workflows.', 'wp-lingotek'), 'updated');
|
14 |
+
}
|
15 |
+
else if ($refresh_success['projects'] == TRUE) {
|
16 |
+
add_settings_error('lingotek_community_resources', 'error', __('Resources from Lingotek were successfully updated for projects.', 'wp-lingotek'), 'updated');
|
17 |
+
}
|
18 |
+
else if ($refresh_success['workflows'] == TRUE) {
|
19 |
+
add_settings_error('lingotek_community_resources', 'error', __('Resources from Lingotek were successfully updated for workflows.', 'wp-lingotek'), 'updated');
|
20 |
+
}
|
21 |
+
}
|
22 |
+
else {
|
23 |
+
$options = array();
|
24 |
+
$settings = $this->get_profiles_settings(true);
|
25 |
+
foreach ($settings as $key => $setting) {
|
26 |
+
if (isset($_POST[$key])) {
|
27 |
+
$options[$key] = $_POST[$key];
|
28 |
+
}
|
29 |
+
}
|
30 |
+
update_option('lingotek_defaults', $options);
|
31 |
+
add_settings_error('lingotek_defaults', 'defaultgs', __('Your <i>Defaults</i> were sucessfully saved.', 'wp-lingotek'), 'updated');
|
32 |
+
|
33 |
+
if (isset($_POST['update_callback'])) {
|
34 |
+
$client = new Lingotek_API();
|
35 |
+
if ($client->update_callback_url($options['project_id']))
|
36 |
+
add_settings_error('lingotek_defaults', 'defaultgs', __('Your callback url was successfully updated.', 'wp-lingotek'), 'updated');
|
37 |
+
}
|
38 |
+
|
39 |
+
//adds new project if text box is filled out
|
40 |
+
if (!empty($_POST['new_project'])) {
|
41 |
+
$client = new Lingotek_API();
|
42 |
+
$title = stripslashes($_POST['new_project']);
|
43 |
+
|
44 |
+
if ($new_id = $client->create_project($title, $community_id)) {
|
45 |
+
add_settings_error('lingotek_defaults', 'defaultgs', __('Your new project was successfully created.', 'wp-lingotek'), 'updated');
|
46 |
+
$this->set_community_resources($community_id);// updates the cache to include the newly created project
|
47 |
+
$options['project_id'] = $new_id;
|
48 |
+
update_option('lingotek_defaults', $options);
|
49 |
+
}
|
50 |
+
}
|
51 |
+
}
|
52 |
+
settings_errors();
|
53 |
+
}
|
54 |
+
$settings = $this->get_profiles_settings(true);
|
55 |
+
$options = get_option('lingotek_defaults');
|
56 |
+
|
57 |
+
// Code to determine which filter scenario will be displayed (Not configured, defaults, custom filters)
|
58 |
+
$primary_filter_id = array_search('okf_json@with-html-subfilter.fprm', $settings['primary_filter_id']['options']);
|
59 |
+
$secondary_filter_id = array_search('okf_html@wordpress.fprm', $settings['secondary_filter_id']['options']);
|
60 |
+
$default_filters = array($primary_filter_id => 'okf_json@with-html-subfilter.fprm', $secondary_filter_id => 'okf_html@wordpress.fprm');
|
61 |
+
$default_filters_exist = FALSE;
|
62 |
+
$extra_filters_exist = FALSE;
|
63 |
+
$no_filters_exist = FALSE;
|
64 |
+
|
65 |
+
if ($settings['primary_filter_id']['options'] == $default_filters) {
|
66 |
+
$default_filters_exist = TRUE;
|
67 |
+
$options['primary_filter_id'] = $primary_filter_id;
|
68 |
+
$options['secondary_filter_id'] = $secondary_filter_id;
|
69 |
+
update_option('lingotek_defaults', $options);
|
70 |
+
}
|
71 |
+
else {
|
72 |
+
$num = count(array_diff_assoc($settings['primary_filter_id']['options'], $default_filters));
|
73 |
+
if ($num > 0) {
|
74 |
+
$extra_filters_exist = TRUE;
|
75 |
+
}
|
76 |
+
else {
|
77 |
+
$options['primary_filter_id'] = '';
|
78 |
+
$options['secondary_filter_id'] = '';
|
79 |
+
update_option('lingotek_defaults', $options);
|
80 |
+
$no_filters_exist = TRUE;
|
81 |
+
}
|
82 |
+
}
|
83 |
+
unset($settings['primary_filter_id']['options'][$secondary_filter_id]);
|
84 |
+
unset($settings['secondary_filter_id']['options'][$primary_filter_id]);
|
85 |
+
?>
|
86 |
+
|
87 |
+
<h3><?php _e('Defaults', 'wp-lingotek'); ?></h3>
|
88 |
+
<p class="description"><?php _e('The default automation settings and resources that should be used for this site. These settings can be overriden using translation profiles and content type configuration.', 'wp-lingotek'); ?></p>
|
89 |
+
|
90 |
+
|
91 |
+
<form id="lingotek-settings" method="post" action="admin.php?page=<?php echo $page_key; ?>" class="validate">
|
92 |
+
<?php wp_nonce_field($page_key, '_wpnonce_' . $page_key); ?>
|
93 |
+
|
94 |
+
<table class="form-table"><?php foreach ($settings as $key => $setting) { ?>
|
95 |
+
<tr id="<?php echo $key.'_row'?>">
|
96 |
+
<th scope="row"><label for="<?php echo $key; ?>"><?php echo $setting['label'] ?></label></th>
|
97 |
+
<td>
|
98 |
+
<select name="<?php echo $key ?>" id="<?php echo $key ?>"><?php
|
99 |
+
foreach ($setting['options'] as $id => $title) {
|
100 |
+
$selected = array_key_exists($key, $options) && ($options[$key] == $id) ? 'selected="selected"' : '';
|
101 |
+
echo "\n\t<option value='" . esc_attr($id) . "' $selected>" . $title . '</option>';
|
102 |
+
} ?>
|
103 |
+
</select><?php
|
104 |
+
if ('project_id' == $key) { ?>
|
105 |
+
<?php
|
106 |
+
$client = new Lingotek_API();
|
107 |
+
|
108 |
+
if ($client->get_projects($community_id) == 'empty') { ?>
|
109 |
+
<script> document.getElementById('project_id').style.display = 'none';</script>
|
110 |
+
<input type="text" name="new_project" id="new_project" placeholder="<?php _e('Enter new project name', 'wp-lingotek') ?>" />
|
111 |
+
<?php }
|
112 |
+
else { ?>
|
113 |
+
|
114 |
+
<input type="text" style="display:none" name="new_project" id="new_project" placeholder="<?php _e('Enter new project name', 'wp-lingotek') ?>" />
|
115 |
+
<input type="checkbox" name="update_callback" id="update_callback"/>
|
116 |
+
<label for="update_callback" id="callback_label"><?php _e('Update the callback url for this project.', 'wp-lingotek') ?></label>
|
117 |
+
|
118 |
+
<br/><a href="#" id="create" onclick="toggleTextbox()" style="padding-left:3px; color:#999; font-size:80%; text-decoration:none"><b>+</b> <?php echo _e('Create New Project', 'wp-lingotek') ?></a>
|
119 |
+
<?php } ?>
|
120 |
+
<?php } ?>
|
121 |
+
<!-- Code to handle displaying of Primary and Secondary Filters -->
|
122 |
+
<?php if($no_filters_exist) { ?>
|
123 |
+
<script> document.getElementById("primary_filter_id_row").style.display = "none";</script>
|
124 |
+
<script> document.getElementById("secondary_filter_id_row").style.display = "none";</script> <?php
|
125 |
+
if ('primary_filter_id' == $key) { ?>
|
126 |
+
<tr id="filters_row"><th><?php _e('Filters', 'wp-lingotek') ?></th><td><i><?php _e('Not configured', 'wp-lingotek') ?></i></td></tr>
|
127 |
+
<?php }
|
128 |
+
}
|
129 |
+
if ($default_filters_exist) { ?>
|
130 |
+
<script> document.getElementById("primary_filter_id_row").style.display = "none";</script>
|
131 |
+
<script> document.getElementById("secondary_filter_id_row").style.display = "none";</script>
|
132 |
+
<?php } ?>
|
133 |
+
<!-- End of filter code -->
|
134 |
+
</tr><?php } ?>
|
135 |
+
</table>
|
136 |
+
|
137 |
+
<p>
|
138 |
+
<?php submit_button(__('Save Changes', 'wp-lingotek'), 'primary', 'submit', false); ?>
|
139 |
+
<?php submit_button(__( 'Refresh Resources', 'wp-lingotek'), 'secondary', 'refresh', false ); ?>
|
140 |
+
</p>
|
141 |
+
</form>
|
admin/settings/view-edit-profile.php
ADDED
@@ -0,0 +1,200 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$settings = $this->get_profiles_settings();
|
4 |
+
|
5 |
+
$defaults = get_option('lingotek_defaults');
|
6 |
+
$default = __('Use global default (%s)', 'wp-lingotek');
|
7 |
+
foreach ($settings as $key => $setting) {
|
8 |
+
if (isset($defaults[$key]) && array_key_exists($defaults[$key], $settings[$key]['options'])) {
|
9 |
+
$default_arr = array('default' => sprintf($default, $settings[$key]['options'][$defaults[$key]]));
|
10 |
+
$settings[$key]['options'] = array_merge($default_arr, $settings[$key]['options']);
|
11 |
+
}
|
12 |
+
}
|
13 |
+
|
14 |
+
$target_settings = array(
|
15 |
+
'default' => __('Use default settings', 'wp-lingotek'),
|
16 |
+
'custom' => __('Use custom settings', 'wp-lingotek'),
|
17 |
+
'disabled' => __('Disabled', 'wp-lingotek')
|
18 |
+
);
|
19 |
+
|
20 |
+
$profiles = $this->get_profiles_usage(get_option('lingotek_profiles'));
|
21 |
+
|
22 |
+
$profile = isset($_GET['profile']) && array_key_exists($_GET['profile'], $profiles) ? $profiles[$_GET['profile']] : array();
|
23 |
+
$disabled = isset($profile['profile']) && in_array($profile['profile'], array('automatic', 'manual')) ? 'disabled="disabled"' : '';
|
24 |
+
|
25 |
+
// Code to determine which filter scenario will be displayed. (Not configured, defaults, custom filters)
|
26 |
+
$primary_filter_id = array_search('okf_json@with-html-subfilter.fprm', $settings['primary_filter_id']['options']);
|
27 |
+
$secondary_filter_id = array_search('okf_html@wordpress.fprm', $settings['secondary_filter_id']['options']);
|
28 |
+
$default_filters = array($primary_filter_id => 'okf_json@with-html-subfilter.fprm', $secondary_filter_id => 'okf_html@wordpress.fprm');
|
29 |
+
$default_filters_exist = FALSE;
|
30 |
+
$extra_filters_exist = FALSE;
|
31 |
+
$no_filters_exist = FALSE;
|
32 |
+
|
33 |
+
if (array_key_exists('default', array_diff_assoc($settings['primary_filter_id']['options'], $default_filters)) && count(array_diff_assoc($settings['primary_filter_id']['options'], $default_filters)) == 1) {
|
34 |
+
unset($settings['primary_filter_id']['options']['default']);
|
35 |
+
}
|
36 |
+
if ($settings['primary_filter_id']['options'] == $default_filters) {
|
37 |
+
$default_filters_exist = TRUE;
|
38 |
+
$defaults['primary_filter_id'] = $primary_filter_id;
|
39 |
+
$defaults['secondary_filter_id'] = $secondary_filter_id;
|
40 |
+
update_option('lingotek_defaults', $defaults);
|
41 |
+
}
|
42 |
+
else {
|
43 |
+
$num = count(array_diff_assoc($settings['primary_filter_id']['options'], $default_filters));
|
44 |
+
if ($num > 0) {
|
45 |
+
$extra_filters_exist = TRUE;
|
46 |
+
}
|
47 |
+
else {
|
48 |
+
$defaults['primary_filter_id'] = '';
|
49 |
+
$defaults['secondary_filter_id'] = '';
|
50 |
+
update_option('lingotek_defaults', $defaults);
|
51 |
+
$no_filters_exist = TRUE;
|
52 |
+
}
|
53 |
+
}
|
54 |
+
unset($settings['primary_filter_id']['options'][$secondary_filter_id]);
|
55 |
+
unset($settings['secondary_filter_id']['options'][$primary_filter_id]);
|
56 |
+
?>
|
57 |
+
|
58 |
+
<form id="lingotek-edit-profile" method="post" action="admin.php?page=wp-lingotek_settings&sm=profiles" class="validate">
|
59 |
+
<?php wp_nonce_field('lingotek-edit-profile', '_wpnonce_lingotek-edit-profile');?>
|
60 |
+
<input name="profile" type="hidden" value="<?php echo empty($profile['profile']) ? '' : esc_attr($profile['profile']); ?>">
|
61 |
+
|
62 |
+
<table class="form-table">
|
63 |
+
<tr>
|
64 |
+
<th scope="row"><?php printf('<label for="%s">%s</label>', 'name' , __('Profile name', 'wp-lingotek')); ?></th>
|
65 |
+
<td><?php
|
66 |
+
$profile_name = $disabled ? __($profile['name'],'wp-lingotek') : $profile['name'];// localize canned profile names
|
67 |
+
printf('<input name="name" id="name" type="text" value="%s" %s>',
|
68 |
+
empty($profile['name']) ? '' : esc_attr($profile_name),
|
69 |
+
$disabled
|
70 |
+
); ?>
|
71 |
+
</td>
|
72 |
+
</tr>
|
73 |
+
</table>
|
74 |
+
|
75 |
+
<h3><?php _e('Default settings', 'wp-lingotek'); ?></h3>
|
76 |
+
|
77 |
+
<table class="form-table"><?php
|
78 |
+
foreach ($settings as $key => $setting) { ?>
|
79 |
+
<tr id="<?php echo $key.'_row'?>">
|
80 |
+
<th scope="row"><?php printf('<label for="%s">%s</label>', $key , $setting['label']); ?></th>
|
81 |
+
<td><?php
|
82 |
+
printf('<select name="%1$s" id="%1$s" %2$s>', $key, in_array($key, array('upload', 'download')) ? $disabled : '');
|
83 |
+
foreach ($setting['options'] as $id => $title) {
|
84 |
+
$selected = isset($profile[$key]) && $profile[$key] == $id ? 'selected="selected"' : '';
|
85 |
+
echo "\n\t<option value='" . esc_attr($id) . "' $selected>" . esc_html($title) . '</option>';
|
86 |
+
} ?>
|
87 |
+
</select><?php
|
88 |
+
|
89 |
+
if ('project_id' == $key) { ?>
|
90 |
+
<input type="checkbox" name="update_callback" id="update_callback"/>
|
91 |
+
<label for="update_callback"><?php _e('Update the callback url for this project.', 'wp-lingotek') ?></label><?php
|
92 |
+
}
|
93 |
+
|
94 |
+
if (isset($setting['description']))
|
95 |
+
printf('<p class="description">%s</p>', $setting['description']);?>
|
96 |
+
|
97 |
+
<!-- Code to handle displaying of Primary and Secondary Filters -->
|
98 |
+
<?php if($no_filters_exist) { ?>
|
99 |
+
<script> document.getElementById("primary_filter_id_row").style.display = "none";</script>
|
100 |
+
<script> document.getElementById("secondary_filter_id_row").style.display = "none";</script> <?php
|
101 |
+
if ('primary_filter_id' == $key) { ?>
|
102 |
+
<tr id="filters_row"><th><?php _e('Filters', 'wp-lingotek') ?></th><td><i><?php _e('Not configured', 'wp-lingotek') ?></i></td></tr>
|
103 |
+
<?php }
|
104 |
+
}
|
105 |
+
if ($default_filters_exist) { ?>
|
106 |
+
<script> document.getElementById("primary_filter_id_row").style.display = "none";</script>
|
107 |
+
<script> document.getElementById("secondary_filter_id_row").style.display = "none";</script>
|
108 |
+
<?php } ?>
|
109 |
+
<!-- End of filter code -->
|
110 |
+
</td>
|
111 |
+
</tr><?php
|
112 |
+
} ?>
|
113 |
+
</table>
|
114 |
+
|
115 |
+
<h3><?php _e('Target languages', 'wp-lingotek'); ?></h3>
|
116 |
+
|
117 |
+
<table class="form-table"><?php
|
118 |
+
unset($settings['upload']); // we don't want this for target languages
|
119 |
+
unset($settings['project_id']); // FIXME disable the possibility to have a different project per target language for now
|
120 |
+
|
121 |
+
foreach ($this->pllm->get_languages_list() as $language) { ?>
|
122 |
+
<tr>
|
123 |
+
<th scope="row"><?php printf('<label for="%s">%s</label>', esc_attr($language->slug) , esc_html($language->name)); ?><?php
|
124 |
+
|
125 |
+
printf('<a id="%1$s_details_link" %2$s class="dashicons dashicons-arrow-right" onclick="%3$s">%4$s</a>',
|
126 |
+
esc_attr($language->slug),
|
127 |
+
isset($profile['targets'][$language->slug]) && 'custom' == $profile['targets'][$language->slug] ? '' : 'style="display:none;"',
|
128 |
+
"
|
129 |
+
d = document.getElementById('{$language->slug}_details');
|
130 |
+
if ('none' == d.style.display) {
|
131 |
+
d.style.display = '';
|
132 |
+
this.className = 'dashicons dashicons-arrow-down';
|
133 |
+
}
|
134 |
+
else {
|
135 |
+
d.style.display = 'none';
|
136 |
+
this.className = 'dashicons dashicons-arrow-right';
|
137 |
+
}",
|
138 |
+
'' //__('Show', 'wp-lingotek')
|
139 |
+
|
140 |
+
); ?></th>
|
141 |
+
<td><?php
|
142 |
+
printf('<select name="targets[%1$s]" id="targets[%1$s]" onchange="%2$s">',
|
143 |
+
esc_attr($language->slug),
|
144 |
+
"
|
145 |
+
dl = document.getElementById('{$language->slug}_details_link');
|
146 |
+
d = document.getElementById('{$language->slug}_details');
|
147 |
+
if ('custom' == this.value) {
|
148 |
+
d.style.display = dl.style.display = '';
|
149 |
+
dl.className = 'dashicons dashicons-arrow-down';
|
150 |
+
}
|
151 |
+
else {
|
152 |
+
d.style.display = dl.style.display = 'none';
|
153 |
+
dl.className = 'dashicons dashicons-arrow-right';
|
154 |
+
}"
|
155 |
+
);
|
156 |
+
foreach ($target_settings as $id => $title) {
|
157 |
+
$selected = (empty($profile['targets'][$language->slug]) && 'default' == $id) || (isset($profile['targets'][$language->slug]) && $profile['targets'][$language->slug] == $id) ? 'selected="selected"' : '';
|
158 |
+
echo "\n\t<option value='" . $id . "' $selected>" . $title . '</option>';
|
159 |
+
} ?>
|
160 |
+
</select>
|
161 |
+
|
162 |
+
</td>
|
163 |
+
</tr>
|
164 |
+
<tr id="<?php echo esc_attr($language->slug); ?>_details" style="display:none;">
|
165 |
+
<td colspan="2" style="padding:0;">
|
166 |
+
<table class="form-table" style="background: #ffffff; margin:0; padding: 10px;"><?php
|
167 |
+
foreach ($settings as $key => $setting) {
|
168 |
+
$custom_key = 'custom['.$key.']['.esc_attr($language->slug).']'; ?>
|
169 |
+
<tr>
|
170 |
+
<th scope="row"> <?php printf('<label for="%s">%s</label>', $custom_key , $setting['label']); ?></th>
|
171 |
+
<td><?php
|
172 |
+
printf('<select name="%1$s" id="%1$s" %2$s>', $custom_key, in_array($key, array('upload', 'download')) ? $disabled : '');
|
173 |
+
foreach ($setting['options'] as $id => $title) {
|
174 |
+
$selected = isset($profile['custom'][$key][$language->slug]) && $profile['custom'][$key][$language->slug] == $id ? 'selected="selected"' : '';
|
175 |
+
echo "\n\t<option value='" . esc_attr($id) . "' $selected>" . esc_html($title) . '</option>';
|
176 |
+
} ?>
|
177 |
+
</select><?php
|
178 |
+
//if (isset($setting['description']))
|
179 |
+
//printf('<p class="description">%s</p>', $setting['description']);?>
|
180 |
+
</td>
|
181 |
+
</tr><?php
|
182 |
+
} ?>
|
183 |
+
</table>
|
184 |
+
</td>
|
185 |
+
</tr>
|
186 |
+
|
187 |
+
<?php
|
188 |
+
} ?>
|
189 |
+
</table><?php submit_button(__('Save Changes', 'wp-lingotek'), 'primary', 'submit', false); ?>
|
190 |
+
|
191 |
+
<?php
|
192 |
+
if (!empty($profile['profile']) && !in_array($profile['profile'], array('automatic', 'manual', 'disabled')) && empty($profile['usage']))
|
193 |
+
printf(
|
194 |
+
'<a href="%s" class="button" onclick = "return confirm(\'%s\');">%s</a>',
|
195 |
+
esc_url(wp_nonce_url('admin.php?page=wp-lingotek_settings&sm=profiles&lingotek_action=delete-profile&noheader=true&profile='.$profile['profile'], 'delete-profile')),
|
196 |
+
__('You are about to permanently delete this profile. Are you sure?', 'wp-lingotek'),
|
197 |
+
__('Delete', 'wp-lingotek')
|
198 |
+
);
|
199 |
+
?> <a href="admin.php?page=wp-lingotek_settings&sm=profiles" class="button"> <?php _e('Cancel', 'wp-lingotek'); ?></a>
|
200 |
+
</form>
|
admin/settings/view-preferences.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$setting_details = array(
|
4 |
+
'download_post_status' => array(
|
5 |
+
'type' => 'dropdown',
|
6 |
+
'label' => __('Download translation status', 'wp-lingotek'),
|
7 |
+
'description' => __('The post status for newly downloaded translations', 'wp-lingotek'),
|
8 |
+
'values' => array(
|
9 |
+
Lingotek_Group_Post::SAME_AS_SOURCE => __('Same as source post', 'wp-lingotek'),
|
10 |
+
'draft' => __('Draft', 'wp-lingotek'),
|
11 |
+
'pending' => __('Pending Review', 'wp-lingotek'),
|
12 |
+
'publish' => __('Published', 'wp-lingotek'),
|
13 |
+
//'future' => __('Scheduled', 'wp-lingotek'),
|
14 |
+
'private' => __('Privately Published', 'wp-lingotek'),
|
15 |
+
)),
|
16 |
+
'auto_upload_post_statuses' => array( // blacklist
|
17 |
+
'type' => 'checkboxes',
|
18 |
+
'label' => __('Auto upload statuses', 'wp-lingotek'),
|
19 |
+
'description' => __('The post statuses checked above are enabled for automatic upload (when using automatic uploading translation profiles).', 'wp-lingotek'),
|
20 |
+
'values' => array(
|
21 |
+
'draft' => __('Draft', 'wp-lingotek'),
|
22 |
+
'pending' => __('Pending Review', 'wp-lingotek'),
|
23 |
+
'publish' => __('Published', 'wp-lingotek'),
|
24 |
+
'future' => __('Scheduled', 'wp-lingotek'),
|
25 |
+
'private' => __('Privately Published', 'wp-lingotek'),
|
26 |
+
)
|
27 |
+
)
|
28 |
+
);
|
29 |
+
|
30 |
+
$page_key = $this->plugin_slug . '_settings&sm=preferences';
|
31 |
+
|
32 |
+
if (!empty($_POST)) {
|
33 |
+
check_admin_referer($page_key, '_wpnonce_' . $page_key);
|
34 |
+
$options = array();
|
35 |
+
foreach ($setting_details as $key => $setting) {
|
36 |
+
$options[$key] = $_POST[$key];
|
37 |
+
}
|
38 |
+
update_option('lingotek_prefs', $options);
|
39 |
+
|
40 |
+
add_settings_error('lingotek_prefs', 'prefs', __('Your preferences were successfully updated.', 'wp-lingotek'), 'updated');
|
41 |
+
settings_errors();
|
42 |
+
}
|
43 |
+
|
44 |
+
$selected_options = Lingotek_Model::get_prefs();
|
45 |
+
|
46 |
+
?>
|
47 |
+
|
48 |
+
<h3><?php _e('Preferences', 'wp-lingotek'); ?></h3>
|
49 |
+
<p class="description"><?php _e('These are your preferred settings.', 'wp-lingotek'); ?></p>
|
50 |
+
|
51 |
+
|
52 |
+
<form id="lingotek-settings" method="post" action="admin.php?page=<?php echo $page_key; ?>" class="validate">
|
53 |
+
<?php wp_nonce_field($page_key, '_wpnonce_' . $page_key); ?>
|
54 |
+
|
55 |
+
<table class="form-table"><?php foreach ($setting_details as $key => $setting) { ?>
|
56 |
+
|
57 |
+
<tr>
|
58 |
+
<th scope="row"><label for="<?php echo $key; ?>"><?php echo $setting['label'] ?></label></th>
|
59 |
+
<td>
|
60 |
+
<?php if ($setting['type'] == 'dropdown') { ?>
|
61 |
+
<select name="<?php echo $key ?>" id="<?php echo $key ?>">
|
62 |
+
<?php
|
63 |
+
foreach ($setting['values'] as $id => $title) {
|
64 |
+
echo "\n\t" . '<option value="' . esc_attr($id) . '" ' . selected($selected_options[$key], $id) . '>' . $title . '</option>';
|
65 |
+
}
|
66 |
+
?>
|
67 |
+
</select>
|
68 |
+
<?php } else if ($setting['type'] == 'checkboxes') {
|
69 |
+
echo '<ul class="pref-statuses">';
|
70 |
+
foreach ($setting['values'] as $id => $title) {
|
71 |
+
$cb_name = $key.'['.esc_attr($id) . ']';
|
72 |
+
$checked = checked('1', (isset($selected_options[$key][$id]) && $selected_options[$key][$id]), false);
|
73 |
+
echo '<li><input type="checkbox" id="'.$cb_name.'" name="'.$cb_name.'" value="1" ' . $checked. '><label for="'.$cb_name.'">' . $title . '</label></li>';
|
74 |
+
}
|
75 |
+
echo '</ul>';
|
76 |
+
} ?>
|
77 |
+
<p class="description">
|
78 |
+
<?php echo $setting['description']; ?>
|
79 |
+
</p>
|
80 |
+
</tr><?php } ?>
|
81 |
+
</table>
|
82 |
+
|
83 |
+
<?php submit_button(__('Save Changes', 'wp-lingotek'), 'primary', 'submit', false); ?>
|
84 |
+
</form>
|
admin/settings/view-profiles.php
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
global $polylang;
|
3 |
+
|
4 |
+
$profiles = Lingotek::get_profiles();
|
5 |
+
$profiles = $this->get_profiles_usage($profiles);
|
6 |
+
$settings = $this->get_profiles_settings();
|
7 |
+
|
8 |
+
if (isset($_GET['lingotek_action']) && 'delete-profile' == $_GET['lingotek_action']) {
|
9 |
+
check_admin_referer('delete-profile');
|
10 |
+
|
11 |
+
// check again that usage empty
|
12 |
+
if (!empty($profiles[$_GET['profile']]) && empty($profiles[$_GET['profile']]['usage'])) {
|
13 |
+
unset($profiles[$_GET['profile']]);
|
14 |
+
update_option('lingotek_profiles', $profiles);
|
15 |
+
add_settings_error('lingotek_profile', 'default', __('Your translation profile was sucessfully deleted.', 'wp-lingotek'), 'updated');
|
16 |
+
set_transient('settings_errors', get_settings_errors(), 30);
|
17 |
+
wp_redirect(admin_url('admin.php?page=wp-lingotek_settings&sm=profiles&settings-updated=1'));
|
18 |
+
exit;
|
19 |
+
}
|
20 |
+
}
|
21 |
+
|
22 |
+
if (!empty($_POST)) {
|
23 |
+
check_admin_referer('lingotek-edit-profile', '_wpnonce_lingotek-edit-profile');
|
24 |
+
|
25 |
+
$defaults = get_option('lingotek_defaults');
|
26 |
+
|
27 |
+
if (empty($_POST['name']) && empty($_POST['profile'])) {
|
28 |
+
add_settings_error('lingotek_profile', 'default', __('You must provide a name for your translation profile.', 'wp-lingotek'), 'error');
|
29 |
+
}
|
30 |
+
else {
|
31 |
+
$profile = sanitize_title(empty($_POST['profile']) ? $_POST['name'] : $_POST['profile']);
|
32 |
+
$profiles[$profile]['profile'] = $profile;
|
33 |
+
if (!empty($_POST['name']))
|
34 |
+
$profiles[$profile]['name'] = strip_tags($_POST['name']);
|
35 |
+
|
36 |
+
foreach (array('upload', 'download', 'project_id', 'workflow_id') as $key) {
|
37 |
+
if (isset($_POST[$key]) && in_array($_POST[$key], array_keys($settings[$key]['options'])))
|
38 |
+
$profiles[$profile][$key] = $_POST[$key];
|
39 |
+
|
40 |
+
if (empty($_POST[$key]) || 'default' == $_POST[$key])
|
41 |
+
unset($profiles[$profile][$key]);
|
42 |
+
}
|
43 |
+
|
44 |
+
foreach ($this->pllm->get_languages_list() as $language) {
|
45 |
+
switch($_POST['targets'][$language->slug]) {
|
46 |
+
case 'custom':
|
47 |
+
foreach (array('download', 'project_id', 'workflow_id') as $key) {
|
48 |
+
if (isset($_POST['custom'][$key][$language->slug]) && in_array($_POST['custom'][$key][$language->slug], array_keys($settings[$key]['options']))) {
|
49 |
+
$profiles[$profile]['custom'][$key][$language->slug] = $_POST['custom'][$key][$language->slug];
|
50 |
+
}
|
51 |
+
|
52 |
+
if (empty($_POST['custom'][$key][$language->slug]) || 'default' == $_POST['custom'][$key][$language->slug]) {
|
53 |
+
unset($profiles[$profile]['custom'][$key][$language->slug]);
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
case 'disabled':
|
58 |
+
$profiles[$profile]['targets'][$language->slug] = $_POST['targets'][$language->slug];
|
59 |
+
break;
|
60 |
+
|
61 |
+
case 'default':
|
62 |
+
unset($profiles[$profile]['targets'][$language->slug]);
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
// hardcode default values for automatic and manual profiles as the process above emptied them
|
67 |
+
$profiles['automatic']['upload'] = $profiles['automatic']['download'] = 'automatic';
|
68 |
+
$profiles['manual']['upload'] = $profiles['manual']['download'] = 'manual';
|
69 |
+
$profiles['automatic']['name'] = 'Automatic'; $profiles['manual']['name'] = 'Manual'; $profiles['disabled']['name'] = 'Disabled';// do not localize names here
|
70 |
+
|
71 |
+
update_option('lingotek_profiles', $profiles);
|
72 |
+
add_settings_error('lingotek_profile', 'default', __('Your translation profile was sucessfully saved.', 'wp-lingotek'), 'updated');
|
73 |
+
|
74 |
+
if (isset($_POST['update_callback'])) {
|
75 |
+
$project_id = isset($profiles[$profile]['project_id']) ? $profiles[$profile]['project_id'] : $defaults['project_id'];
|
76 |
+
$client = new Lingotek_API();
|
77 |
+
if ($client->update_callback_url($project_id))
|
78 |
+
add_settings_error('lingotek_profile', 'default', __('Your callback url was successfully updated.', 'wp-lingotek'), 'updated');
|
79 |
+
}
|
80 |
+
}
|
81 |
+
settings_errors();
|
82 |
+
}
|
83 |
+
|
84 |
+
?>
|
85 |
+
<h3><?php _e('Translation Profiles', 'wp-lingotek'); ?></h3>
|
86 |
+
<p class="description"><?php _e('Translation profiles allow you to quickly configure and re-use translation settings.', 'wp-lingotek'); ?></p><?php
|
87 |
+
$table = new Lingotek_Profiles_Table();
|
88 |
+
$table->prepare_items($profiles);
|
89 |
+
$table->display();
|
90 |
+
printf(
|
91 |
+
'<a href="%s" class="button button-primary">%s</a>',
|
92 |
+
admin_url('admin.php?page=wp-lingotek_settings&sm=edit-profile'),
|
93 |
+
__('Add New Profile', 'wp-lingotek')
|
94 |
+
);
|
95 |
+
|
admin/settings/view-utilities.php
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
$page_key = $this->plugin_slug . '_settings&sm=utilities';
|
3 |
+
|
4 |
+
if (!empty($_POST)) {
|
5 |
+
check_admin_referer($page_key, '_wpnonce_' . $page_key);
|
6 |
+
|
7 |
+
// progress dialog placeholder
|
8 |
+
if (!empty($_POST['utility_disassociate'])) {
|
9 |
+
$ids = Lingotek_Utilities::get_all_document_ids();
|
10 |
+
if (!empty($ids))
|
11 |
+
printf('<div id="lingotek-progressdialog" title="%s"><div id="lingotek-progressbar"></div></div>', __('Disassociating content...', 'wp-lingotek'));
|
12 |
+
}
|
13 |
+
|
14 |
+
$utilities = array();
|
15 |
+
if(array_key_exists('utility_set_default_language', $_POST) && $_POST['utility_set_default_language'] == 'on'){
|
16 |
+
$utilities[] = 'utility_set_default_language';
|
17 |
+
}
|
18 |
+
|
19 |
+
$GLOBALS['wp_lingotek']->utilities->run_utilities($utilities);
|
20 |
+
|
21 |
+
settings_errors();
|
22 |
+
}
|
23 |
+
|
24 |
+
?>
|
25 |
+
<h3><?php _e('Utilities', 'wp-lingotek'); ?></h3>
|
26 |
+
<p class="description"><?php _e('These utilities are designed to help you prepare and maintain your multilingual content.', 'wp-lingotek'); ?></p>
|
27 |
+
|
28 |
+
<h4><?php _e('Language', 'wp-lingotek'); ?></h4>
|
29 |
+
<form id="lingotek-utilities" method="post" action="admin.php?page=<?php echo $page_key; ?>" class="validate"><?php
|
30 |
+
wp_nonce_field($page_key, '_wpnonce_' . $page_key);
|
31 |
+
|
32 |
+
printf(
|
33 |
+
'<p><input type="checkbox" name="%1$s" id="%1$s"/><label for="%1$s">%2$s</label></p>',
|
34 |
+
'utility_set_default_language',
|
35 |
+
__('Set <i>default language</i> as the language for all content that has not been assigned a language.', 'wp-lingotek')
|
36 |
+
);
|
37 |
+
|
38 |
+
?>
|
39 |
+
<h4><?php _e('Disassociation', 'wp-lingotek'); ?></h4>
|
40 |
+
<?php
|
41 |
+
|
42 |
+
printf(
|
43 |
+
'<p><input type="checkbox" name="%1$s" id="%1$s" onclick="%3$s"/><label for="%1$s">%2$s</label></p>',
|
44 |
+
'utility_disassociate',
|
45 |
+
__('Disassociate all the content from Lingotek TMS.', 'wp-lingotek'),
|
46 |
+
"
|
47 |
+
if (this.checked == false) {
|
48 |
+
document.getElementById('utility_delete_documents').checked = false;
|
49 |
+
}"
|
50 |
+
);
|
51 |
+
|
52 |
+
printf(
|
53 |
+
'<p><input type="checkbox" name="%1$s" id="%1$s" onclick="%3$s"/><label for="%1$s">%2$s</label></p>',
|
54 |
+
'utility_delete_documents',
|
55 |
+
__('Delete all documents in Lingotek TMS.', 'wp-lingotek'),
|
56 |
+
"
|
57 |
+
if (this.checked == true) {
|
58 |
+
document.getElementById('utility_disassociate').checked = true;
|
59 |
+
}"
|
60 |
+
);
|
61 |
+
|
62 |
+
$confirm_disassociate = __('You are about to disassociate all your content from Lingotek TMS. Are you sure ?', 'wp-lingotek');
|
63 |
+
$confirm_delete = __('You are about to disassociate all your content and delete all documents in Lingotek TMS. Are you sure ?', 'wp-lingotek');
|
64 |
+
|
65 |
+
$confirm_js = "
|
66 |
+
d = document.getElementById('utility_disassociate');
|
67 |
+
dd = document.getElementById('utility_delete_documents');
|
68 |
+
if (dd.checked == true) {
|
69 |
+
return confirm('$confirm_delete');
|
70 |
+
}
|
71 |
+
if (d.checked == true) {
|
72 |
+
return confirm('$confirm_disassociate');
|
73 |
+
}";
|
74 |
+
|
75 |
+
submit_button(__('Run Utilities', 'wp-lingotek'), 'primary', 'submit', true, sprintf('onclick="%s"', $confirm_js)); ?>
|
76 |
+
</form><?php
|
77 |
+
|
78 |
+
|
admin/string-actions.php
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Lingotek_String_actions extends Lingotek_Actions {
|
4 |
+
|
5 |
+
/*
|
6 |
+
* Constructor
|
7 |
+
*
|
8 |
+
* @since 0.2
|
9 |
+
*/
|
10 |
+
public function __construct() {
|
11 |
+
parent::__construct('string');
|
12 |
+
|
13 |
+
if (isset($this->pllm->options['default_lang']) && 'automatic' == Lingotek_Model::get_profile_option('upload', 'string', $this->pllm->get_language($this->pllm->options['default_lang'])))
|
14 |
+
add_action('updated_option', array(&$this, 'updated_option'));
|
15 |
+
}
|
16 |
+
|
17 |
+
/*
|
18 |
+
* get the language of strings sources
|
19 |
+
*
|
20 |
+
* @since 0.2
|
21 |
+
*
|
22 |
+
* @param string $name
|
23 |
+
* @return object
|
24 |
+
*/
|
25 |
+
protected function get_language($name) {
|
26 |
+
return $this->pllm->get_language($this->pllm->options['default_lang']);;
|
27 |
+
}
|
28 |
+
|
29 |
+
|
30 |
+
/*
|
31 |
+
* displays the icon of an uploaded strings group (no link)
|
32 |
+
*
|
33 |
+
* @since 0.2
|
34 |
+
*
|
35 |
+
* @param int $id
|
36 |
+
*/
|
37 |
+
public static function uploaded_icon($id) {
|
38 |
+
return self::display_icon('uploaded', '#');
|
39 |
+
}
|
40 |
+
|
41 |
+
/*
|
42 |
+
* creates an html action link
|
43 |
+
*
|
44 |
+
* @since 0.2
|
45 |
+
*
|
46 |
+
* @param array $args parameters to add to the link
|
47 |
+
* @param bool $warning whether to display an alert or not, optional, defaults to false
|
48 |
+
* @return string
|
49 |
+
*/
|
50 |
+
protected function get_action_link($args, $warning = false) {
|
51 |
+
$args['page'] = 'wp-lingotek_manage';
|
52 |
+
$args['noheader'] = true;
|
53 |
+
return parent::get_action_link($args, $warning);
|
54 |
+
}
|
55 |
+
|
56 |
+
/*
|
57 |
+
* adds a row actions links
|
58 |
+
*
|
59 |
+
* @since 0.2
|
60 |
+
*
|
61 |
+
* @param string $name strings group name
|
62 |
+
* @return array
|
63 |
+
*/
|
64 |
+
public function row_actions($name) {
|
65 |
+
return $this->_row_actions(array(), $name);
|
66 |
+
}
|
67 |
+
|
68 |
+
/*
|
69 |
+
* manages Lingotek actions
|
70 |
+
*
|
71 |
+
* @since 0.2
|
72 |
+
*/
|
73 |
+
public function manage_actions($action) {
|
74 |
+
|
75 |
+
$redirect = remove_query_arg( array('action', 'action2'), wp_get_referer() );
|
76 |
+
if (!$redirect)
|
77 |
+
$redirect = admin_url("admin.php?page=wp-lingotek_manage&sm=strings");
|
78 |
+
|
79 |
+
switch($action) {
|
80 |
+
case 'bulk-lingotek-upload':
|
81 |
+
$ids = array();
|
82 |
+
|
83 |
+
foreach ($_REQUEST['strings'] as $id) {
|
84 |
+
// safe upload
|
85 |
+
if ($this->lgtm->can_upload('string', $id))
|
86 |
+
$ids[] = $id;
|
87 |
+
}
|
88 |
+
|
89 |
+
case 'bulk-lingotek-request':
|
90 |
+
case 'bulk-lingotek-download':
|
91 |
+
case 'bulk-lingotek-status':
|
92 |
+
case 'bulk-lingotek-delete':
|
93 |
+
if (empty($ids)) {
|
94 |
+
if (empty($_REQUEST['strings']))
|
95 |
+
return;
|
96 |
+
|
97 |
+
$ids = $_REQUEST['strings'];
|
98 |
+
}
|
99 |
+
|
100 |
+
check_admin_referer('bulk-lingotek-strings-translations');
|
101 |
+
$redirect = add_query_arg($action, 1, $redirect);
|
102 |
+
$redirect = add_query_arg('ids', implode(',', array_map('intval', $ids)), $redirect);
|
103 |
+
|
104 |
+
break;
|
105 |
+
|
106 |
+
case 'lingotek-upload':
|
107 |
+
check_admin_referer('lingotek-upload');
|
108 |
+
$this->lgtm->upload_strings($_GET['string']);
|
109 |
+
break;
|
110 |
+
|
111 |
+
default:
|
112 |
+
if (!$this->_manage_actions($action))
|
113 |
+
return; // do not redirect if this is not one of our actions
|
114 |
+
|
115 |
+
}
|
116 |
+
|
117 |
+
wp_redirect($redirect);
|
118 |
+
exit();
|
119 |
+
|
120 |
+
}
|
121 |
+
|
122 |
+
/*
|
123 |
+
* ajax response to upload documents and showing progress
|
124 |
+
*
|
125 |
+
* @since 0.2
|
126 |
+
*/
|
127 |
+
public function ajax_upload() {
|
128 |
+
check_ajax_referer('lingotek_progress', '_lingotek_nonce');
|
129 |
+
$this->lgtm->upload_strings($_POST['id']);
|
130 |
+
die();
|
131 |
+
}
|
132 |
+
|
133 |
+
/*
|
134 |
+
* automatic upload of strings when an option is updated
|
135 |
+
*
|
136 |
+
* @since 0.2
|
137 |
+
*/
|
138 |
+
public function updated_option() {
|
139 |
+
foreach (Lingotek_Model::get_strings() as $id) {
|
140 |
+
if ($this->lgtm->can_upload('string', $id['context']))
|
141 |
+
$this->lgtm->upload_strings($id['context']);
|
142 |
+
}
|
143 |
+
}
|
144 |
+
}
|
admin/strings-table.php
ADDED
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if(!class_exists('WP_List_Table')){
|
4 |
+
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' ); // since WP 3.1
|
5 |
+
}
|
6 |
+
|
7 |
+
class Lingotek_Strings_Table extends WP_List_Table {
|
8 |
+
public $pllm, $lgtm, $string_actions;
|
9 |
+
|
10 |
+
/*
|
11 |
+
* constructor
|
12 |
+
*
|
13 |
+
* @since 0.2
|
14 |
+
*/
|
15 |
+
function __construct($string_actions) {
|
16 |
+
parent::__construct(array(
|
17 |
+
'plural' => 'lingotek-strings-translations', // do not translate (used for css class)
|
18 |
+
'ajax' => false
|
19 |
+
));
|
20 |
+
$this->pllm = $GLOBALS['polylang']->model;
|
21 |
+
$this->lgtm = $GLOBALS['wp_lingotek']->model;
|
22 |
+
$this->string_actions = $string_actions;
|
23 |
+
}
|
24 |
+
|
25 |
+
/*
|
26 |
+
* displays the item information in a column (default case)
|
27 |
+
*
|
28 |
+
* @since 0.2
|
29 |
+
*
|
30 |
+
* @param array $item
|
31 |
+
* @param string $column_name
|
32 |
+
* @return string
|
33 |
+
*/
|
34 |
+
function column_default($item, $column_name) {
|
35 |
+
// generic case (count)
|
36 |
+
if (false === strpos($column_name, 'language_'))
|
37 |
+
return $item[$column_name];
|
38 |
+
|
39 |
+
// language column
|
40 |
+
$language = $this->pllm->get_language(substr($column_name, 9));
|
41 |
+
$document = $this->lgtm->get_group('string', $item['context']); // FIXME
|
42 |
+
|
43 |
+
// post ready for upload
|
44 |
+
if ($this->lgtm->can_upload('string', $item['context']) && $language->slug == $this->pllm->options['default_lang'])
|
45 |
+
echo $this->string_actions->upload_icon($item['context']);
|
46 |
+
|
47 |
+
// translation disabled
|
48 |
+
elseif (isset($document->source) && $document->is_disabled_target($language))
|
49 |
+
echo '<div class="lingotek-color dashicons dashicons-no"></div>';
|
50 |
+
|
51 |
+
// source post is uploaded
|
52 |
+
elseif (isset($document->source) && $document->source == $language->mo_id)
|
53 |
+
echo 'importing' == $document->status ? Lingotek_Actions::importing_icon($document) : Lingotek_String_actions::uploaded_icon($item['context']);
|
54 |
+
|
55 |
+
// translations
|
56 |
+
elseif (isset($document->translations[$language->locale]) || (isset($document->source) && 'current' == $document->status))
|
57 |
+
echo Lingotek_Actions::translation_icon($document, $language);
|
58 |
+
|
59 |
+
// no translation
|
60 |
+
else
|
61 |
+
echo '<div class="lingotek-color dashicons dashicons-no"></div>';
|
62 |
+
}
|
63 |
+
|
64 |
+
/*
|
65 |
+
* displays the checkbox in first column
|
66 |
+
*
|
67 |
+
* @since 0.2
|
68 |
+
*
|
69 |
+
* @param array $item
|
70 |
+
* @return string
|
71 |
+
*/
|
72 |
+
function column_cb($item){
|
73 |
+
return sprintf('<input type="checkbox" name="strings[]" value="%d" />', esc_attr($item['row']));
|
74 |
+
}
|
75 |
+
|
76 |
+
/*
|
77 |
+
* displays the item information in the column 'group'
|
78 |
+
* displays the row actions links
|
79 |
+
*
|
80 |
+
* @since 0.2
|
81 |
+
*
|
82 |
+
* @param object $item
|
83 |
+
* @return string
|
84 |
+
*/
|
85 |
+
function column_context($item) {
|
86 |
+
return $item['context'] . $this->row_actions($this->string_actions->row_actions($item['context']));
|
87 |
+
}
|
88 |
+
|
89 |
+
/*
|
90 |
+
* gets the list of columns
|
91 |
+
*
|
92 |
+
* @since 0.2
|
93 |
+
*
|
94 |
+
* @return array the list of column titles
|
95 |
+
*/
|
96 |
+
function get_columns() {
|
97 |
+
$columns = array(
|
98 |
+
'cb' => '<input type="checkbox" />', //checkbox
|
99 |
+
'context' => __('Group', 'wp-lingotek'),
|
100 |
+
'count' => __('Count', 'wp-lingotek'),
|
101 |
+
);
|
102 |
+
|
103 |
+
foreach ($GLOBALS['polylang']->model->get_languages_list() as $lang) {
|
104 |
+
if (!$lang->flag) {
|
105 |
+
$columns['language_' . $lang->slug] = $lang->slug;
|
106 |
+
}
|
107 |
+
else {
|
108 |
+
$columns['language_' . $lang->slug] = $lang->flag;
|
109 |
+
}
|
110 |
+
}
|
111 |
+
|
112 |
+
return $columns;
|
113 |
+
}
|
114 |
+
|
115 |
+
/*
|
116 |
+
* gets the list of sortable columns
|
117 |
+
*
|
118 |
+
* @since 0.2
|
119 |
+
*
|
120 |
+
* @return array
|
121 |
+
*/
|
122 |
+
function get_sortable_columns() {
|
123 |
+
return array(
|
124 |
+
'context' => array('context', false),
|
125 |
+
'count' => array('count', false),
|
126 |
+
);
|
127 |
+
}
|
128 |
+
|
129 |
+
/*
|
130 |
+
* prepares the list of items ofr displaying
|
131 |
+
*
|
132 |
+
* @since 0.2
|
133 |
+
*
|
134 |
+
* @param array $data
|
135 |
+
*/
|
136 |
+
function prepare_items($data = array()) {
|
137 |
+
$per_page = $this->get_items_per_page('lingotek_strings_per_page');
|
138 |
+
$this->_column_headers = array($this->get_columns(), array(), $this->get_sortable_columns());
|
139 |
+
|
140 |
+
function usort_reorder($a, $b){
|
141 |
+
$result = strcmp($a[$_REQUEST['orderby']], $b[$_REQUEST['orderby']]); // determine sort order
|
142 |
+
return (empty($_REQUEST['order']) || $_REQUEST['order'] == 'asc') ? $result : -$result; // send final sort direction to usort
|
143 |
+
};
|
144 |
+
|
145 |
+
if (!empty($_REQUEST['orderby'])) // no sort by default
|
146 |
+
usort($data, 'usort_reorder');
|
147 |
+
|
148 |
+
$total_items = count($data);
|
149 |
+
$this->items = array_slice($data, ($this->get_pagenum() - 1) * $per_page, $per_page);
|
150 |
+
|
151 |
+
$this->set_pagination_args(array(
|
152 |
+
'total_items' => $total_items,
|
153 |
+
'per_page' => $per_page,
|
154 |
+
'total_pages' => ceil($total_items/$per_page)
|
155 |
+
));
|
156 |
+
}
|
157 |
+
|
158 |
+
/*
|
159 |
+
* get the list of possible bulk actions
|
160 |
+
*
|
161 |
+
* @since 0.2
|
162 |
+
*
|
163 |
+
* @return array
|
164 |
+
*/
|
165 |
+
function get_bulk_actions() {
|
166 |
+
foreach (Lingotek_String_actions::$actions as $action => $strings)
|
167 |
+
$arr['bulk-lingotek-' . $action] = $strings['action'];
|
168 |
+
return $arr;
|
169 |
+
}
|
170 |
+
}
|
admin/table-string.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* extends the Polylang class to disable the input fields
|
5 |
+
*
|
6 |
+
* @since 0.3
|
7 |
+
*/
|
8 |
+
class Lingotek_Table_String extends PLL_Table_String {
|
9 |
+
/*
|
10 |
+
* displays the translations to edit (disabled)
|
11 |
+
*
|
12 |
+
* @since 0.3
|
13 |
+
*
|
14 |
+
* @param array $item
|
15 |
+
* @return string
|
16 |
+
*/
|
17 |
+
function column_translations($item) {
|
18 |
+
$out = '';
|
19 |
+
foreach($item['translations'] as $key => $translation) {
|
20 |
+
$input_type = $item['multiline'] ?
|
21 |
+
'<textarea name="translation[%1$s][%2$s]" id="%1$s-%2$s" disabled="disabled">%4$s</textarea>' :
|
22 |
+
'<input type="text" name="translation[%1$s][%2$s]" id="%1$s-%2$s" value="%4$s" disabled="disabled" />';
|
23 |
+
$out .= sprintf('<div class="translation"><label for="%1$s-%2$s">%3$s</label>'.$input_type.'</div>'."\n",
|
24 |
+
esc_attr($key),
|
25 |
+
esc_attr($item['row']),
|
26 |
+
esc_html($this->languages[$key]),
|
27 |
+
format_to_edit($translation)); // don't interpret special chars
|
28 |
+
}
|
29 |
+
return $out;
|
30 |
+
}
|
31 |
+
}
|
admin/term-actions.php
ADDED
@@ -0,0 +1,184 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* Adds row and bulk actions to categories and post tags list
|
5 |
+
* Manages actions which trigger communication with Lingotek TMS
|
6 |
+
*
|
7 |
+
* @since 0.2
|
8 |
+
*/
|
9 |
+
class Lingotek_Term_actions extends Lingotek_Actions {
|
10 |
+
|
11 |
+
/*
|
12 |
+
* Constructor
|
13 |
+
*
|
14 |
+
* @since 0.2
|
15 |
+
*/
|
16 |
+
public function __construct() {
|
17 |
+
parent::__construct('term');
|
18 |
+
|
19 |
+
foreach ($this->pllm->get_translated_taxonomies() as $taxonomy)
|
20 |
+
add_filter( $taxonomy . '_row_actions', array(&$this, 'term_row_actions'), 10, 2);
|
21 |
+
|
22 |
+
add_action('admin_footer-edit-tags.php', array(&$this, 'add_bulk_actions')); // FIXME admin_print_footer_scripts instead?
|
23 |
+
add_action('load-edit-tags.php', array(&$this, 'manage_actions'));
|
24 |
+
}
|
25 |
+
|
26 |
+
/*
|
27 |
+
* get the language of a term
|
28 |
+
*
|
29 |
+
* @since 0.2
|
30 |
+
*
|
31 |
+
* @param int $term_id
|
32 |
+
* @return object
|
33 |
+
*/
|
34 |
+
protected function get_language($term_id) {
|
35 |
+
return $this->pllm->get_term_language($term_id);
|
36 |
+
}
|
37 |
+
|
38 |
+
/*
|
39 |
+
* displays the icon of an uploaded term with the relevant link
|
40 |
+
*
|
41 |
+
* @since 0.2
|
42 |
+
*
|
43 |
+
* @param int $id
|
44 |
+
*/
|
45 |
+
public static function uploaded_icon($id) {
|
46 |
+
$post_type = isset($GLOBALS['post_type']) ? $GLOBALS['post_type'] : $_REQUEST['post_type']; // 2nd case for quick edit
|
47 |
+
$taxonomy = isset($GLOBALS['taxonomy']) ? $GLOBALS['taxonomy'] : $_REQUEST['taxonomy'];
|
48 |
+
$link = get_edit_term_link($id, $taxonomy, $post_type);
|
49 |
+
return self::display_icon('uploaded', $link);
|
50 |
+
}
|
51 |
+
|
52 |
+
/*
|
53 |
+
* adds a row action link
|
54 |
+
*
|
55 |
+
* @since 0.2
|
56 |
+
*
|
57 |
+
* @param array $actions list of action links
|
58 |
+
* @param object $term
|
59 |
+
* @return array
|
60 |
+
*/
|
61 |
+
public function term_row_actions($actions, $term) {
|
62 |
+
if ($this->pllm->is_translated_taxonomy($term->taxonomy)) {
|
63 |
+
$actions = $this->_row_actions($actions, $term->term_id);
|
64 |
+
|
65 |
+
$language = $this->pllm->get_term_language($term->term_id);
|
66 |
+
if (!empty($language)) {
|
67 |
+
$profile = Lingotek_Model::get_profile($term->taxonomy, $language);
|
68 |
+
if ('disabled' == $profile['profile'])
|
69 |
+
unset($actions['lingotek-upload']);
|
70 |
+
}
|
71 |
+
}
|
72 |
+
return $actions;
|
73 |
+
}
|
74 |
+
|
75 |
+
/*
|
76 |
+
* adds actions to bulk dropdown in posts list table
|
77 |
+
*
|
78 |
+
* @since 0.1
|
79 |
+
*/
|
80 |
+
public function add_bulk_actions() {
|
81 |
+
if ($this->pllm->is_translated_taxonomy($GLOBALS['taxnow']))
|
82 |
+
$this->_add_bulk_actions();
|
83 |
+
}
|
84 |
+
|
85 |
+
/*
|
86 |
+
* manages Lingotek specific actions before WordPress acts
|
87 |
+
*
|
88 |
+
* @since 0.2
|
89 |
+
*/
|
90 |
+
public function manage_actions() {
|
91 |
+
global $taxnow, $post_type;
|
92 |
+
|
93 |
+
if (!$this->pllm->is_translated_taxonomy($taxnow))
|
94 |
+
return;
|
95 |
+
|
96 |
+
// get the action
|
97 |
+
$wp_list_table = _get_list_table('WP_Terms_List_Table');
|
98 |
+
$action = $wp_list_table->current_action();
|
99 |
+
|
100 |
+
if (empty($action))
|
101 |
+
return;
|
102 |
+
|
103 |
+
$redirect = remove_query_arg( array('action', 'action2', 'delete_tags'), wp_get_referer() );
|
104 |
+
if (!$redirect)
|
105 |
+
$redirect = admin_url("edit-tags.php?taxonomy=$taxnow&post_type=$post_type");
|
106 |
+
|
107 |
+
switch($action) {
|
108 |
+
case 'bulk-lingotek-upload':
|
109 |
+
if (empty($_REQUEST['delete_tags']))
|
110 |
+
return;
|
111 |
+
|
112 |
+
$term_ids = array();
|
113 |
+
|
114 |
+
foreach (array_map('intval', $_REQUEST['delete_tags']) as $term_id) {
|
115 |
+
// safe upload
|
116 |
+
if ($this->lgtm->can_upload('term', $term_id))
|
117 |
+
$terms_ids[] = $term_id;
|
118 |
+
|
119 |
+
// the document is already translated so will be overwritten
|
120 |
+
elseif(($document = $this->lgtm->get_group('term', $term_id)) && empty($document->source)) {
|
121 |
+
// take care to upload only one post in a translation group
|
122 |
+
$intersect = array_intersect($term_ids, $this->pllm->get_translations('term', $term_id));
|
123 |
+
if (empty($intersect)) {
|
124 |
+
$term_ids[] = $term_id;
|
125 |
+
$redirect = add_query_arg('lingotek_warning', 1, $redirect);
|
126 |
+
}
|
127 |
+
}
|
128 |
+
}
|
129 |
+
|
130 |
+
// check if translation is disabled
|
131 |
+
if (!empty($term_ids)) {
|
132 |
+
foreach ($term_ids as $key => $term_id) {
|
133 |
+
$language = $this->pllm->get_term_language($term_id);
|
134 |
+
$profile = Lingotek_Model::get_profile($taxnow, $language);
|
135 |
+
if ('disabled' == $profile['profile'])
|
136 |
+
unset($term_ids[$key]);
|
137 |
+
}
|
138 |
+
}
|
139 |
+
|
140 |
+
case 'bulk-lingotek-request':
|
141 |
+
case 'bulk-lingotek-download':
|
142 |
+
case 'bulk-lingotek-status':
|
143 |
+
case 'bulk-lingotek-delete':
|
144 |
+
if (empty($_REQUEST['delete_tags']))
|
145 |
+
return;
|
146 |
+
|
147 |
+
if (empty($term_ids))
|
148 |
+
$term_ids = array_map('intval', $_REQUEST['delete_tags']);
|
149 |
+
|
150 |
+
check_admin_referer('bulk-tags');
|
151 |
+
|
152 |
+
$redirect = add_query_arg($action, 1, $redirect);
|
153 |
+
$redirect = add_query_arg('ids', implode(',', $term_ids), $redirect);
|
154 |
+
|
155 |
+
break;
|
156 |
+
|
157 |
+
case 'lingotek-upload':
|
158 |
+
check_admin_referer('lingotek-upload');
|
159 |
+
$this->lgtm->upload_term((int) $_GET['term'], $taxnow);
|
160 |
+
break;
|
161 |
+
|
162 |
+
default:
|
163 |
+
if (!$this->_manage_actions($action))
|
164 |
+
return; // do not redirect if this is not one of our actions
|
165 |
+
|
166 |
+
}
|
167 |
+
|
168 |
+
wp_redirect($redirect);
|
169 |
+
exit();
|
170 |
+
|
171 |
+
}
|
172 |
+
|
173 |
+
/*
|
174 |
+
* ajax response to upload documents and showing progress
|
175 |
+
*
|
176 |
+
* @since 0.1
|
177 |
+
*/
|
178 |
+
public function ajax_upload() {
|
179 |
+
check_ajax_referer('lingotek_progress', '_lingotek_nonce');
|
180 |
+
if (taxonomy_exists($_POST['taxonomy']))
|
181 |
+
$this->lgtm->upload_term((int) $_POST['id'], $_POST['taxonomy']);
|
182 |
+
die();
|
183 |
+
}
|
184 |
+
}
|
admin/tutorial/content.php
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<style>
|
2 |
+
.tutorial-photo-right {
|
3 |
+
width: 50%;
|
4 |
+
height: auto;
|
5 |
+
float: right;
|
6 |
+
padding-left: 3px;
|
7 |
+
}
|
8 |
+
|
9 |
+
.img-caption {
|
10 |
+
font-size: 8px;
|
11 |
+
color: #999;
|
12 |
+
font-style: italic;
|
13 |
+
padding-left: 20px;
|
14 |
+
}
|
15 |
+
|
16 |
+
th {
|
17 |
+
text-align: left;
|
18 |
+
padding-left: 10px;
|
19 |
+
}
|
20 |
+
</style>
|
21 |
+
|
22 |
+
<p><?php _e('', 'wp-lingotek') ?></p>
|
23 |
+
|
24 |
+
<div>
|
25 |
+
<h4><?php _e('1. Create content', 'wp-lingotek') ?></h4>
|
26 |
+
<p><?php _e('Whether you write a blog post, create a page for your site, or have existing posts and pages, any of your Wordpress content can be uploaded to <i>Lingotek</i>.', 'wp-lingotek') ?>
|
27 |
+
<?php _e('The examples shown below are for Pages but translation for other content types works the same way!', 'wp-lingotek') ?></p>
|
28 |
+
<img class="lingotek-bordered" src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/add-page.png'; ?>">
|
29 |
+
<p class="img-caption"><?php _e('Create a new page for translation.', 'wp-lingotek') ?></p>
|
30 |
+
</div>
|
31 |
+
<div>
|
32 |
+
<h4><?php _e('2. Upload content to Lingotek', 'wp-lingotek') ?></h4>
|
33 |
+
<p><?php _e('Your Wordpress content can be uploaded to <i>Lingotek</i> with the simple push of a button.', 'wp-lingotek') ?></p>
|
34 |
+
<img class="lingotek-bordered" src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/ready-to-upload.png'; ?>">
|
35 |
+
<p class="img-caption"><?php _e('Content has been created and is ready for upload to Lingotek.', 'wp-lingotek') ?></p>
|
36 |
+
</div>
|
37 |
+
<div>
|
38 |
+
<h4><?php _e('3. Request translations for target languages', 'wp-lingotek') ?></h4>
|
39 |
+
<p><?php _e('Request translation for a specific language by clicking on the orange plus icon, for all languages at once, or in bulk by using the <i>Bulk Actions</i> dropdown.', 'wp-lingotek') ?></p>
|
40 |
+
<img class="lingotek-bordered" src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/request-translations.png'; ?>">
|
41 |
+
<p class="img-caption"><?php _e('The source content is uploaded and ready for target languages.', 'wp-lingotek') ?></p>
|
42 |
+
</div>
|
43 |
+
<div>
|
44 |
+
<h4><?php _e('4. Translate your content', 'wp-lingotek') ?></h4>
|
45 |
+
<p><?php _e('Your content will now be translated into your selected target languages by free machine translation or, if you contract with <i>Lingotek</i>, professional translation services.', 'wp-lingotek') ?></p>
|
46 |
+
<img class="lingotek-bordered" src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/translations-underway.png'; ?>">
|
47 |
+
<p class="img-caption"><?php _e('Your translations are underway.', 'wp-lingotek') ?></p>
|
48 |
+
</div>
|
49 |
+
<div>
|
50 |
+
<h4><?php _e('5. Download translations', 'wp-lingotek') ?></h4>
|
51 |
+
<p><?php _e('Once your translations are complete they will be marked ready for download. You can download translations for all languages, each language individually, or in bulk (using the <i>Bulk Actions</i> dropdown).', 'wp-lingotek') ?></p>
|
52 |
+
<img class="lingotek-bordered" src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/translations-ready-for-download.png'; ?>">
|
53 |
+
<p class="img-caption"><?php _e('Your translations are ready for download.', 'wp-lingotek') ?></p>
|
54 |
+
</div>
|
55 |
+
<div>
|
56 |
+
<h4><?php _e('6. Your content is translated!', 'wp-lingotek') ?></h4>
|
57 |
+
<p><?php _e('The orange pencil icons indicate that your translations are finished, downloaded, and current within your Wordpress site. Clicking on any one of the pencils will direct you to the Lingotek Workbench for that specific language. Here you can make updates and changes to your translations if necessary.', 'wp-lingotek') ?></p>
|
58 |
+
<img class="lingotek-bordered" src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/translations-downloaded.png'; ?>">
|
59 |
+
<p class="img-caption"><?php _e('Your content has been translated.', 'wp-lingotek') ?></p>
|
60 |
+
</div>
|
61 |
+
|
62 |
+
<h2><?php _e('What do all the icons mean?', 'wp-lingotek') ?></h2>
|
63 |
+
|
64 |
+
<table>
|
65 |
+
<tr>
|
66 |
+
<td><span class="lingotek-color dashicons dashicons-upload"></span></td>
|
67 |
+
<th><?php _e('Upload Source', 'wp-lingotek') ?></th>
|
68 |
+
<td><?php _e('There is content ready to be uploaded to Lingotek.', 'wp-lingotek') ?></td>
|
69 |
+
</tr>
|
70 |
+
<tr>
|
71 |
+
<td><span class="lingotek-color dashicons dashicons-clock"></span></td>
|
72 |
+
<th><?php _e('In Progress', 'wp-lingotek') ?></th>
|
73 |
+
<td><?php _e('Content is importing to Lingotek or a target language is being added to source content.', 'wp-lingotek') ?></td>
|
74 |
+
</tr>
|
75 |
+
<tr>
|
76 |
+
<td><span class="lingotek-color dashicons dashicons-yes"></span></td>
|
77 |
+
<th><?php _e('Source Uploaded', 'wp-lingotek') ?></th>
|
78 |
+
<td><?php _e('The source content has been uploaded to Lingotek.', 'wp-lingotek') ?></td>
|
79 |
+
</tr>
|
80 |
+
<tr>
|
81 |
+
<td><span class="lingotek-color dashicons dashicons-plus"></span></td>
|
82 |
+
<th><?php _e('Request Translation', 'wp-lingotek') ?></th>
|
83 |
+
<td><?php _e('Request a translation of the source content. (Add a target language)', 'wp-lingotek') ?></td>
|
84 |
+
</tr>
|
85 |
+
<tr>
|
86 |
+
<td><span class="lingotek-color dashicons dashicons-download"></span></td>
|
87 |
+
<th><?php _e('Download Translation', 'wp-lingotek') ?></th>
|
88 |
+
<td><?php _e('Download the translated content to Wordpress.', 'wp-lingotek') ?></td>
|
89 |
+
</tr>
|
90 |
+
<tr>
|
91 |
+
<td><span class="lingotek-color dashicons dashicons-edit"></span></td>
|
92 |
+
<th><?php _e('Translation Current', 'wp-lingotek') ?></th>
|
93 |
+
<td><?php _e('The translation is complete. (Clicking on this icon will allow you to edit translations in the Lingotek Workbench)', 'wp-lingotek') ?></td>
|
94 |
+
</tr>
|
95 |
+
</table>
|
admin/tutorial/credits.php
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$people = array(
|
4 |
+
'fred'=>array(
|
5 |
+
'name'=>'Frédéric Demarle',
|
6 |
+
'title'=>'Lead Polylang Developer',
|
7 |
+
'image_url'=>'https://www.gravatar.com/avatar/132157ff7a533c8e9a272795a1b5c2b9',
|
8 |
+
'url'=>'https://profiles.wordpress.org/chouby'),
|
9 |
+
'matt'=>array(
|
10 |
+
'name'=>'Matt Smith',
|
11 |
+
'title'=>'Lead Developer',
|
12 |
+
'image_url'=>'https://www.gravatar.com/avatar/d79b46c94a52b4679c308986ef05eac2',
|
13 |
+
'url'=>'https://profiles.wordpress.org/smithworx'),
|
14 |
+
'brian'=>array(
|
15 |
+
'name'=>'Brian Isle',
|
16 |
+
'title'=>'Quality Assurance',
|
17 |
+
'image_url'=>'https://www.gravatar.com/avatar/5f43658c382412d8f120cb5595d9bf03',
|
18 |
+
'url'=>'https://profiles.wordpress.org/bisle'),
|
19 |
+
'edward'=>array(
|
20 |
+
'name'=>'Edward Richards',
|
21 |
+
'title'=>'Developer',
|
22 |
+
'image_url'=>'https://www.gravatar.com/avatar/a0ab415173b16d2ac476077d587bea96',
|
23 |
+
'url'=>'https://profiles.wordpress.org/erichie'),
|
24 |
+
'calvin'=>array(
|
25 |
+
'name'=>'Calvin Scharffs',
|
26 |
+
'title'=>'Marketing Guru',
|
27 |
+
'image_url'=>'https://www.gravatar.com/avatar/d18e8bf783f63bf893e143cf04e0034d',
|
28 |
+
'url'=>'https://profiles.wordpress.org/cscharffs'),
|
29 |
+
'brad'=>array(
|
30 |
+
'name'=>'Brad Ross',
|
31 |
+
'title'=>'Product Management',
|
32 |
+
'image_url'=>'https://www.gravatar.com/avatar/477601d2c0c8c8dd31c021e3bae3841c',
|
33 |
+
'url'=>'https://profiles.wordpress.org/bradross12/'),
|
34 |
+
'laura'=>array(
|
35 |
+
'name'=>'Laura White',
|
36 |
+
'title'=>'Tech Writer',
|
37 |
+
'image_url'=>'https://www.gravatar.com/avatar/56c44e12c3431aca766d06c6019201ff',
|
38 |
+
'url'=>'https://profiles.wordpress.org/laurakaysc'),
|
39 |
+
);
|
40 |
+
|
41 |
+
shuffle($people);
|
42 |
+
|
43 |
+
?>
|
44 |
+
|
45 |
+
<p class="about-description"><?php _e('The Lingotek plugin for WordPress is created with love.', 'wp-lingotek'); ?></p>
|
46 |
+
|
47 |
+
<h4 class="wp-people-group"><?php _e('Team', 'wp-lingotek'); ?></h4>
|
48 |
+
|
49 |
+
<ul class="wp-people-group">
|
50 |
+
<?php
|
51 |
+
|
52 |
+
foreach($people as $person_key=>$person){
|
53 |
+
printf('<li class="wp-person" id="wp-person-%s">
|
54 |
+
<a href="%s"><img src="%s?s=60&d=mm&r=G" srcset="%s?s=120&d=mm&r=G 2x" class="gravatar" alt="%s"></a>
|
55 |
+
<a class="web" href="%s">%s</a>
|
56 |
+
<span class="title">%s</span>
|
57 |
+
</li>',$person_key,$person['url'],$person['image_url'],$person['image_url'],$person['name'],$person['url'],$person['name'],$person['title']);
|
58 |
+
}
|
59 |
+
|
60 |
+
?>
|
61 |
+
</ul>
|
admin/tutorial/faq.php
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<style>
|
2 |
+
.tutorial-photo-right {
|
3 |
+
width: 50%;
|
4 |
+
height: auto;
|
5 |
+
float: right;
|
6 |
+
padding-left: 3px;
|
7 |
+
}
|
8 |
+
</style>
|
9 |
+
|
10 |
+
<p class="about-description"><?php _e('Questions and answers...', 'wp-lingotek'); ?></p>
|
11 |
+
|
12 |
+
<b><?php _e('How does this really work?', 'wp-lingotek') ?></b>
|
13 |
+
<p><?php _e('<i>Polylang</i> puts in the framework to make WordPress multilingual and <i>Lingotek</i> leverages that framework to provide localization through machine translation and professional translation services.', 'wp-lingotek') ?></p>
|
14 |
+
|
15 |
+
<b><?php _e('What does the Lingotek plugin do?', 'wp-lingotek') ?></b>
|
16 |
+
<p><?php _e('<i>Lingotek</i> has teamed up with <i>Polylang</i> to offer a simple way to make your WordPress site truly multilingual. Manage all your multilingual content in the same site. No need to have a different site for each language!', 'wp-lingotek') ?></p>
|
17 |
+
|
18 |
+
<b><?php _e('How can I add a language?', 'wp-lingotek') ?></b>
|
19 |
+
<p><?php _e('On the <i>translation dashboard</i>, click on the <i>Translate my site into...</i> textbox and choose from the list or start typing to quickly find a language.', 'wp-lingotek') ?></p>
|
20 |
+
|
21 |
+
<b><?php _e('How can I remove a language?', 'wp-lingotek') ?></b>
|
22 |
+
<p>
|
23 |
+
<?php _e('On the <i>translation dashboard</i>, click on the blue check mark for the language you would like to remove.', 'wp-lingotek') ?>
|
24 |
+
<i><?php _e('Note: If you have translated content in a language you will not be able to remove that language until that content has been deleted.', 'wp-lingotek') ?></i>
|
25 |
+
</p>
|
26 |
+
|
27 |
+
<b><?php _e("Can I use my own translation agency with Lingotek?", 'wp-lingotek') ?></b>
|
28 |
+
<p><?php _e( "Use your own translation agency or tap into Lingotek's network of more than 5,000+ in-country translators. Content transfer is fully automated between WordPress and Lingotek. You'll have full visibility into the translation process every step of the way. And once the translations are completed, they'll automatically download and publish to your website according to the preferences you've set." , 'wp-lingotek'); ?></p>
|
29 |
+
|
30 |
+
<b><?php _e('How can I check the overall translation progress of my site?', 'wp-lingotek') ?></b>
|
31 |
+
<p><?php _e('On the <i>translation dashboard</i>, the bars under <i>Completed Percentage</i> show the translation progress of content for each language. You can filter by content type or show progress for all content.', 'wp-lingotek') ?></p>
|
32 |
+
<ul>
|
33 |
+
<li>
|
34 |
+
<b><?php _e('Why are there two different shades of blue in the progress bar?', 'wp-lingotek') ?></b>
|
35 |
+
<p><?php _e('The <i>translation dashboard</i> not only shows how much of your content is translated, but also indicates the language that your source content was authored in.', 'wp-lingotek') ?></p>
|
36 |
+
</li>
|
37 |
+
<ul style="list-style-type:disc; padding-left:30px">
|
38 |
+
<li><?php _e('<i>Dark Blue:</i> Indicates that this is a source language that the content was authored in.', 'wp-lingotek') ?></li>
|
39 |
+
<li><?php _e('<i>Light Blue:</i> Indicates that this is a target language that the content was translated into.', 'wp-lingotek') ?></li>
|
40 |
+
</ul>
|
41 |
+
</ul>
|
42 |
+
|
43 |
+
<b><?php _e('What happens when I <i>Disassociate Translations</i>?', 'wp-lingotek') ?></b>
|
44 |
+
<p><?php _e('When content is disassociated the connection between WordPress and <i>Lingotek</i> safely disconnected from Lingotek, so that translations can be solely managed inside of WordPress.', 'wp-lingotek') ?></p>
|
45 |
+
|
46 |
+
<b><?php _e("How do I translate strings within widgets or general WordPress settings (e.g., Site Title, Tagline)?", 'wp-lingotek') ?></b>
|
47 |
+
<p><?php printf(__( "Groups of strings can be sent for translation and managed using the <a href='%s'>String Groups</a> page. Individual strings may be viewed on the <a href='%s'>Strings</a> page." , 'wp-lingotek'),'admin.php?page=wp-lingotek_manage&sm=string-groups','admin.php?page=wp-lingotek_manage&sm=strings'); ?></p>
|
48 |
+
|
49 |
+
|
50 |
+
<div class="changelog feature-section two-col">
|
51 |
+
<div>
|
52 |
+
<img class="workbench-image" src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/workbench-full.png'; ?>">
|
53 |
+
<h3><?php _e( 'Lingotek Workbench', 'wp-lingotek'); ?></h3>
|
54 |
+
<p><?php _e( 'Lingotek Translation is the only WordPress plugin to integrate a Translation Management System directly into WordPress, thus allowing the WordPress community to use professional-grade translation technologies (e.g. machine translation, translation memory, CAT tool) without ever having to leave the comfort of the WordPress environment.', 'wp-lingotek'); ?></p>
|
55 |
+
</div>
|
56 |
+
<div class="last-feature">
|
57 |
+
<a href="admin.php?page=wp-lingotek"><img src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/dashboard.png'; ?>"></a>
|
58 |
+
<h3><?php _e( 'Translation Dashboard', 'wp-lingotek'); ?></h3>
|
59 |
+
<p><?php _e( "The <i>translation dashboard</i> allows you to view your site languages, add and remove new languages, check the overall translation progress of your site, see site analytics, and connect with Lingotek support.", 'wp-lingotek'); ?></p>
|
60 |
+
</div>
|
61 |
+
</div>
|
62 |
+
|
63 |
+
|
64 |
+
|
admin/tutorial/features.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="changelog feature-section three-col">
|
3 |
+
<div>
|
4 |
+
<a href="admin.php?page=wp-lingotek"><img src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/add-languages.png'; ?>"></a>
|
5 |
+
<h3><?php _e( 'Translate into new languages', 'wp-lingotek' ); ?></h3>
|
6 |
+
<p><?php printf( __( 'Easily translate your site into new languages by adding the desired language to your site. Lingotek allows you to quickly add any of the most frequently used locales using the <a href="%s" title="Translation > Dashboard">Translation Dashboard</a>.', 'wp-lingotek' ), 'admin.php?page=wp-lingotek' ); ?></p>
|
7 |
+
</div>
|
8 |
+
<div>
|
9 |
+
<img class="lingotek-bordered" src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/automatic-translation.gif'; ?>">
|
10 |
+
<h3><?php _e( 'Automatically translate content', 'wp-lingotek' ); ?></h3>
|
11 |
+
<p><?php _e( "Machine translation is an excellent option if you're on a tight budget, looking for near-instant results, and are okay with less-than-perfect quality. The plugin allows you to quickly and automatically translate your site (the cost is covered by Lingotek for up to 100,000 characters).", 'wp-lingotek'); ?></p>
|
12 |
+
</div>
|
13 |
+
<div class="last-feature">
|
14 |
+
<img src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/polylang-compatible.png'; ?>">
|
15 |
+
<h3><?php _e( 'Fully compatible with Polylang', 'wp-lingotek' ); ?></h3>
|
16 |
+
<p><?php printf( __( 'Polylang and Lingotek work together seamlessly. Continue to use Polylang for content that you want to translate inside WordPress, while sending other content to be translated by Lingotek. The <b style="color: %s">orange</b> icons indicate Lingotek statuses/actions while the <b style="color: %s">blue</b> icons continue to represent Polylang actions.', 'wp-lingotek' ), 'darkorange', '#0473a8' ); ?></p>
|
17 |
+
</div>
|
18 |
+
|
19 |
+
</div>
|
20 |
+
|
21 |
+
|
22 |
+
<div class="changelog feature-section three-col">
|
23 |
+
<div>
|
24 |
+
<a href="admin.php?page=wp-lingotek_settings&sm=profiles"><img src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/translation-profiles.png'; ?>"></a>
|
25 |
+
<h3><?php _e( 'Use translation profiles', 'wp-lingotek'); ?></h3>
|
26 |
+
<p><?php _e( 'One of the most time-consuming activities of any multilingual web-site project is managing the ongoing flow of changes and additions to site content and configurations. Translation profiles were created to allow you to create and save and re-use your translation settings.', 'wp-lingotek'); ?></p>
|
27 |
+
</div>
|
28 |
+
<div>
|
29 |
+
<a href="admin.php?page=wp-lingotek_settings&sm=content"><img src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/content-types.png'; ?>"></a>
|
30 |
+
<h3><?php _e( 'Content type profiles', 'wp-lingotek'); ?></h3>
|
31 |
+
<p><?php _e( 'Content type profiles. Manually choosing which content to upload and download is rarely what a content administrator wants to do, and automating the upload of every change is not workable because there are various types of content. Each type of translatable content can be assigned to a customizable profile. For example, by default, we like to have Posts use an <i>Automatic</i> profile so that content will automatically be uploaded for translation and the resulting translations automatically be downloaded back into WordPress.', 'wp-lingotek'); ?></p>
|
32 |
+
</div>
|
33 |
+
<div class="last-feature">
|
34 |
+
<!-- <img style="" class="lingotek-bordered" src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/pro-translation.png'; ?>"> -->
|
35 |
+
<img src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/professional-translation.png'; ?>">
|
36 |
+
<h3><?php _e( 'Request professional translation', 'wp-lingotek'); ?></h3>
|
37 |
+
<p><?php _e( "Use your own translation agency or tap into Lingotek's network of more than 5,000+ in-country translators. Content transfer is fully automated between WordPress and Lingotek. You'll have full visibility into the translation process every step of the way. And once the translations are completed, they'll automatically download and publish to your website according to the preferences you've set.", 'wp-lingotek'); ?></p>
|
38 |
+
</div>
|
39 |
+
</div>
|
admin/tutorial/img/add-languages.png
ADDED
Binary file
|
admin/tutorial/img/add-page.png
ADDED
Binary file
|
admin/tutorial/img/add-page2.png
ADDED
Binary file
|
admin/tutorial/img/automatic-translation.gif
ADDED
Binary file
|
admin/tutorial/img/automatic-translation.png
ADDED
Binary file
|
admin/tutorial/img/check-status.png
ADDED
Binary file
|
admin/tutorial/img/content-types.png
ADDED
Binary file
|
admin/tutorial/img/dashboard.png
ADDED
Binary file
|
admin/tutorial/img/polylang-compatible.png
ADDED
Binary file
|
admin/tutorial/img/pro-translation.png
ADDED
Binary file
|
admin/tutorial/img/professional-translation.png
ADDED
Binary file
|
admin/tutorial/img/ready-to-upload.png
ADDED
Binary file
|
admin/tutorial/img/request-translations.png
ADDED
Binary file
|
admin/tutorial/img/translation-profiles.png
ADDED
Binary file
|
admin/tutorial/img/translations-downloaded.png
ADDED
Binary file
|
admin/tutorial/img/translations-ready-for-download.png
ADDED
Binary file
|
admin/tutorial/img/translations-underway.png
ADDED
Binary file
|
admin/tutorial/img/workbench-full.png
ADDED
Binary file
|
admin/tutorial/img/workbench.png
ADDED
Binary file
|
admin/utilities.php
ADDED
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* A class to manage utilities
|
5 |
+
*
|
6 |
+
* @since 0.2
|
7 |
+
*/
|
8 |
+
class Lingotek_Utilities {
|
9 |
+
public $pllm, $lgtm; // Polylang and Lingotek models
|
10 |
+
|
11 |
+
/*
|
12 |
+
* Constructor
|
13 |
+
*
|
14 |
+
* @since 0.2
|
15 |
+
*/
|
16 |
+
public function __construct() {
|
17 |
+
$this->pllm = $GLOBALS['polylang']->model;
|
18 |
+
$this->lgtm = $GLOBALS['wp_lingotek']->model;
|
19 |
+
|
20 |
+
add_action('admin_enqueue_scripts', array(&$this, 'admin_enqueue_scripts'));
|
21 |
+
add_action('wp_ajax_lingotek_progress_disassociate' , array(&$this, 'ajax_utility_disassociate'));
|
22 |
+
add_action('wp_ajax_lingotek_progress_disassociate_and_delete' , array(&$this, 'ajax_utility_disassociate'));
|
23 |
+
}
|
24 |
+
|
25 |
+
/*
|
26 |
+
* run an array of utilities
|
27 |
+
*
|
28 |
+
* @since 0.2
|
29 |
+
*
|
30 |
+
* @param array $utilities array of utility names to run
|
31 |
+
* @return array
|
32 |
+
*/
|
33 |
+
public function run_utilities($utilities){
|
34 |
+
$results = array();
|
35 |
+
if(!empty($utilities) && is_array($utilities)){
|
36 |
+
foreach($utilities as $utility_name) {
|
37 |
+
$results[] = $this->run_utility($utility_name);
|
38 |
+
}
|
39 |
+
}
|
40 |
+
return $results;
|
41 |
+
}
|
42 |
+
|
43 |
+
/*
|
44 |
+
* run a specified utility by name
|
45 |
+
*
|
46 |
+
* @since 0.2
|
47 |
+
*
|
48 |
+
* @param string $utilty_name
|
49 |
+
* @return boolean $result
|
50 |
+
*/
|
51 |
+
public function run_utility($utility_name) {
|
52 |
+
$result = 0;
|
53 |
+
switch ($utility_name) {
|
54 |
+
case "set_default_language":
|
55 |
+
case "utility_set_default_language":
|
56 |
+
$result = $this->utility_set_default_language();
|
57 |
+
break;
|
58 |
+
default:
|
59 |
+
break;
|
60 |
+
}
|
61 |
+
return $result;
|
62 |
+
}
|
63 |
+
|
64 |
+
// Utilities
|
65 |
+
|
66 |
+
/*
|
67 |
+
* fills existing posts & terms with default language
|
68 |
+
*
|
69 |
+
* @since 0.2
|
70 |
+
*/
|
71 |
+
public function utility_set_default_language() {
|
72 |
+
if ($nolang = $this->pllm->get_objects_with_no_lang()) {
|
73 |
+
if (!empty($nolang['posts']))
|
74 |
+
$this->pllm->set_language_in_mass('post', $nolang['posts'], $this->pllm->options['default_lang']);
|
75 |
+
if (!empty($nolang['terms']))
|
76 |
+
$this->pllm->set_language_in_mass('term', $nolang['terms'], $this->pllm->options['default_lang']);
|
77 |
+
}
|
78 |
+
add_settings_error('lingotek_utilities', 'utilities', __('The language update utility ran successfully.', 'wp-lingotek'), 'updated');
|
79 |
+
return 0;
|
80 |
+
}
|
81 |
+
|
82 |
+
/*
|
83 |
+
* get all (associated) Lingotek document ids
|
84 |
+
*
|
85 |
+
* @since 0.2
|
86 |
+
*
|
87 |
+
* @return array
|
88 |
+
*/
|
89 |
+
static public function get_all_document_ids() {
|
90 |
+
$terms = get_terms(array('post_translations', 'term_translations'));
|
91 |
+
foreach ($terms as $term) {
|
92 |
+
$desc_arr = unserialize($term->description);
|
93 |
+
if (!empty($desc_arr['lingotek']))
|
94 |
+
$ids[] = $term->slug;
|
95 |
+
}
|
96 |
+
|
97 |
+
return empty($ids) ? array() : $ids;
|
98 |
+
}
|
99 |
+
|
100 |
+
/*
|
101 |
+
* outputs javascript data for progress.js
|
102 |
+
*
|
103 |
+
* @since 0.2
|
104 |
+
*/
|
105 |
+
public function admin_enqueue_scripts() {
|
106 |
+
if (!empty($_POST['utility_disassociate'])) {
|
107 |
+
$ids = self::get_all_document_ids();
|
108 |
+
if (!empty($ids)) {
|
109 |
+
wp_localize_script('lingotek_progress', 'lingotek_data', array(
|
110 |
+
'action' => 'disassociate' . ('on' == $_POST['utility_delete_documents'] ? '_and_delete' : ''),
|
111 |
+
'taxonomy' => '',
|
112 |
+
'sendback' => wp_get_referer(),
|
113 |
+
'ids' => $ids, // Lingotek document ids
|
114 |
+
'warning' => '',
|
115 |
+
'nonce' => wp_create_nonce('lingotek_progress')
|
116 |
+
));
|
117 |
+
}
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
/*
|
122 |
+
* ajax response to disassociate documents and showing progress
|
123 |
+
*
|
124 |
+
* @since 0.2
|
125 |
+
*/
|
126 |
+
public function ajax_utility_disassociate() {
|
127 |
+
check_ajax_referer('lingotek_progress', '_lingotek_nonce');
|
128 |
+
if ($group = $this->lgtm->get_group_by_id($_POST['id']))
|
129 |
+
$group->disassociate('lingotek_progress_disassociate_and_delete' == $_POST['action']);
|
130 |
+
die();
|
131 |
+
}
|
132 |
+
}
|
admin/view-dashboard.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="wrap">
|
2 |
+
<h2><?php _e('Dashboard', 'wp-lingotek'); ?></h2>
|
3 |
+
<script>
|
4 |
+
var cms_data = <?php echo json_encode($cms_data); ?>
|
5 |
+
</script>
|
6 |
+
<link rel="stylesheet" href="http://gmc.lingotek.com/v2/styles/ltk.css">
|
7 |
+
<script src="http://gmc.lingotek.com/v2/ltk.min.js"></script>
|
8 |
+
<div ltk-dashboard ng-app="LingotekApp" style="margin-top: -15px;"></div>
|
9 |
+
</div>
|
admin/view-manage.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="wrap">
|
2 |
+
<h2><?php _e('Manage', 'wp-lingotek'); ?></h2>
|
3 |
+
|
4 |
+
<?php
|
5 |
+
|
6 |
+
$menu_items = array(
|
7 |
+
'string-groups' => __('String Groups', 'wp-lingotek'),
|
8 |
+
'strings' => __('Strings', 'wp-lingotek'),
|
9 |
+
);
|
10 |
+
|
11 |
+
?>
|
12 |
+
|
13 |
+
<h3 class="nav-tab-wrapper">
|
14 |
+
<?php
|
15 |
+
$menu_item_index = 0;
|
16 |
+
foreach ($menu_items as $menu_item_key => $menu_item_label) {
|
17 |
+
$use_as_default = ($menu_item_index === 0 && !isset($_GET['sm'])) ? TRUE : FALSE;
|
18 |
+
?>
|
19 |
+
|
20 |
+
<a class="nav-tab <?php if ($use_as_default || (isset($_GET['sm']) && $_GET['sm'] == $menu_item_key)): ?> nav-tab-active<?php endif; ?>"
|
21 |
+
href="admin.php?page=<?php echo $_GET['page']; ?>&sm=<?php echo $menu_item_key; ?>"><?php echo $menu_item_label; ?></a>
|
22 |
+
<?php
|
23 |
+
$menu_item_index++;
|
24 |
+
}
|
25 |
+
?>
|
26 |
+
</h3>
|
27 |
+
|
28 |
+
<?php
|
29 |
+
settings_errors();
|
30 |
+
$submenu = isset($_GET['sm']) ? $_GET['sm'] : current(array_keys($menu_items));
|
31 |
+
$dir = dirname(__FILE__) . '/manage/';
|
32 |
+
$filename = $dir . 'view-' . $submenu . ".php";
|
33 |
+
if (file_exists($filename))
|
34 |
+
include $filename;
|
35 |
+
else
|
36 |
+
echo "TO-DO: create <i>" . 'manage/view-' . $submenu . ".php</i>";
|
37 |
+
?>
|
38 |
+
|
39 |
+
</div>
|
admin/view-network.php
ADDED
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
$sites = wp_get_sites();
|
3 |
+
$site_data = array();
|
4 |
+
|
5 |
+
foreach ($sites as $site)
|
6 |
+
{
|
7 |
+
switch_to_blog($site['blog_id']);
|
8 |
+
$details = get_blog_details($site['blog_id'])->blogname;
|
9 |
+
$temp = array("blog_id" => $site['blog_id'], "blogname" => $details);
|
10 |
+
array_push($site_data, $temp);
|
11 |
+
$ltk = new Lingotek();
|
12 |
+
$ltk->admin_init();
|
13 |
+
restore_current_blog();
|
14 |
+
}
|
15 |
+
|
16 |
+
if (!empty($_POST)) {
|
17 |
+
$source_site = $_POST['source'];
|
18 |
+
|
19 |
+
if (isset($_POST['destination'])) {
|
20 |
+
$destination_site = $_POST['destination'];
|
21 |
+
|
22 |
+
foreach ($destination_site as $destination) {
|
23 |
+
|
24 |
+
if (!empty($_POST['settings'])) {
|
25 |
+
$selected_settings = $_POST['settings'];
|
26 |
+
|
27 |
+
foreach ($selected_settings as $setting) {
|
28 |
+
//Updates account options for access token and the base url to connect to Lingotek
|
29 |
+
if ($setting == 'token') {
|
30 |
+
$lingotek_option = 'lingotek_' . $setting;
|
31 |
+
|
32 |
+
$source_options = get_blog_option($source_site, $lingotek_option);
|
33 |
+
update_blog_option($destination, $lingotek_option, $source_options);
|
34 |
+
|
35 |
+
$source_options = get_blog_option($source_site, 'lingotek_base_url');
|
36 |
+
update_blog_option($destination, 'lingotek_base_url', $source_options);
|
37 |
+
}
|
38 |
+
|
39 |
+
//Updates the chosen option
|
40 |
+
$lingotek_option = 'lingotek_' . $setting;
|
41 |
+
|
42 |
+
$source_options = get_blog_option($source_site, $lingotek_option);
|
43 |
+
update_blog_option($destination, $lingotek_option, $source_options);
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
//Creates a new project based on the name of the selected site
|
48 |
+
if (isset($_POST['new_project'])) {
|
49 |
+
$options = get_blog_option($destination, 'lingotek_defaults');
|
50 |
+
$client = new Lingotek_API();
|
51 |
+
$title = htmlspecialchars_decode(get_blog_details($destination)->blogname, ENT_QUOTES);
|
52 |
+
|
53 |
+
if ($new_id = $client->create_project($title, $community_id = get_blog_option($destination, 'lingotek_community'))) {
|
54 |
+
$options['project_id'] = $new_id;
|
55 |
+
// Adds correct callback URL for new project
|
56 |
+
$args = array('callback_url' => add_query_arg('lingotek', 1, get_blog_details($destination)->siteurl));
|
57 |
+
$response = $client->patch($client->get_api_url() . '/project/' . $new_id, $args);
|
58 |
+
update_blog_option($destination, 'lingotek_defaults', $options);
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
if (isset($_POST['preferences'])) {
|
63 |
+
switch_to_blog($source_site);
|
64 |
+
$preferences = Lingotek_Model::get_prefs();
|
65 |
+
update_blog_option($destination, 'lingotek_prefs', $preferences);
|
66 |
+
restore_current_blog();
|
67 |
+
}
|
68 |
+
|
69 |
+
if (isset($_POST['utility_set_default_language'])) {
|
70 |
+
switch_to_blog($destination);
|
71 |
+
$GLOBALS['wp_lingotek']->utilities->run_utility('utility_set_default_language');
|
72 |
+
restore_current_blog();
|
73 |
+
}
|
74 |
+
|
75 |
+
}
|
76 |
+
|
77 |
+
if (isset($_POST['utility_set_default_language'])) {
|
78 |
+
add_settings_error('network', 'utilities', __('The language utility ran successfully.', 'wp-lingotek'), 'updated');
|
79 |
+
}
|
80 |
+
add_settings_error('network', 'destination', __('Your chosen settings have updated successfully for all selected sites.', 'wp-lingotek'), 'updated');
|
81 |
+
}
|
82 |
+
else {
|
83 |
+
add_settings_error('network', 'destination', __('Please choose at least one destination site.', 'wp-lingotek'), 'error');
|
84 |
+
}
|
85 |
+
|
86 |
+
//Refreshes community resources so that the defaults are set when you visit the sites translation settings
|
87 |
+
if (isset($_POST['new_project']) && isset($_POST['destination'])) {
|
88 |
+
$this->set_community_resources(get_option('lingotek_community'));
|
89 |
+
foreach ($destination_site as $destination) {
|
90 |
+
$source_options = get_option('lingotek_community_resources');
|
91 |
+
update_blog_option($destination, 'lingotek_community_resources', $source_options);
|
92 |
+
}
|
93 |
+
$num = count($destination_site);
|
94 |
+
if ($num > 1) {
|
95 |
+
add_settings_error('network', 'projects', __('Your new projects were successfully created.', 'wp-lingotek'), 'updated');
|
96 |
+
}
|
97 |
+
else {
|
98 |
+
add_settings_error('network', 'projects', __('Your new project was successfully created.', 'wp-lingotek'), 'updated');
|
99 |
+
}
|
100 |
+
}
|
101 |
+
}
|
102 |
+
settings_errors('network');
|
103 |
+
?>
|
104 |
+
|
105 |
+
<style>
|
106 |
+
input[type=checkbox] {
|
107 |
+
margin: 0px 7px;
|
108 |
+
}
|
109 |
+
</style>
|
110 |
+
|
111 |
+
<div class="wrap">
|
112 |
+
<h2><?php _e('Lingotek Network Settings', 'wp-lingotek'); ?></h2>
|
113 |
+
<p><?php _e('Copy Lingotek settings from the source site to multiple sites', 'wp-lingotek'); ?></p>
|
114 |
+
|
115 |
+
<form id="network-settings" method="post" action="admin.php?page=wp-lingotek_network" class="validate" onsubmit="return confirm('Are you sure you want to submit this request? It will overwrite any current settings you have for the destination sites.');">
|
116 |
+
|
117 |
+
<table class="form-table">
|
118 |
+
<tr>
|
119 |
+
<th><?php echo _e('Source Site', 'wp-lingotek'); ?></th>
|
120 |
+
<td>
|
121 |
+
<select name="source" id="source"><?php foreach ($site_data as $site) {
|
122 |
+
echo "\n\t<option value='" . esc_attr($site['blog_id']) . "'>" . $site['blogname'] . '</option>';
|
123 |
+
} ?>
|
124 |
+
</select>
|
125 |
+
</td>
|
126 |
+
</tr>
|
127 |
+
<tr>
|
128 |
+
<th><?php echo _e('Destination Site', 'wp-lingotek'); ?></th>
|
129 |
+
<td>
|
130 |
+
<select multiple="multiple" name="destination[]" id="destination"><?php foreach ($site_data as $site) {
|
131 |
+
echo "\n\t<option value='" . esc_attr($site['blog_id']) . "'>" . $site['blogname'] . '</option>';
|
132 |
+
} ?>
|
133 |
+
</select>
|
134 |
+
</td>
|
135 |
+
</tr>
|
136 |
+
<tr>
|
137 |
+
<th><?php echo _e('Settings to copy', 'wp-lingotek'); ?></th>
|
138 |
+
<td>
|
139 |
+
<input checked type="checkbox" id="account" name="settings[]" value="token"><label for="account"><?php echo _e('Account', 'wp-lingotek'); ?></label>
|
140 |
+
<input checked type="checkbox" id="community" name="settings[]" value="community"><label for="community"><?php echo _e('Community', 'wp-lingotek'); ?></label>
|
141 |
+
<input checked type="checkbox" id="defaults" name="settings[]" value="defaults"><label for="defaults"><?php echo _e('Defaults', 'wp-lingotek'); ?></label>
|
142 |
+
<input checked type="checkbox" id="resources" name="settings[]" value="community_resources"><label for="resources"><?php echo _e('Resources', 'wp-lingotek'); ?></label>
|
143 |
+
<input checked type="checkbox" id="profiles" name="settings[]" value="profiles"><label for="profiles"><?php echo _e('Profiles', 'wp-lingotek'); ?></label>
|
144 |
+
<input checked type="checkbox" id="content_types" name="settings[]" value="content_type"><label for="content_types"><?php echo _e('Content Types', 'wp-lingotek'); ?></label>
|
145 |
+
<input checked type="checkbox" id="preferences" name="preferences" value="preferences"><label for="preferences"><?php echo _e('Preferences', 'wp-lingotek'); ?></label>
|
146 |
+
</td>
|
147 |
+
</tr>
|
148 |
+
<tr>
|
149 |
+
<th><?php echo _e('New Project', 'wp-lingotek'); ?></th>
|
150 |
+
<td>
|
151 |
+
<input checked type="checkbox" name="new_project" id="new_project" ><label for="new_project"><?php echo _e('Create a new project using the name of the selected site (Recommended for a newly created site)', 'wp-lingotek'); ?></label>
|
152 |
+
</td>
|
153 |
+
</tr>
|
154 |
+
<tr>
|
155 |
+
<th><?php echo _e('Language', 'wp-lingotek'); ?></th>
|
156 |
+
<td>
|
157 |
+
<input checked type="checkbox" name="utility_set_default_language" id="utility_set_default_language" ><label for="utility_set_default_language"><?php echo _e('Set <i>default language</i> as the language for all existing content that has not been assigned a language.', 'wp-lingotek'); ?></label>
|
158 |
+
</td>
|
159 |
+
</tr>
|
160 |
+
</table>
|
161 |
+
|
162 |
+
<p>
|
163 |
+
<?php submit_button(__('Update Options', 'wp-lingotek'), 'primary', 'submit', false); ?>
|
164 |
+
</p>
|
165 |
+
|
166 |
+
</form>
|
167 |
+
</div>
|
admin/view-tutorial.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$menu_items = array(
|
4 |
+
'features' => __("Features", 'wp-lingotek'),
|
5 |
+
'content' => __('Tutorial', 'wp-lingotek'),
|
6 |
+
'faq' => __('FAQ', 'wp-lingotek'),
|
7 |
+
'credits' => __('Credits', 'wp-lingotek'),
|
8 |
+
);
|
9 |
+
|
10 |
+
?>
|
11 |
+
|
12 |
+
|
13 |
+
<div class="wrap about-wrap">
|
14 |
+
|
15 |
+
<h1><?php printf( __( 'Welcome to Lingotek' , 'wp-lingotek') ); ?></h1>
|
16 |
+
|
17 |
+
<div class="about-text"><?php printf( __( 'Thank you for updating! Lingotek offers convenient cloud-based localization and translation.' , 'wp-lingotek'), LINGOTEK_VERSION ); ?></div>
|
18 |
+
|
19 |
+
|
20 |
+
<div class="wp-badge" style="background: url(<?php echo LINGOTEK_URL ?>/img/lingotek-chevrons-blue.png) center 24px/85px 80px no-repeat #fff; color: #666;"><?php printf( __( 'Version %s' , 'wp-lingotek'), LINGOTEK_VERSION ); ?></div>
|
21 |
+
|
22 |
+
<h2 class="nav-tab-wrapper">
|
23 |
+
<?php
|
24 |
+
$menu_item_index = 0;
|
25 |
+
foreach ($menu_items as $menu_item_key => $menu_item_label) {
|
26 |
+
$use_as_default = ($menu_item_index === 0 && !isset($_GET['sm'])) ? TRUE : FALSE;
|
27 |
+
?>
|
28 |
+
|
29 |
+
<a class="nav-tab <?php if ($use_as_default || (isset($_GET['sm']) && $_GET['sm'] == $menu_item_key)): ?> nav-tab-active<?php endif; ?>"
|
30 |
+
href="admin.php?page=<?php echo $_GET['page']; ?>&sm=<?php echo $menu_item_key; ?>"><?php echo $menu_item_label; ?></a>
|
31 |
+
<?php
|
32 |
+
$menu_item_index++;
|
33 |
+
}
|
34 |
+
?>
|
35 |
+
</h2>
|
36 |
+
|
37 |
+
|
38 |
+
<?php
|
39 |
+
settings_errors();
|
40 |
+
$submenu = isset($_GET['sm']) ? $_GET['sm'] : current(array_keys($menu_items));
|
41 |
+
$dir = dirname(__FILE__) . '/tutorial/';
|
42 |
+
$filename = $dir . $submenu . ".php";
|
43 |
+
if (file_exists($filename))
|
44 |
+
include $filename;
|
45 |
+
else
|
46 |
+
echo "TO-DO: create <i>" . 'tutorial/' . $submenu . ".php</i>";
|
47 |
+
?>
|
48 |
+
|
49 |
+
</div>
|
css/admin.css
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* progress dialog */
|
2 |
+
#lingotek-progressbar {
|
3 |
+
margin: 20px;
|
4 |
+
height: 2em;
|
5 |
+
background-color: #dddddd;
|
6 |
+
}
|
7 |
+
|
8 |
+
#lingotek-progressbar .ui-progressbar-value {
|
9 |
+
margin: -1px;
|
10 |
+
height: 100%;
|
11 |
+
background-color: #0074a2;
|
12 |
+
}
|
13 |
+
|
14 |
+
#lingotek-progressdialog .ui-dialog-titlebar-close {
|
15 |
+
display: none;
|
16 |
+
}
|
17 |
+
|
18 |
+
/* icons color */
|
19 |
+
.lingotek-color {
|
20 |
+
color: #ff7b12; /* lingotek color */
|
21 |
+
}
|
22 |
+
a.lingotek-color {
|
23 |
+
color: #ff7b12; /* lingotek color */
|
24 |
+
}
|
25 |
+
|
26 |
+
a.lingotek-color:hover {
|
27 |
+
color: #ffab42; /* lighter orange */
|
28 |
+
}
|
29 |
+
|
30 |
+
a.dashicons {
|
31 |
+
cursor: pointer;
|
32 |
+
}
|
33 |
+
|
34 |
+
/* content type configuration */
|
35 |
+
.lingotek-content .column-name, .lingotek-content .column-profile {
|
36 |
+
width: 25%;
|
37 |
+
}
|
38 |
+
|
39 |
+
.sources-name {
|
40 |
+
margin: 0 0 0 20px;
|
41 |
+
}
|
42 |
+
|
43 |
+
.sources-profile {
|
44 |
+
margin: 0;
|
45 |
+
}
|
46 |
+
|
47 |
+
.content-type-name, .content-type-profile {
|
48 |
+
margin-bottom: 6px;
|
49 |
+
}
|
50 |
+
|
51 |
+
.content-type-name, .sources-name li, .lingotek-content .dashicons {
|
52 |
+
line-height: 28px;
|
53 |
+
height: 28px;
|
54 |
+
padding: 2px;
|
55 |
+
vertical-align: middle;
|
56 |
+
}
|
57 |
+
|
58 |
+
.content-type-fields li {
|
59 |
+
display: inline-block;
|
60 |
+
width: 150px;
|
61 |
+
}
|
62 |
+
|
63 |
+
.pref-statuses li {
|
64 |
+
display: inline-block;
|
65 |
+
padding-right: 15px;
|
66 |
+
}
|
67 |
+
|
68 |
+
.lingotek-bordered {
|
69 |
+
border: 1px solid #e5e5e5;
|
70 |
+
}
|
71 |
+
|
72 |
+
|
73 |
+
/* utilities */
|
74 |
+
|
75 |
+
#utility_delete_documents {
|
76 |
+
margin-left: 20px;
|
77 |
+
}
|
img/lingotek-chevrons-blue.png
ADDED
Binary file
|
img/lingotek-icon.png
ADDED
Binary file
|
img/lingotek-white.png
ADDED
Binary file
|
include/api.php
ADDED
@@ -0,0 +1,292 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require_once('http.php');
|
4 |
+
|
5 |
+
/*
|
6 |
+
* manages communication with Lingotek TMS
|
7 |
+
* uses Lingotek API V5
|
8 |
+
*
|
9 |
+
* @since 0.1
|
10 |
+
*/
|
11 |
+
class Lingotek_API extends Lingotek_HTTP {
|
12 |
+
protected $base_url;
|
13 |
+
protected $api_url;
|
14 |
+
protected $client_id;
|
15 |
+
|
16 |
+
const PRODUCTION_URL = "https://myaccount.lingotek.com";
|
17 |
+
const SANDBOX_URL = "https://cms.lingotek.com";
|
18 |
+
const CLIENT_ID = "780966c9-f9c8-4691-96e2-c0aaf47f62ff";// Lingotek App ID
|
19 |
+
|
20 |
+
/*
|
21 |
+
* constructor
|
22 |
+
*
|
23 |
+
* @since 0.1
|
24 |
+
*/
|
25 |
+
public function __construct() {
|
26 |
+
$base_url = get_option('lingotek_base_url');
|
27 |
+
$this->base_url = $base_url ? $base_url : self::PRODUCTION_URL;
|
28 |
+
$this->api_url = $this->base_url.'/api';
|
29 |
+
$this->client_id = self::CLIENT_ID;
|
30 |
+
$token_details = get_option('lingotek_token');
|
31 |
+
$this->headers['Authorization'] = 'bearer ' . $token_details['access_token'];
|
32 |
+
$this->defaults = get_option('lingotek_defaults');
|
33 |
+
}
|
34 |
+
|
35 |
+
public function get_token_details($access_token) {
|
36 |
+
$url = $this->base_url . "/auth/oauth2/access_token_info?access_token=" . $access_token;
|
37 |
+
Lingotek::log("GET " . $url . " (" . __METHOD__ . ")");
|
38 |
+
$response = wp_remote_get($url);
|
39 |
+
$response_code = wp_remote_retrieve_response_code($response);
|
40 |
+
|
41 |
+
if ($response_code == 200) {
|
42 |
+
$response_body = json_decode(wp_remote_retrieve_body($response));
|
43 |
+
$token_details = $response_body;
|
44 |
+
}
|
45 |
+
else {
|
46 |
+
$token_details = FALSE;
|
47 |
+
}
|
48 |
+
return $token_details;
|
49 |
+
}
|
50 |
+
|
51 |
+
public function get_api_url() {
|
52 |
+
return $this->api_url;
|
53 |
+
}
|
54 |
+
|
55 |
+
/*
|
56 |
+
* updates the projet callback
|
57 |
+
*
|
58 |
+
* @since 0.2
|
59 |
+
*
|
60 |
+
* @param string $project_id
|
61 |
+
*/
|
62 |
+
public function update_callback_url($project_id) {
|
63 |
+
$args = array('callback_url' => add_query_arg('lingotek', 1, site_url()));
|
64 |
+
$response = $this->patch($this->api_url . '/project/' . $project_id, $args);
|
65 |
+
return !is_wp_error($response) && 204 == wp_remote_retrieve_response_code($response);
|
66 |
+
}
|
67 |
+
|
68 |
+
/*
|
69 |
+
* creates a new project
|
70 |
+
*
|
71 |
+
* @since 0.2
|
72 |
+
*
|
73 |
+
* @param string $title
|
74 |
+
*/
|
75 |
+
public function create_project($title, $community_id) {
|
76 |
+
$args = array(
|
77 |
+
'title' => $title,
|
78 |
+
'community_id' => $community_id,
|
79 |
+
'workflow_id' => $this->defaults['workflow_id'],
|
80 |
+
'callback_url' => add_query_arg('lingotek', 1, site_url()),
|
81 |
+
);
|
82 |
+
|
83 |
+
$response = $this->post($this->api_url . '/project', $args);
|
84 |
+
if(!is_wp_error($response) && 201 == wp_remote_retrieve_response_code($response)) {
|
85 |
+
$new_id = json_decode(wp_remote_retrieve_body($response));
|
86 |
+
return $new_id->properties->id;
|
87 |
+
}
|
88 |
+
else {
|
89 |
+
return false;
|
90 |
+
}
|
91 |
+
}
|
92 |
+
|
93 |
+
/*
|
94 |
+
* uploads a document
|
95 |
+
*
|
96 |
+
* @since 0.1
|
97 |
+
*
|
98 |
+
* @param array $args expects array with title, content and locale_code
|
99 |
+
* @returns bool|string document_id, false if something got wrong
|
100 |
+
*/
|
101 |
+
public function upload_document($args) {
|
102 |
+
$args = wp_parse_args($args, array('format' => 'JSON', 'project_id' => $this->defaults['project_id'], 'workflow_id' => $this->defaults['workflow_id']));
|
103 |
+
|
104 |
+
$this->format_as_multipart($args);
|
105 |
+
$response = $this->post($this->api_url . '/document', $args);
|
106 |
+
|
107 |
+
if (!is_wp_error($response) && 202 == wp_remote_retrieve_response_code($response)) {
|
108 |
+
$b = json_decode(wp_remote_retrieve_body($response));
|
109 |
+
return $b->properties->id;
|
110 |
+
}
|
111 |
+
return false;
|
112 |
+
}
|
113 |
+
|
114 |
+
/*
|
115 |
+
* modifies a document
|
116 |
+
*
|
117 |
+
* @since 0.1
|
118 |
+
*
|
119 |
+
* @param string $id document id
|
120 |
+
* @param array $args expects array with content
|
121 |
+
* @return bool false if something got wrong
|
122 |
+
*/
|
123 |
+
public function patch_document($id, $args) {
|
124 |
+
$args = wp_parse_args($args, array('format' => 'JSON'));
|
125 |
+
$this->format_as_multipart($args);
|
126 |
+
$response = $this->patch($this->api_url . '/document/' . $id, $args);
|
127 |
+
return !is_wp_error($response) && 202 == wp_remote_retrieve_response_code($response);
|
128 |
+
}
|
129 |
+
|
130 |
+
/*
|
131 |
+
* deletes a document
|
132 |
+
*
|
133 |
+
* @since 0.1
|
134 |
+
*
|
135 |
+
* @param string $id document id
|
136 |
+
*/
|
137 |
+
public function delete_document($id) {
|
138 |
+
$response = $this->delete($this->api_url . '/document/' . $id);
|
139 |
+
return !is_wp_error($response) && 204 == wp_remote_retrieve_response_code($response);
|
140 |
+
}
|
141 |
+
|
142 |
+
/*
|
143 |
+
* get documents ids
|
144 |
+
*
|
145 |
+
* @since 0.1
|
146 |
+
*/
|
147 |
+
public function get_documents($args = array()) {
|
148 |
+
$response = $this->get(add_query_arg($args, $this->api_url . '/document'));
|
149 |
+
$ids = array();
|
150 |
+
|
151 |
+
if (!is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response)) {
|
152 |
+
$documents = json_decode(wp_remote_retrieve_body($response));
|
153 |
+
foreach ($documents->entities as $doc) {
|
154 |
+
$ids[] = $doc->properties->id;
|
155 |
+
}
|
156 |
+
}
|
157 |
+
|
158 |
+
return $ids;
|
159 |
+
}
|
160 |
+
|
161 |
+
/*
|
162 |
+
* check if a document is existing
|
163 |
+
*
|
164 |
+
* @since 0.1
|
165 |
+
*
|
166 |
+
* @param string $id document id
|
167 |
+
* @return bool
|
168 |
+
*/
|
169 |
+
public function document_exists($id) {
|
170 |
+
$response = $this->get($this->api_url . '/document/' . $id);
|
171 |
+
return !is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response);
|
172 |
+
}
|
173 |
+
|
174 |
+
/*
|
175 |
+
* check translations status of a document
|
176 |
+
*
|
177 |
+
* @since 0.1
|
178 |
+
*
|
179 |
+
* @param string $id document id
|
180 |
+
* @return array with locale as key and status as value
|
181 |
+
*/
|
182 |
+
public function get_translations_status($id) {
|
183 |
+
$response = $this->get($this->api_url . '/document/' . $id . '/translation');
|
184 |
+
if (!is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response)) {
|
185 |
+
$b = json_decode(wp_remote_retrieve_body($response));
|
186 |
+
foreach ($b->entities as $e) {
|
187 |
+
$translations[$e->properties->locale_code] = $e->properties->percent_complete;
|
188 |
+
}
|
189 |
+
}
|
190 |
+
|
191 |
+
return empty($translations) ? array() : $translations;
|
192 |
+
}
|
193 |
+
|
194 |
+
/*
|
195 |
+
* requests a new translation of a document
|
196 |
+
*
|
197 |
+
* @since 0.1
|
198 |
+
*
|
199 |
+
* @param string $id document id
|
200 |
+
* @param string $locale Lingotek locale
|
201 |
+
* @param array $args optional arguments (only workflow_id at the moment)
|
202 |
+
* @return bool true if the request succeeded
|
203 |
+
*/
|
204 |
+
public function request_translation($id, $locale, $args = array()) {
|
205 |
+
$args = wp_parse_args($args, array('workflow_id' => $this->defaults['workflow_id']));
|
206 |
+
$args = array_merge(array('locale_code' => $locale), $args);
|
207 |
+
$response = $this->post($this->api_url . '/document/' . $id . '/translation', $args);
|
208 |
+
return !is_wp_error($response) && 201 == wp_remote_retrieve_response_code($response);
|
209 |
+
}
|
210 |
+
|
211 |
+
/*
|
212 |
+
* get a translation
|
213 |
+
*
|
214 |
+
* @since 0.1
|
215 |
+
*
|
216 |
+
* @param string $id document id
|
217 |
+
* @param string $locale Lingotek locale
|
218 |
+
* @return string|bool the translation, false if there is none
|
219 |
+
*/
|
220 |
+
public function get_translation($id, $locale) {
|
221 |
+
$response = $this->get(add_query_arg(array('locale_code' => $locale, 'auto_format' => 'true') , $this->api_url . '/document/' . $id . '/content'));
|
222 |
+
return !is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response) ? wp_remote_retrieve_body($response) : false;
|
223 |
+
}
|
224 |
+
|
225 |
+
/*
|
226 |
+
* deletes a translation
|
227 |
+
*
|
228 |
+
* @since 0.1
|
229 |
+
*
|
230 |
+
* @param string $id document id
|
231 |
+
* @param string $locale Lingotek locale
|
232 |
+
*/
|
233 |
+
public function delete_translation($id, $locale) {
|
234 |
+
$response = $this->delete($this->api_url . '/document/' . $id . '/translation/' . $locale);
|
235 |
+
// FIXME send a response
|
236 |
+
}
|
237 |
+
|
238 |
+
/*
|
239 |
+
* get connect account url
|
240 |
+
*
|
241 |
+
* @param string $redirect_uri the location where to redirect to after account has been connected
|
242 |
+
* @return string the complete url for the connect account link
|
243 |
+
*/
|
244 |
+
public function get_connect_url($redirect_uri, $env = NULL) {
|
245 |
+
$base_url = $this->base_url;
|
246 |
+
$client_id = $this->client_id;
|
247 |
+
if(!is_null($env)){
|
248 |
+
$base_url = (strcasecmp($env,'SANDBOX') == 0) ? self::SANDBOX_URL : self::PRODUCTION_URL;
|
249 |
+
}
|
250 |
+
return $base_url . "/auth/authorize.html?client_id=" . $client_id . "&redirect_uri=" . urlencode($redirect_uri) . "&response_type=token";
|
251 |
+
}
|
252 |
+
|
253 |
+
public function get_new_url($redirect_uri) {
|
254 |
+
$base_url = self::PRODUCTION_URL;
|
255 |
+
$client_id = $this->client_id;
|
256 |
+
return $base_url . "/lingopoint/portal/requestAccount.action?client_id=" . $client_id . "&app=" . urlencode($redirect_uri) . "&response_type=token";
|
257 |
+
|
258 |
+
}
|
259 |
+
|
260 |
+
public function get_communities() {
|
261 |
+
$response = $this->get(add_query_arg(array('limit' => 100), $this->api_url . '/community'));
|
262 |
+
return !is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response) ? json_decode(wp_remote_retrieve_body($response)) : false;
|
263 |
+
}
|
264 |
+
|
265 |
+
public function get_projects($community_id) {
|
266 |
+
$response = $this->get(add_query_arg(array('community_id' => $community_id, 'limit' => 100), $this->api_url . '/project'));
|
267 |
+
if (wp_remote_retrieve_response_code($response) == 204) {
|
268 |
+
return 'empty';
|
269 |
+
}
|
270 |
+
return !is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response) ? json_decode(wp_remote_retrieve_body($response)) : false;
|
271 |
+
}
|
272 |
+
|
273 |
+
public function get_vaults($community_id) {
|
274 |
+
$response = $this->get(add_query_arg(array('community_id' => $community_id, 'limit' => 100), $this->api_url . '/vault'));
|
275 |
+
return !is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response) ? json_decode(wp_remote_retrieve_body($response)) : false;
|
276 |
+
}
|
277 |
+
|
278 |
+
public function get_workflows($community_id) {
|
279 |
+
$response = $this->get(add_query_arg(array('community_id' => $community_id, 'limit' => 100), $this->api_url . '/workflow'));
|
280 |
+
return !is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response) ? json_decode(wp_remote_retrieve_body($response)) : false;
|
281 |
+
}
|
282 |
+
|
283 |
+
public function get_filters() {
|
284 |
+
$response = $this->get(add_query_arg(array('limit' => 100), $this->api_url . '/filter'));
|
285 |
+
return !is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response) ? json_decode(wp_remote_retrieve_body($response)) : false;
|
286 |
+
}
|
287 |
+
|
288 |
+
public function upload_filter($name, $type, $content) {
|
289 |
+
$args = array('name' => $name, 'type' => $type, 'content' => $content);
|
290 |
+
$response = $this->post($this->api_url . '/filter', $args);
|
291 |
+
}
|
292 |
+
}
|
include/callback.php
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* a class to handle Lingotek callbacks
|
5 |
+
*
|
6 |
+
* @since 0.1
|
7 |
+
*/
|
8 |
+
class Lingotek_Callback {
|
9 |
+
public $lgtm;
|
10 |
+
|
11 |
+
/*
|
12 |
+
* Constructor
|
13 |
+
*
|
14 |
+
* @since 0.1
|
15 |
+
*/
|
16 |
+
public function __construct(&$model) {
|
17 |
+
$this->lgtm = &$model;
|
18 |
+
|
19 |
+
add_filter('request', array(&$this, 'request'));
|
20 |
+
}
|
21 |
+
|
22 |
+
/*
|
23 |
+
* dispatches the Lingotek callback and dies
|
24 |
+
*
|
25 |
+
* @since 0.1
|
26 |
+
*
|
27 |
+
* @param array $query_vars query vars known to WordPres
|
28 |
+
* @return array unmodified query vars if the request is not a Lingotek callback
|
29 |
+
*/
|
30 |
+
public function request($query_vars) {
|
31 |
+
if (empty($query_vars['lingotek']))
|
32 |
+
return $query_vars;
|
33 |
+
|
34 |
+
if (isset($_GET['type'], $_GET['document_id']) && $document = $this->lgtm->get_group_by_id($_GET['document_id'])) {
|
35 |
+
|
36 |
+
// url for in context review
|
37 |
+
if (isset($_GET['locale']) && 'get' == $_GET['type']) {
|
38 |
+
$locale = Lingotek::map_to_wp_locale($_GET['locale']); // map to WP locale
|
39 |
+
|
40 |
+
// posts
|
41 |
+
if (post_type_exists($document->type)) {
|
42 |
+
if ($id = $document->pllm->get_post($document->source, $locale)) {
|
43 |
+
wp_redirect(get_permalink($id), 301);
|
44 |
+
exit();
|
45 |
+
}
|
46 |
+
else {
|
47 |
+
wp_redirect(get_permalink($document->source), 302);
|
48 |
+
exit();
|
49 |
+
}
|
50 |
+
}
|
51 |
+
|
52 |
+
// taxonomy terms
|
53 |
+
elseif (taxonomy_exists($document->type) && $id = $document->pllm->get_term($document->source, $locale)) {
|
54 |
+
wp_redirect(get_term_link($id, $document->type), 301);
|
55 |
+
exit();
|
56 |
+
}
|
57 |
+
|
58 |
+
status_header(404); // no document found
|
59 |
+
die();
|
60 |
+
}
|
61 |
+
|
62 |
+
if ('document_uploaded' == $_GET['type']) {
|
63 |
+
$document->source_ready();
|
64 |
+
|
65 |
+
if ($document->is_automatic_upload())
|
66 |
+
$document->request_translations();
|
67 |
+
}
|
68 |
+
|
69 |
+
if (isset($_GET['locale']) && 'target' == $_GET['type']) {
|
70 |
+
// We will need access to PLL_Admin_Sync::copy_post_metas
|
71 |
+
global $polylang;
|
72 |
+
$polylang->sync = new PLL_Admin_Sync($polylang);
|
73 |
+
|
74 |
+
$locale = Lingotek::map_to_wp_locale($_GET['locale']); // map to WP locale
|
75 |
+
$document->is_automatic_download($locale) ? $document->create_translation($locale) : $document->translation_ready($locale);
|
76 |
+
}
|
77 |
+
|
78 |
+
status_header(200); // useless as it the default value
|
79 |
+
die();
|
80 |
+
}
|
81 |
+
|
82 |
+
status_header(404); // no document found
|
83 |
+
die();
|
84 |
+
}
|
85 |
+
}
|
include/dashboard.php
ADDED
@@ -0,0 +1,307 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* a class to handle Lingotek dashboard requests
|
5 |
+
*
|
6 |
+
* @since 0.1
|
7 |
+
*/
|
8 |
+
class Lingotek_Dashboard {
|
9 |
+
|
10 |
+
/*
|
11 |
+
* Constructor
|
12 |
+
*
|
13 |
+
* @since 0.1
|
14 |
+
*/
|
15 |
+
public function __construct() {
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Lingotek
|
20 |
+
*/
|
21 |
+
function ajax_language_dashboard() {
|
22 |
+
global $polylang;
|
23 |
+
|
24 |
+
$request_method = isset($_REQUEST['_method']) ? $_REQUEST['_method'] : (isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET');
|
25 |
+
|
26 |
+
$response = array(
|
27 |
+
'method' => $request_method
|
28 |
+
);
|
29 |
+
switch ($request_method) {
|
30 |
+
case 'POST':
|
31 |
+
if (isset($_REQUEST['code'], $_REQUEST['native'], $_REQUEST['direction'])) {
|
32 |
+
$name = $_REQUEST['native'];
|
33 |
+
$slug = substr($_REQUEST['code'], 0, strpos($_REQUEST['code'], '_')); // 3rd parameter of strstr needs PHP 5.3
|
34 |
+
$locale = Lingotek::map_to_wp_locale($_REQUEST['code']);
|
35 |
+
|
36 |
+
// avoid conflicts between language slugs
|
37 |
+
$existing_slugs = $polylang->model->get_languages_list(array('fields' => 'slug'));
|
38 |
+
if (!empty($existing_slugs) && in_array($slug, $existing_slugs))
|
39 |
+
$slug = strtolower(str_replace('_', '-', $locale));
|
40 |
+
|
41 |
+
$rtl = $_REQUEST['direction'] == 'RTL';
|
42 |
+
$term_group = 0;
|
43 |
+
|
44 |
+
// adds the language
|
45 |
+
$polylang->model->add_language(compact('name', 'slug', 'locale', 'rtl', 'term_group'));
|
46 |
+
|
47 |
+
// attempts to install the language pack
|
48 |
+
require_once(ABSPATH . 'wp-admin/includes/translation-install.php');
|
49 |
+
wp_download_language_pack($locale);
|
50 |
+
|
51 |
+
// force checking for themes and plugins translations updates
|
52 |
+
wp_update_themes();
|
53 |
+
wp_update_plugins();
|
54 |
+
|
55 |
+
$response = array(
|
56 |
+
'request' => 'POST: add target language to CMS and Lingotek Project Language',
|
57 |
+
'locale' => $_REQUEST['code'],
|
58 |
+
'xcode' => $locale,
|
59 |
+
'active' => 1,
|
60 |
+
'enabled' => 1,
|
61 |
+
'source' => self::get_counts_by_type($locale, 'sources'),
|
62 |
+
'target' => self::get_counts_by_type($locale, 'targets')
|
63 |
+
);
|
64 |
+
status_header(200);
|
65 |
+
}
|
66 |
+
break;
|
67 |
+
|
68 |
+
case 'DELETE':
|
69 |
+
$body = file_get_contents("php://input");
|
70 |
+
$code = str_replace('code=', '', $body);
|
71 |
+
$lang = $polylang->model->get_language(Lingotek::map_to_wp_locale($code)); // map code to WP locales to find the language
|
72 |
+
|
73 |
+
// prevents deleting the last language as it would break the Lingotek dashboard
|
74 |
+
if (1 == count($polylang->model->get_languages_list())) {
|
75 |
+
$response = array (
|
76 |
+
'request' => sprintf('DELETE: remove language from CMS and project (%s)', $code),
|
77 |
+
'code' => $code,
|
78 |
+
'success' => false,
|
79 |
+
'message' => __('You must keep at least one language.', 'wp-lingotek')
|
80 |
+
);
|
81 |
+
status_header(403);
|
82 |
+
}
|
83 |
+
|
84 |
+
elseif (!self::has_language_content($lang)) {
|
85 |
+
$default_category = pll_get_term(get_option('default_category'), $lang->slug);
|
86 |
+
$polylang->model->delete_language((int) $lang->term_id);
|
87 |
+
wp_delete_term( $default_category, 'category' ); // delete the default category after the language
|
88 |
+
|
89 |
+
$response = array (
|
90 |
+
'request' => sprintf('DELETE: remove language from CMS and project (%s)', $code),
|
91 |
+
'code' => $code,
|
92 |
+
'active' => false,
|
93 |
+
'success' => true
|
94 |
+
);
|
95 |
+
status_header(204);
|
96 |
+
}
|
97 |
+
|
98 |
+
else {
|
99 |
+
$response = array (
|
100 |
+
'request' => sprintf('DELETE: remove language from CMS and project (%s)', $code),
|
101 |
+
'code' => $code,
|
102 |
+
'success' => false,
|
103 |
+
'message' => __('The language can only be removed when no existing content is using it. If you would like to remove this language from the site, then first remove any content assigned to this language.', 'wp-lingotek')
|
104 |
+
);
|
105 |
+
status_header(403);
|
106 |
+
}
|
107 |
+
break;
|
108 |
+
|
109 |
+
case 'GET':
|
110 |
+
default:
|
111 |
+
$locale_code = isset($_REQUEST['code']) ? $_REQUEST['code'] : NULL;
|
112 |
+
$response = $response + $this->get_language_details($locale_code);
|
113 |
+
break;
|
114 |
+
}
|
115 |
+
|
116 |
+
wp_send_json($response);
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Lingotek - get the details of each language
|
121 |
+
*/
|
122 |
+
function get_language_details($locale_requested = NULL) {
|
123 |
+
global $polylang;
|
124 |
+
|
125 |
+
$response = array();
|
126 |
+
$available_languages = $polylang->model->get_languages_list();
|
127 |
+
$source_total = 0;
|
128 |
+
$target_total = 0;
|
129 |
+
$source_totals = array();
|
130 |
+
$target_totals = array();
|
131 |
+
|
132 |
+
// If we get a parameter, only return that language. Otherwise return all languages.
|
133 |
+
foreach ($available_languages as $lang_details) {
|
134 |
+
$wordpress_lang_code = $lang_details->slug;
|
135 |
+
$locale = $lang_details->locale;
|
136 |
+
if (!is_null($locale_requested) && $locale_requested != $locale) {
|
137 |
+
continue;
|
138 |
+
}
|
139 |
+
|
140 |
+
$lingotek_locale = str_replace('-', '_', $lang_details->lingotek_locale);
|
141 |
+
$source_counts = self::get_source_counts($wordpress_lang_code);
|
142 |
+
$target_counts = self::get_target_counts($wordpress_lang_code);
|
143 |
+
self::standardize_and_sort($source_counts['types'], $target_counts['types']);
|
144 |
+
$source_count = $source_counts['total']; //unset($source_counts['total']);
|
145 |
+
$target_count = $target_counts['total'];
|
146 |
+
|
147 |
+
$target_status = array(
|
148 |
+
'locale' => $lingotek_locale, // Return this language code as the Lingotek language code.
|
149 |
+
'xcode' => $wordpress_lang_code,
|
150 |
+
'active' => 1, //TO-DO: lingotek_enabled?
|
151 |
+
'enabled' => 1, //intval($lang_details->active), // wordpress enabled
|
152 |
+
'source' => $source_counts,
|
153 |
+
'target' => $target_counts
|
154 |
+
);
|
155 |
+
if ($locale_requested == $locale) {
|
156 |
+
$response = $target_status;
|
157 |
+
}
|
158 |
+
else {
|
159 |
+
$response[$lingotek_locale] = $target_status;
|
160 |
+
}
|
161 |
+
//$source_total += $source_count;
|
162 |
+
$target_total += $target_count;
|
163 |
+
//$source_totals = self::array_sum_values($source_totals, $source_counts['types']);
|
164 |
+
$target_totals = self::array_sum_values($target_totals, $target_counts['types']);
|
165 |
+
}
|
166 |
+
if (is_null($locale_requested)) {
|
167 |
+
$source_totals_package = self::get_unique_source_counts_by_type();
|
168 |
+
$source_totals = $source_totals_package['types'];
|
169 |
+
$source_total = $source_totals_package['total'];
|
170 |
+
self::standardize_and_sort($source_totals, $target_totals);
|
171 |
+
|
172 |
+
$response = array(
|
173 |
+
'languages' => $response,
|
174 |
+
'source' => array('types' => $source_totals, 'total' => $source_total),
|
175 |
+
'target' => array('types' => $target_totals, 'total' => $target_total),
|
176 |
+
'count' => count($available_languages),
|
177 |
+
);
|
178 |
+
}
|
179 |
+
return $response;
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Lingotek - standardize and sort helper function
|
184 |
+
*/
|
185 |
+
static function standardize_and_sort(&$a1, &$a2) {
|
186 |
+
$merged_totals = array_fill_keys(array_keys($a1 + $a2), 0);
|
187 |
+
$a1 = $a1 + $merged_totals;
|
188 |
+
$a2 = $a2 + $merged_totals;
|
189 |
+
ksort($a1);
|
190 |
+
ksort($a2);
|
191 |
+
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Lingotek - get_source_counts
|
195 |
+
*/
|
196 |
+
function get_source_counts($locale) {
|
197 |
+
return self::get_counts_by_type($locale, 'sources');
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Lingotek - get_target_counts
|
202 |
+
*/
|
203 |
+
function get_target_counts($locale) {
|
204 |
+
return self::get_counts_by_type($locale, 'targets');
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Lingotek - get_counts_by_type
|
209 |
+
*/
|
210 |
+
static function get_counts_by_type($locale, $condition) {
|
211 |
+
global $polylang;
|
212 |
+
|
213 |
+
$lgtm = new Lingotek_Model(); // FIXME not created by Lingotek as Polylang believes we are doing ajax on frontend
|
214 |
+
|
215 |
+
foreach ($polylang->model->get_translated_post_types() as $post_type) {
|
216 |
+
$count = $lgtm->count_posts($post_type);
|
217 |
+
$post_type_object = get_post_type_object($post_type);
|
218 |
+
$response['types'][$post_type_object->labels->name] = isset($count[$condition][$locale]) ? $count[$condition][$locale] : 0;
|
219 |
+
}
|
220 |
+
|
221 |
+
foreach ($polylang->model->get_translated_taxonomies() as $tax) {
|
222 |
+
$count = $lgtm->count_terms($tax);
|
223 |
+
$taxonomy = get_taxonomy($tax);
|
224 |
+
$response['types'][$taxonomy->labels->name] = isset($count[$condition][$locale]) ? $count[$condition][$locale] : 0;
|
225 |
+
}
|
226 |
+
|
227 |
+
$response['total'] = array_sum($response['types']);
|
228 |
+
|
229 |
+
return $response;
|
230 |
+
}
|
231 |
+
|
232 |
+
static function get_unique_source_counts_by_type(){
|
233 |
+
|
234 |
+
global $polylang;
|
235 |
+
|
236 |
+
$lgtm = new Lingotek_Model(); // FIXME not created by Lingotek as Polylang believes we are doing ajax on frontend
|
237 |
+
|
238 |
+
foreach ($polylang->model->get_translated_post_types() as $post_type) {
|
239 |
+
$count = $lgtm->count_posts($post_type);
|
240 |
+
$post_type_object = get_post_type_object($post_type);
|
241 |
+
$response['types'][$post_type_object->labels->name] = isset($count['total']) ? $count['total'] : 0; //only count translation sets
|
242 |
+
}
|
243 |
+
|
244 |
+
foreach ($polylang->model->get_translated_taxonomies() as $tax) {
|
245 |
+
$count = $lgtm->count_terms($tax);
|
246 |
+
$taxonomy = get_taxonomy($tax);
|
247 |
+
$response['types'][$taxonomy->labels->name] = isset($count['total']) ? $count['total'] : 0; //only count translation sets
|
248 |
+
}
|
249 |
+
|
250 |
+
$response['total'] = array_sum($response['types']);
|
251 |
+
|
252 |
+
return $response;
|
253 |
+
}
|
254 |
+
|
255 |
+
/**
|
256 |
+
* Sums the values of the arrays be there keys (PHP 4, PHP 5)
|
257 |
+
* array array_sum_values ( array array1 [, array array2 [, array ...]] )
|
258 |
+
*/
|
259 |
+
public static function array_sum_values() {
|
260 |
+
$return = array();
|
261 |
+
$intArgs = func_num_args();
|
262 |
+
$arrArgs = func_get_args();
|
263 |
+
if ($intArgs < 1) {
|
264 |
+
trigger_error('Warning: Wrong parameter count for arraySumValues()', E_USER_WARNING);
|
265 |
+
}
|
266 |
+
|
267 |
+
foreach ($arrArgs as $arrItem) {
|
268 |
+
if (!is_array($arrItem)) {
|
269 |
+
trigger_error('Warning: Wrong parameter values for arraySumValues()', E_USER_WARNING);
|
270 |
+
}
|
271 |
+
foreach ($arrItem as $k => $v) {
|
272 |
+
if (!key_exists($k, $return)) {
|
273 |
+
$return[$k] = 0;
|
274 |
+
}
|
275 |
+
$return[$k] += $v;
|
276 |
+
}
|
277 |
+
}
|
278 |
+
return $return;
|
279 |
+
|
280 |
+
$sumArray = array();
|
281 |
+
foreach ($myArray as $k => $subArray) {
|
282 |
+
foreach ($subArray as $id => $value) {
|
283 |
+
$sumArray[$id]+=$value;
|
284 |
+
}
|
285 |
+
}
|
286 |
+
return $sumArray;
|
287 |
+
}
|
288 |
+
|
289 |
+
/*
|
290 |
+
* checks if any content exists in the language
|
291 |
+
*
|
292 |
+
* @since 0.2
|
293 |
+
*
|
294 |
+
* @param object $language
|
295 |
+
* @return bool false if no content in the language or only the default category
|
296 |
+
*/
|
297 |
+
static public function has_language_content($language) {
|
298 |
+
// posts
|
299 |
+
$objects = get_objects_in_term($language->term_id, 'language');
|
300 |
+
if (!empty($objects))
|
301 |
+
return true;
|
302 |
+
|
303 |
+
// terms, only the default category is accepted
|
304 |
+
$objects = get_objects_in_term($language->tl_term_id, 'term_language');
|
305 |
+
return count($objects) > 1 || (isset($objects[0]) && $objects[0] != pll_get_term(get_option('default_category'), $language->slug));
|
306 |
+
}
|
307 |
+
}
|
include/group-post.php
ADDED
@@ -0,0 +1,219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* Translations groups for posts, pages and custom post types
|
5 |
+
*
|
6 |
+
* @since 0.2
|
7 |
+
*/
|
8 |
+
class Lingotek_Group_Post extends Lingotek_Group {
|
9 |
+
|
10 |
+
const SAME_AS_SOURCE = 'SAME_AS_SOURCE'; // pref constant used for downloaded translations
|
11 |
+
|
12 |
+
/*
|
13 |
+
* set a translation term for an object
|
14 |
+
*
|
15 |
+
* @since 0.2
|
16 |
+
*
|
17 |
+
* @param int $object_id post id
|
18 |
+
* @param object $language
|
19 |
+
* @param string $document_id translation term name (Lingotek document id)
|
20 |
+
*/
|
21 |
+
public static function create($object_id, $language, $document_id) {
|
22 |
+
$data = array(
|
23 |
+
'lingotek' => array(
|
24 |
+
'type' => get_post_type($object_id),
|
25 |
+
'source' => $object_id,
|
26 |
+
'status' => 'importing',
|
27 |
+
'translations' => array()
|
28 |
+
),
|
29 |
+
$language->slug => $object_id // for Polylang
|
30 |
+
);
|
31 |
+
|
32 |
+
self::_create($object_id, $document_id, $data, 'post_translations');
|
33 |
+
}
|
34 |
+
|
35 |
+
/*
|
36 |
+
* returns content type fields
|
37 |
+
*
|
38 |
+
* @since 0.2
|
39 |
+
*
|
40 |
+
* @param string $post_type
|
41 |
+
* @return array
|
42 |
+
*/
|
43 |
+
static public function get_content_type_fields($post_type) {
|
44 |
+
$arr = 'attachment' == $post_type ?
|
45 |
+
array(
|
46 |
+
'post_title' => __('Title', 'wp-lingotek'),
|
47 |
+
'post_excerpt' => __('Caption', 'wp-lingotek'),
|
48 |
+
'metas' => array('_wp_attachment_image_alt' => __('Alternative Text', 'wp-lingotek')),
|
49 |
+
'post_content' => __('Description', 'wp-lingotek'),
|
50 |
+
) :
|
51 |
+
array(
|
52 |
+
'post_title' => __('Title', 'wp-lingotek'),
|
53 |
+
'post_name' => __('Slug', 'wp-lingotek'),
|
54 |
+
'post_content' => __('Content', 'wp-lingotek'),
|
55 |
+
'post_excerpt' => __('Excerpt', 'wp-lingotek')
|
56 |
+
);
|
57 |
+
|
58 |
+
// add the custom fields from wpml-config.xml <custom-fields> sections
|
59 |
+
$wpml_config = PLL_WPML_Config::instance();
|
60 |
+
|
61 |
+
if (isset($wpml_config->tags['custom-fields'])) {
|
62 |
+
foreach ($wpml_config->tags['custom-fields'] as $context) {
|
63 |
+
foreach ($context['custom-field'] as $cf) {
|
64 |
+
if ('translate' == $cf['attributes']['action'])
|
65 |
+
$arr['metas'][$cf['value']] = $cf['value'];
|
66 |
+
}
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
// allow plugins to modify the fields to translate
|
71 |
+
return apply_filters('lingotek_post_content_type_fields', $arr, $post_type);
|
72 |
+
}
|
73 |
+
|
74 |
+
/*
|
75 |
+
* returns the content to translate
|
76 |
+
*
|
77 |
+
* @since 0.2
|
78 |
+
*
|
79 |
+
* @param object $post
|
80 |
+
* @return string json encoded content to translate
|
81 |
+
*/
|
82 |
+
public static function get_content($post) {
|
83 |
+
$fields = self::get_content_type_fields($post->post_type);
|
84 |
+
$content_types = get_option('lingotek_content_type');
|
85 |
+
|
86 |
+
foreach (array_keys($fields) as $key) {
|
87 |
+
if ('metas' == $key) {
|
88 |
+
foreach (array_keys($fields['metas']) as $meta) {
|
89 |
+
if (empty($content_types[$post->post_type]['fields']['metas'][$meta]) && $value = get_post_meta($post->ID, $meta, true))
|
90 |
+
$arr['metas'][$meta] = $value;
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
// send slug for translation only if it has been modified
|
95 |
+
elseif('post_name' == $key && empty($content_types[$post->post_type]['fields'][$key])) {
|
96 |
+
$default_slug = sanitize_title($post->post_title); // default slug created by WP
|
97 |
+
if ($default_slug != $post->post_name)
|
98 |
+
$arr['post'][$key] = $post->$key;
|
99 |
+
}
|
100 |
+
|
101 |
+
elseif (empty($content_types[$post->post_type]['fields'][$key])) {
|
102 |
+
$arr['post'][$key] = $post->$key;
|
103 |
+
}
|
104 |
+
}
|
105 |
+
|
106 |
+
return json_encode($arr);
|
107 |
+
}
|
108 |
+
|
109 |
+
public static function is_valid_auto_upload_post_status($post_status) {
|
110 |
+
$prefs = Lingotek_Model::get_prefs();
|
111 |
+
$valid_statuses = $prefs['auto_upload_post_statuses'];
|
112 |
+
$valid = array_key_exists($post_status, $valid_statuses) && $valid_statuses[$post_status];
|
113 |
+
return $valid;
|
114 |
+
}
|
115 |
+
|
116 |
+
/*
|
117 |
+
* requests translations to Lingotek TMS
|
118 |
+
*
|
119 |
+
* @since 0.1
|
120 |
+
*/
|
121 |
+
public function request_translations() {
|
122 |
+
if (isset($this->source)) {
|
123 |
+
$language = $this->pllm->get_post_language((int) $this->source);
|
124 |
+
$this->_request_translations($language);
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
/*
|
129 |
+
* create a translation downloaded from Lingotek TMS
|
130 |
+
*
|
131 |
+
* @since 0.1
|
132 |
+
* @uses Lingotek_Group::safe_translation_status_update() as the status can be automatically set by the TMS callback
|
133 |
+
*
|
134 |
+
* @param string $locale
|
135 |
+
*/
|
136 |
+
public function create_translation($locale) {
|
137 |
+
$client = new Lingotek_API();
|
138 |
+
|
139 |
+
if (false === ($translation = $client->get_translation($this->document_id, $locale)))
|
140 |
+
return;
|
141 |
+
|
142 |
+
self::$creating_translation = true;
|
143 |
+
$prefs = Lingotek_Model::get_prefs(); // need an array by default
|
144 |
+
|
145 |
+
$translation = json_decode($translation, true); // wp_insert_post expects array
|
146 |
+
$tr_post = $translation['post'];
|
147 |
+
|
148 |
+
$post = get_post($this->source); // source post
|
149 |
+
$tr_post['post_status'] = ($prefs['download_post_status'] === self::SAME_AS_SOURCE)? $post->post_status : $prefs['download_post_status']; // status
|
150 |
+
|
151 |
+
// update existing translation
|
152 |
+
if ($tr_id = $this->pllm->get_post($this->source, $locale)) {
|
153 |
+
$tr_post['ID'] = $tr_id;
|
154 |
+
wp_update_post($tr_post);
|
155 |
+
|
156 |
+
$this->safe_translation_status_update($locale, 'current');
|
157 |
+
}
|
158 |
+
|
159 |
+
// create new translation
|
160 |
+
else {
|
161 |
+
unset($post->post_name); // forces the creation of a new default slug if not translated by Lingotek
|
162 |
+
$tr_post = array_merge((array) $post , $tr_post); // copy all untranslated fields from the original post
|
163 |
+
$tr_post['ID'] = null; // will force the creation of a new post
|
164 |
+
|
165 |
+
// translate parent
|
166 |
+
$tr_post['post_parent'] = ($post->post_parent && $tr_parent = $this->pllm->get_translation('post', $post->post_parent, $locale)) ? $tr_parent : 0;
|
167 |
+
|
168 |
+
if ('attachment' == $post->post_type) {
|
169 |
+
$tr_id = wp_insert_attachment($tr_post);
|
170 |
+
add_post_meta($tr_id, '_wp_attachment_metadata', get_post_meta($this->source, '_wp_attachment_metadata', true));
|
171 |
+
add_post_meta($tr_id, '_wp_attached_file', get_post_meta($this->source, '_wp_attached_file', true));
|
172 |
+
}
|
173 |
+
else {
|
174 |
+
$tr_id = wp_insert_post($tr_post);
|
175 |
+
}
|
176 |
+
|
177 |
+
if ($tr_id) {
|
178 |
+
$tr_lang = $this->pllm->get_language($locale);
|
179 |
+
$this->pllm->set_post_language($tr_id, $tr_lang);
|
180 |
+
|
181 |
+
$this->safe_translation_status_update($locale, 'current', array($tr_lang->slug => $tr_id));
|
182 |
+
wp_set_object_terms($tr_id, $this->term_id, 'post_translations');
|
183 |
+
|
184 |
+
// assign terms and metas
|
185 |
+
$GLOBALS['polylang']->sync->copy_post_metas($this->source, $tr_id, $tr_lang->slug);
|
186 |
+
|
187 |
+
// translate metas
|
188 |
+
if (!empty($translation['metas'])) {
|
189 |
+
foreach ($translation['metas'] as $key => $meta)
|
190 |
+
update_post_meta($tr_id, $key, $meta);
|
191 |
+
}
|
192 |
+
}
|
193 |
+
}
|
194 |
+
|
195 |
+
self::$creating_translation = false;
|
196 |
+
}
|
197 |
+
|
198 |
+
/*
|
199 |
+
* checks if content should be automatically uploaded
|
200 |
+
*
|
201 |
+
* @since 0.2
|
202 |
+
*
|
203 |
+
* @return bool
|
204 |
+
*/
|
205 |
+
public function is_automatic_upload() {
|
206 |
+
return 'automatic' == Lingotek_Model::get_profile_option('upload', get_post_type($this->source), $this->get_source_language());
|
207 |
+
}
|
208 |
+
|
209 |
+
/*
|
210 |
+
* get the the language of the source post
|
211 |
+
*
|
212 |
+
* @since 0.2
|
213 |
+
*
|
214 |
+
* @return object
|
215 |
+
*/
|
216 |
+
public function get_source_language() {
|
217 |
+
return $this->pllm->get_post_language($this->source);
|
218 |
+
}
|
219 |
+
}
|
include/group-string.php
ADDED
@@ -0,0 +1,188 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* Translations groups for strings
|
5 |
+
*
|
6 |
+
* @since 0.2
|
7 |
+
*/
|
8 |
+
class Lingotek_Group_String extends Lingotek_Group {
|
9 |
+
|
10 |
+
/*
|
11 |
+
* assigns this object properties from the underlying term
|
12 |
+
*
|
13 |
+
* @since 0.2
|
14 |
+
*
|
15 |
+
* @param object $term term translation object
|
16 |
+
*/
|
17 |
+
protected function load($term) {
|
18 |
+
parent::load($term);
|
19 |
+
$this->name = $term->name;
|
20 |
+
$this->md5 = &$this->desc_array['lingotek']['md5'];
|
21 |
+
}
|
22 |
+
|
23 |
+
/*
|
24 |
+
* updates the translation term in DB
|
25 |
+
*
|
26 |
+
* @since 0.2
|
27 |
+
*/
|
28 |
+
public function save() {
|
29 |
+
wp_update_term((int) $this->term_id, $this->taxonomy, array('slug' => $this->document_id, 'name' => $this->name, 'description' => serialize($this->desc_array)));
|
30 |
+
}
|
31 |
+
|
32 |
+
/*
|
33 |
+
* set a translation term for a strings group
|
34 |
+
*
|
35 |
+
* @since 0.2
|
36 |
+
*
|
37 |
+
* @param string string group name
|
38 |
+
* @param object $language
|
39 |
+
* @param string $document_id translation term name (Lingotek document id)
|
40 |
+
*/
|
41 |
+
public static function create($name, $language, $document_id) {
|
42 |
+
$desc = array(
|
43 |
+
'lingotek' => array(
|
44 |
+
'type' => 'string',
|
45 |
+
'md5' => md5(self::get_content($name)),
|
46 |
+
'source' => $language->mo_id,
|
47 |
+
'status' => 'importing',
|
48 |
+
'translations' => array()
|
49 |
+
),
|
50 |
+
);
|
51 |
+
|
52 |
+
$terms = wp_get_object_terms($language->mo_id, 'post_translations');
|
53 |
+
|
54 |
+
// the translation already exists but was previously disassociated
|
55 |
+
if ($key = array_search($name, wp_list_pluck($terms, 'name'))) {
|
56 |
+
wp_update_term((int) $terms[$key]->term_id, 'post_translations', array('slug' => $document_id, 'name' => $name, 'description' => serialize($desc)));
|
57 |
+
}
|
58 |
+
|
59 |
+
else {
|
60 |
+
wp_insert_term($name, 'post_translations', array('slug' => $document_id, 'description' => serialize($desc)));
|
61 |
+
}
|
62 |
+
|
63 |
+
wp_set_object_terms($language->mo_id, $document_id, 'post_translations', true); // add terms
|
64 |
+
|
65 |
+
}
|
66 |
+
|
67 |
+
/*
|
68 |
+
* disassociates translations from the Lingotek TMS
|
69 |
+
*
|
70 |
+
* @since 0.2
|
71 |
+
*
|
72 |
+
* @param bool $delete whether to delete the Lingotek document or not
|
73 |
+
*/
|
74 |
+
public function disassociate($delete = true) {
|
75 |
+
$client = new Lingotek_API();
|
76 |
+
|
77 |
+
if (!$delete || $client->delete_document($this->document_id)) {
|
78 |
+
wp_delete_term($this->term_id, 'post_translations');
|
79 |
+
}
|
80 |
+
}
|
81 |
+
|
82 |
+
/*
|
83 |
+
* uploads a modified source
|
84 |
+
*
|
85 |
+
* @since 0.2
|
86 |
+
*
|
87 |
+
* @param string $group group name
|
88 |
+
* @param string $empty used for compatibility with parent class
|
89 |
+
*/
|
90 |
+
public function patch($group, $empty = '', $external_url = '', $filters = array()) {
|
91 |
+
$client = new Lingotek_API();
|
92 |
+
$content = $this->get_content($group);
|
93 |
+
|
94 |
+
$params = array(
|
95 |
+
'title' => $title,
|
96 |
+
'content' => $this->get_content($content),
|
97 |
+
'external_url' => $external_url,
|
98 |
+
);
|
99 |
+
$params = array_merge($params, $filters);
|
100 |
+
|
101 |
+
$res = $client->patch_document($this->document_id, $params);
|
102 |
+
|
103 |
+
if ($res) {
|
104 |
+
$this->md5 = md5($content);
|
105 |
+
$this->status = 'importing';
|
106 |
+
$this->translations = array_fill_keys(array_keys($this->translations), 'pending');
|
107 |
+
$this->save();
|
108 |
+
}
|
109 |
+
}
|
110 |
+
|
111 |
+
/*
|
112 |
+
* returns the content to translate
|
113 |
+
*
|
114 |
+
* @since 0.2
|
115 |
+
*
|
116 |
+
* @param object $group string group name
|
117 |
+
* @return string json encoded content to translate
|
118 |
+
*/
|
119 |
+
public static function get_content($group) {
|
120 |
+
foreach (PLL_Admin_Strings::get_strings() as $string) {
|
121 |
+
if ($string['context'] == $group)
|
122 |
+
$arr[$string['string']] = $string['string'];
|
123 |
+
}
|
124 |
+
return json_encode($arr);
|
125 |
+
}
|
126 |
+
|
127 |
+
/*
|
128 |
+
* requests translations to Lingotek TMS
|
129 |
+
*
|
130 |
+
* @since 0.2
|
131 |
+
*/
|
132 |
+
public function request_translations() {
|
133 |
+
if (isset($this->source))
|
134 |
+
$this->_request_translations($this->get_source_language());
|
135 |
+
}
|
136 |
+
|
137 |
+
/*
|
138 |
+
* create a translation downloaded from Lingotek TMS
|
139 |
+
*
|
140 |
+
* @since 0.2
|
141 |
+
* @uses Lingotek_Group::safe_translation_status_update() as the status can be automatically set by the TMS callback
|
142 |
+
*
|
143 |
+
* @param string $locale
|
144 |
+
*/
|
145 |
+
public function create_translation($locale) {
|
146 |
+
$client = new Lingotek_API();
|
147 |
+
|
148 |
+
if (false === ($translation = $client->get_translation($this->document_id, $locale)))
|
149 |
+
return;
|
150 |
+
|
151 |
+
$strings = wp_list_pluck(PLL_Admin_Strings::get_strings(), 'name', 'string'); // get the strings name for the filter
|
152 |
+
$translations = json_decode($translation, true); // wp_insert_post expects array
|
153 |
+
$language = $this->pllm->get_language($locale);
|
154 |
+
|
155 |
+
$mo = new PLL_MO();
|
156 |
+
$mo->import_from_db($language);
|
157 |
+
|
158 |
+
foreach ($translations as $key => $translation) {
|
159 |
+
$translation = apply_filters('pll_sanitize_string_translation', $translation, $strings[$key], $this->name);
|
160 |
+
$mo->add_entry($mo->make_entry($key, $translation));
|
161 |
+
}
|
162 |
+
|
163 |
+
$mo->export_to_db($language);
|
164 |
+
$this->safe_translation_status_update($locale, 'current');
|
165 |
+
}
|
166 |
+
|
167 |
+
/*
|
168 |
+
* checks if content should be automatically uploaded
|
169 |
+
*
|
170 |
+
* @since 0.2
|
171 |
+
*
|
172 |
+
* @return bool
|
173 |
+
*/
|
174 |
+
public function is_automatic_upload() {
|
175 |
+
return 'automatic' == Lingotek_Model::get_profile_option('upload', 'string', $this->get_source_language());
|
176 |
+
}
|
177 |
+
|
178 |
+
/*
|
179 |
+
* get the the language of the source string (always the default language)
|
180 |
+
*
|
181 |
+
* @since 0.2
|
182 |
+
*
|
183 |
+
* @return object
|
184 |
+
*/
|
185 |
+
public function get_source_language() {
|
186 |
+
return $this->pllm->get_language($this->pllm->options['default_lang']);
|
187 |
+
}
|
188 |
+
}
|
include/group-term.php
ADDED
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* Translations groups for categories, tags and custom taxonomies
|
5 |
+
*
|
6 |
+
* @since 0.2
|
7 |
+
*/
|
8 |
+
class Lingotek_Group_Term extends Lingotek_Group {
|
9 |
+
|
10 |
+
/*
|
11 |
+
* set a translation term for an object
|
12 |
+
*
|
13 |
+
* @since 0.2
|
14 |
+
*
|
15 |
+
* @param int $object_id term id
|
16 |
+
* @param string $tax taxonomy name
|
17 |
+
* @param object $language
|
18 |
+
* @param string $document_id translation term name (Lingotek document id)
|
19 |
+
*/
|
20 |
+
public static function create($object_id, $tax, $language, $document_id) {
|
21 |
+
$data = array(
|
22 |
+
'lingotek' => array(
|
23 |
+
'type' => $tax,
|
24 |
+
'source' => $object_id,
|
25 |
+
'status' => 'importing',
|
26 |
+
'translations' => array()
|
27 |
+
),
|
28 |
+
$language->slug => $object_id // for Polylang
|
29 |
+
);
|
30 |
+
|
31 |
+
self::_create($object_id, $document_id, $data, 'term_translations');
|
32 |
+
}
|
33 |
+
|
34 |
+
/*
|
35 |
+
* returns content type fields
|
36 |
+
*
|
37 |
+
* @since 0.2
|
38 |
+
*
|
39 |
+
* @param string $taxonomy
|
40 |
+
* @return array
|
41 |
+
*/
|
42 |
+
static public function get_content_type_fields($taxonomy) {
|
43 |
+
$arr = array(
|
44 |
+
'name' => __('Name', 'wp-lingotek'),
|
45 |
+
'args' => array(
|
46 |
+
'slug' => __('Slug', 'wp-lingotek'),
|
47 |
+
'description' => __('Description', 'wp-lingotek')
|
48 |
+
)
|
49 |
+
);
|
50 |
+
|
51 |
+
return apply_filters('lingotek_term_content_type_fields', $arr, $taxonomy);
|
52 |
+
}
|
53 |
+
|
54 |
+
/*
|
55 |
+
* returns the content to translate
|
56 |
+
*
|
57 |
+
* @since 0.2
|
58 |
+
*
|
59 |
+
* @param object $term
|
60 |
+
* @return string json encoded content to translate
|
61 |
+
*/
|
62 |
+
public static function get_content($term) {
|
63 |
+
$fields = self::get_content_type_fields($term->taxonomy);
|
64 |
+
$content_types = get_option('lingotek_content_type');
|
65 |
+
|
66 |
+
foreach (array_keys($fields) as $key) {
|
67 |
+
if ('args' == $key) {
|
68 |
+
foreach (array_keys($fields['args']) as $arg) {
|
69 |
+
if (empty($content_types[$term->taxonomy]['fields']['args'][$arg]))
|
70 |
+
$arr['args'][$arg] = $term->$arg;
|
71 |
+
}
|
72 |
+
}
|
73 |
+
|
74 |
+
elseif (empty($content_types[$term->taxonomy]['fields'][$key])) {
|
75 |
+
$arr[$key] = $term->$key;
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
return json_encode($arr);
|
80 |
+
}
|
81 |
+
|
82 |
+
/*
|
83 |
+
* requests translations to Lingotek TMS
|
84 |
+
*
|
85 |
+
* @since 0.2
|
86 |
+
*/
|
87 |
+
public function request_translations() {
|
88 |
+
if (isset($this->source)) {
|
89 |
+
$language = $this->pllm->get_term_language((int) $this->source);
|
90 |
+
$this->_request_translations($language);
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
/*
|
95 |
+
* create a translation downloaded from Lingotek TMS
|
96 |
+
*
|
97 |
+
* @since 0.2
|
98 |
+
* @uses Lingotek_Group::safe_translation_status_update() as the status can be automatically set by the TMS callback
|
99 |
+
*
|
100 |
+
* @param string $locale
|
101 |
+
*/
|
102 |
+
public function create_translation($locale) {
|
103 |
+
$client = new Lingotek_API();
|
104 |
+
|
105 |
+
if (false === ($translation = $client->get_translation($this->document_id, $locale)))
|
106 |
+
return;
|
107 |
+
|
108 |
+
self::$creating_translation = true;
|
109 |
+
|
110 |
+
$translation = json_decode($translation, true); // wp_insert_post expects array
|
111 |
+
$args = $translation['args'];
|
112 |
+
|
113 |
+
// update existing translation
|
114 |
+
if ($tr_id = $this->pllm->get_term($this->source, $locale)) {
|
115 |
+
$args['name'] = $translation['name'];
|
116 |
+
wp_update_term($tr_id, $this->type, $args);
|
117 |
+
|
118 |
+
$this->safe_translation_status_update($locale, 'current');
|
119 |
+
}
|
120 |
+
|
121 |
+
// create new translation
|
122 |
+
else {
|
123 |
+
$tr_lang = $this->pllm->get_language($locale);
|
124 |
+
|
125 |
+
// translate parent
|
126 |
+
$term = get_term($this->source, $this->type);
|
127 |
+
$args['parent'] = ($term->parent && $tr_parent = $this->model->get_translation('term', $term->parent, $locale)) ? $tr_parent : 0;
|
128 |
+
|
129 |
+
// attempt to get a unique slug in case it already exists in another language
|
130 |
+
if (isset($args['slug']) && term_exists($args['slug'])) {
|
131 |
+
$args['slug'] .= '-' . $tr_lang->slug;
|
132 |
+
}
|
133 |
+
|
134 |
+
$tr = wp_insert_term($translation['name'], $this->type, $args);
|
135 |
+
|
136 |
+
if (!is_wp_error($tr)) {
|
137 |
+
$this->pllm->set_term_language($tr['term_id'], $tr_lang);
|
138 |
+
$this->safe_translation_status_update($locale, 'current', array($tr_lang->slug => $tr['term_id']));
|
139 |
+
wp_set_object_terms($tr['term_id'], $this->term_id, 'term_translations');
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
self::$creating_translation = false;
|
144 |
+
}
|
145 |
+
|
146 |
+
/*
|
147 |
+
* checks if content should be automatically uploaded
|
148 |
+
*
|
149 |
+
* @since 0.2
|
150 |
+
*
|
151 |
+
* @return bool
|
152 |
+
*/
|
153 |
+
public function is_automatic_upload() {
|
154 |
+
return 'automatic' == Lingotek_Model::get_profile_option('upload', $this->type, $this->get_source_language());
|
155 |
+
}
|
156 |
+
|
157 |
+
/*
|
158 |
+
* get the the language of the source term
|
159 |
+
*
|
160 |
+
* @since 0.2
|
161 |
+
*
|
162 |
+
* @return object
|
163 |
+
*/
|
164 |
+
public function get_source_language() {
|
165 |
+
return $this->pllm->get_term_language($this->source);
|
166 |
+
}
|
167 |
+
}
|
include/group.php
ADDED
@@ -0,0 +1,294 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* Abstract class for Translations groups objects
|
5 |
+
*
|
6 |
+
* @since 0.2
|
7 |
+
*/
|
8 |
+
abstract class Lingotek_Group {
|
9 |
+
static public $creating_translation; // used to avoid uploading a translation when using automatinc upload
|
10 |
+
|
11 |
+
/*
|
12 |
+
* constructor
|
13 |
+
*
|
14 |
+
* @since 0.2
|
15 |
+
*/
|
16 |
+
public function __construct($term, &$pllm) {
|
17 |
+
$this->pllm = &$pllm;
|
18 |
+
$this->load($term);
|
19 |
+
}
|
20 |
+
|
21 |
+
/*
|
22 |
+
* assigns this object properties from the underlying term
|
23 |
+
*
|
24 |
+
* @since 0.2
|
25 |
+
*
|
26 |
+
* @param object $term term translation object
|
27 |
+
*/
|
28 |
+
protected function load($term) {
|
29 |
+
$this->term_id = (int) $term->term_id;
|
30 |
+
$this->tt_id = (int) $term->term_taxonomy_id;
|
31 |
+
$this->document_id = $term->slug;
|
32 |
+
$this->taxonomy = $term->taxonomy;
|
33 |
+
$this->desc_array = unserialize($term->description);
|
34 |
+
|
35 |
+
foreach (array('type', 'source', 'status', 'translations') as $prop)
|
36 |
+
$this->$prop = &$this->desc_array['lingotek'][$prop];
|
37 |
+
}
|
38 |
+
|
39 |
+
/*
|
40 |
+
* updates the translation term in DB
|
41 |
+
*
|
42 |
+
* @since 0.2
|
43 |
+
*/
|
44 |
+
public function save() {
|
45 |
+
wp_update_term((int) $this->term_id, $this->taxonomy, array('slug' => $this->document_id, 'name' => $this->document_id, 'description' => serialize($this->desc_array)));
|
46 |
+
}
|
47 |
+
|
48 |
+
/*
|
49 |
+
* provides a safe way to update the translations statuses when receiving "simultaneous" TMS callbacks
|
50 |
+
*
|
51 |
+
* @since 0.2
|
52 |
+
*
|
53 |
+
* @param string $locale
|
54 |
+
* @param string $status
|
55 |
+
* @param array $arr translations to add
|
56 |
+
*/
|
57 |
+
protected function safe_translation_status_update($locale, $status, $arr = array()) {
|
58 |
+
global $wpdb;
|
59 |
+
$wpdb->query("LOCK TABLES $wpdb->term_taxonomy WRITE");
|
60 |
+
$d = $wpdb->get_var($wpdb->prepare("SELECT description FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %d", $this->tt_id));
|
61 |
+
$d = unserialize($d);
|
62 |
+
$this->translations[$locale] = $d['lingotek']['translations'][$locale] = $status;
|
63 |
+
$d = array_merge($d, $arr); // optionally add a new translation
|
64 |
+
$d = serialize($d);
|
65 |
+
$wpdb->query($wpdb->prepare("UPDATE $wpdb->term_taxonomy SET description = %s WHERE term_taxonomy_id = %d", $d, $this->tt_id));
|
66 |
+
$wpdb->query("UNLOCK TABLES");
|
67 |
+
}
|
68 |
+
|
69 |
+
/*
|
70 |
+
* creates a new term translation object in DB
|
71 |
+
*
|
72 |
+
* @since 0.2
|
73 |
+
*
|
74 |
+
* @param int $object_id the id of the object to translate
|
75 |
+
* @param string $document_id Lingotek document id
|
76 |
+
* @param array $desc data to store in the Lingotek array
|
77 |
+
* @param string $taxonomy either 'post_translations' or 'term_translations'
|
78 |
+
*/
|
79 |
+
protected static function _create($object_id, $document_id, $desc, $taxonomy) {
|
80 |
+
$terms = wp_get_object_terms($object_id, $taxonomy);
|
81 |
+
$term = array_pop($terms);
|
82 |
+
|
83 |
+
if (empty($term)) {
|
84 |
+
wp_insert_term($document_id, $taxonomy, array('description' => serialize($desc)));
|
85 |
+
}
|
86 |
+
|
87 |
+
// the translation already exists but was not managed by Lingotek
|
88 |
+
else {
|
89 |
+
if (is_array($old_desc = maybe_unserialize($term->description)))
|
90 |
+
$desc = array_merge($old_desc, $desc);
|
91 |
+
wp_update_term((int) $term->term_id, $taxonomy, array('slug' => $document_id, 'name' => $document_id, 'description' => serialize($desc)));
|
92 |
+
}
|
93 |
+
|
94 |
+
wp_set_object_terms($object_id, $document_id, $taxonomy);
|
95 |
+
}
|
96 |
+
|
97 |
+
/*
|
98 |
+
* disassociates translations from the Lingotek TMS
|
99 |
+
*
|
100 |
+
* @since 0.2
|
101 |
+
*
|
102 |
+
* @param bool $delete whether to delete the Lingotek document or not
|
103 |
+
*/
|
104 |
+
public function disassociate($delete = true) {
|
105 |
+
$client = new Lingotek_API();
|
106 |
+
|
107 |
+
if (!$delete || $client->delete_document($this->document_id)) {
|
108 |
+
unset($this->desc_array['lingotek']);
|
109 |
+
$this->save();
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
/*
|
114 |
+
* uploads a modified source
|
115 |
+
*
|
116 |
+
* @since 0.2
|
117 |
+
*
|
118 |
+
* @param string $title
|
119 |
+
* @param object $content can be a post object, a term object
|
120 |
+
*/
|
121 |
+
public function patch($title, $content, $external_url = '', $filters = array()) {
|
122 |
+
$client = new Lingotek_API();
|
123 |
+
|
124 |
+
$params = array(
|
125 |
+
'title' => $title,
|
126 |
+
'content' => $this->get_content($content),
|
127 |
+
'external_url' => $external_url,
|
128 |
+
);
|
129 |
+
$params = array_merge($params, $filters);
|
130 |
+
|
131 |
+
$res = $client->patch_document($this->document_id, $params);
|
132 |
+
|
133 |
+
if ($res) {
|
134 |
+
$this->status = 'importing';
|
135 |
+
$this->translations = array_fill_keys(array_keys($this->translations), 'pending');
|
136 |
+
$this->save();
|
137 |
+
}
|
138 |
+
}
|
139 |
+
|
140 |
+
/*
|
141 |
+
* checks the status of source document
|
142 |
+
*
|
143 |
+
* @since 0.2
|
144 |
+
*/
|
145 |
+
public function source_status() {
|
146 |
+
$client = new Lingotek_API();
|
147 |
+
|
148 |
+
if ('importing' == $this->status && $client->document_exists($this->document_id)) {
|
149 |
+
$this->status = 'current';
|
150 |
+
$this->save();
|
151 |
+
}
|
152 |
+
}
|
153 |
+
|
154 |
+
/*
|
155 |
+
* sets source status to ready
|
156 |
+
*
|
157 |
+
* @since 0.2
|
158 |
+
*/
|
159 |
+
public function source_ready() {
|
160 |
+
$this->status = 'current';
|
161 |
+
$this->save();
|
162 |
+
}
|
163 |
+
|
164 |
+
/*
|
165 |
+
* requests a translation to Lingotek TMS
|
166 |
+
*
|
167 |
+
* @since 0.2
|
168 |
+
*
|
169 |
+
* @param string $locale
|
170 |
+
*/
|
171 |
+
public function request_translation($locale) {
|
172 |
+
$client = new Lingotek_API();
|
173 |
+
$language = $this->pllm->get_language($locale);
|
174 |
+
$workflow = Lingotek_Model::get_profile_option('workflow_id', $this->type, $this->get_source_language(), $language);
|
175 |
+
$args = $workflow ? array('workflow_id' => $workflow) : array();
|
176 |
+
|
177 |
+
if (!$this->is_disabled_target($language) && empty($this->translations[$language->locale]) && $client->request_translation($this->document_id, $language->locale, $args)) {
|
178 |
+
$this->status = 'current';
|
179 |
+
$this->translations[$language->locale] = 'pending';
|
180 |
+
$this->save();
|
181 |
+
}
|
182 |
+
}
|
183 |
+
|
184 |
+
/*
|
185 |
+
* requests translations to Lingotek TMS
|
186 |
+
*
|
187 |
+
* @since 0.2
|
188 |
+
*
|
189 |
+
* @param object $source_language language of the source
|
190 |
+
*/
|
191 |
+
protected function _request_translations($source_language) {
|
192 |
+
$client = new Lingotek_API();
|
193 |
+
|
194 |
+
foreach ($this->pllm->get_languages_list() as $lang) {
|
195 |
+
if ($source_language->slug != $lang->slug && !$this->is_disabled_target($lang) && empty($this->translations[$lang->locale])) {
|
196 |
+
$workflow = Lingotek_Model::get_profile_option('workflow_id', $this->type, $source_language, $lang);
|
197 |
+
$args = $workflow ? array('workflow_id' => $workflow) : array();
|
198 |
+
$client->request_translation($this->document_id, $lang->lingotek_locale, $args);
|
199 |
+
$this->status = 'current';
|
200 |
+
$this->translations[$lang->locale] = 'pending';
|
201 |
+
}
|
202 |
+
}
|
203 |
+
|
204 |
+
$this->save();
|
205 |
+
}
|
206 |
+
|
207 |
+
/*
|
208 |
+
* checks the translations status of a document
|
209 |
+
*
|
210 |
+
* @since 0.1
|
211 |
+
*/
|
212 |
+
public function translations_status() {
|
213 |
+
$client = new Lingotek_API();
|
214 |
+
$translations = $client->get_translations_status($this->document_id); // key are Lingotek locales
|
215 |
+
foreach($this->translations as $locale => $status) {
|
216 |
+
$lingotek_locale = $this->pllm->get_language($locale)->lingotek_locale;
|
217 |
+
if ('current' != $status && isset($translations[$lingotek_locale]) && 100 == $translations[$lingotek_locale])
|
218 |
+
$this->translations[$locale] = 'ready';
|
219 |
+
}
|
220 |
+
|
221 |
+
$this->save();
|
222 |
+
}
|
223 |
+
|
224 |
+
/*
|
225 |
+
* sets translation status to ready
|
226 |
+
*
|
227 |
+
* @since 0.1
|
228 |
+
* @uses Lingotek_Group::safe_translation_status_update() as the status can be automatically set by the TMS callback
|
229 |
+
*/
|
230 |
+
public function translation_ready($locale) {
|
231 |
+
$this->safe_translation_status_update($locale, 'ready');
|
232 |
+
}
|
233 |
+
|
234 |
+
/*
|
235 |
+
* attempts to create all translations from an object
|
236 |
+
*
|
237 |
+
* @since 0.2
|
238 |
+
*/
|
239 |
+
public function create_translations() {
|
240 |
+
if (isset($this->translations)) {
|
241 |
+
foreach ($this->translations as $locale => $status)
|
242 |
+
if ('pending' == $status || 'ready' == $status)
|
243 |
+
$this->create_translation($locale);
|
244 |
+
}
|
245 |
+
}
|
246 |
+
|
247 |
+
/*
|
248 |
+
* sets document status to edited
|
249 |
+
*
|
250 |
+
* @since 0.1
|
251 |
+
*/
|
252 |
+
public function source_edited() {
|
253 |
+
$this->status = 'edited';
|
254 |
+
$this->translations = array_fill_keys(array_keys($this->translations), 'not-current');
|
255 |
+
$this->save();
|
256 |
+
}
|
257 |
+
|
258 |
+
/*
|
259 |
+
* returns true if at least one of the translations has the requested status
|
260 |
+
*
|
261 |
+
* @since 0.2
|
262 |
+
*
|
263 |
+
* @param string $status
|
264 |
+
* @return bool
|
265 |
+
*/
|
266 |
+
public function has_translation_status($status) {
|
267 |
+
return array_intersect(array_keys($this->translations, $status), $this->pllm->get_languages_list(array('fields' => 'locale')));
|
268 |
+
}
|
269 |
+
|
270 |
+
/*
|
271 |
+
* checks if target should be automatically downloaded
|
272 |
+
*
|
273 |
+
* @since 0.2
|
274 |
+
*
|
275 |
+
* @param string $locale
|
276 |
+
* @return bool
|
277 |
+
*/
|
278 |
+
public function is_automatic_download($locale) {
|
279 |
+
return 'automatic' == Lingotek_Model::get_profile_option('download', $this->type, $this->get_source_language(), $this->pllm->get_language($locale));
|
280 |
+
}
|
281 |
+
|
282 |
+
/*
|
283 |
+
* checks if translation is disabled for a target language
|
284 |
+
*
|
285 |
+
* @since 0.2
|
286 |
+
*
|
287 |
+
* @param string $type post type or taxonomy
|
288 |
+
* @param object $language
|
289 |
+
*/
|
290 |
+
public function is_disabled_target($language) {
|
291 |
+
$profile = Lingotek_Model::get_profile($this->type, $language);
|
292 |
+
return isset($profile['targets'][$language->slug]) && 'disabled' == $profile['targets'][$language->slug];
|
293 |
+
}
|
294 |
+
}
|
include/http.php
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* a simple wrapper to wp http functions
|
5 |
+
*
|
6 |
+
* @since 0.1
|
7 |
+
*/
|
8 |
+
class Lingotek_HTTP {
|
9 |
+
protected $headers = array();
|
10 |
+
|
11 |
+
/*
|
12 |
+
* formats a request as multipart
|
13 |
+
* greatly inspired from mailgun wordpress plugin
|
14 |
+
*
|
15 |
+
* @since 0.1
|
16 |
+
*/
|
17 |
+
public function format_as_multipart(&$body) {
|
18 |
+
$boundary = '----------------------------32052ee8fd2c'; // arbitrary boundary
|
19 |
+
|
20 |
+
$this->headers['Content-Type'] = 'multipart/form-data; boundary=' . $boundary;
|
21 |
+
|
22 |
+
$data = '';
|
23 |
+
|
24 |
+
foreach ($body as $key => $value) {
|
25 |
+
if (is_array($value)) {
|
26 |
+
// FIXME is this block useful for Lingotek ?
|
27 |
+
foreach($value as $k => $v) {
|
28 |
+
$data .= '--' . $boundary . "\r\n";
|
29 |
+
$data .= 'Content-Disposition: form-data; name="' . $key . '[' . $k . ']"' . "\r\n\r\n";
|
30 |
+
$data .= $v . "\r\n";
|
31 |
+
}
|
32 |
+
}
|
33 |
+
else {
|
34 |
+
$data .= '--' . $boundary ."\r\n";
|
35 |
+
$data .= 'Content-Disposition: form-data; name="' . $key . '"' . "\r\n\r\n";
|
36 |
+
$data .= $value . "\r\n";
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
$body = $data . '--' . $boundary . '--';
|
41 |
+
}
|
42 |
+
|
43 |
+
/*
|
44 |
+
* send a POST request
|
45 |
+
*
|
46 |
+
* @since 0.1
|
47 |
+
*/
|
48 |
+
public function post($url, $args = array()) {
|
49 |
+
Lingotek::log("POST " . $url);
|
50 |
+
if (!empty($args)) {
|
51 |
+
Lingotek::log($args);
|
52 |
+
}
|
53 |
+
return wp_remote_post($url, array('headers' => $this->headers, 'body' => $args));
|
54 |
+
}
|
55 |
+
|
56 |
+
/*
|
57 |
+
* send a GET request
|
58 |
+
*
|
59 |
+
* @since 0.1
|
60 |
+
*/
|
61 |
+
public function get($url, $args = array()) {
|
62 |
+
Lingotek::log("GET " . $url);
|
63 |
+
if (!empty($args)) {
|
64 |
+
Lingotek::log($args);
|
65 |
+
}
|
66 |
+
return wp_remote_get($url, array('headers' => $this->headers, 'body' => $args, 'timeout' => 8));
|
67 |
+
}
|
68 |
+
|
69 |
+
/*
|
70 |
+
* send a DELETE request
|
71 |
+
*
|
72 |
+
* @since 0.1
|
73 |
+
*/
|
74 |
+
public function delete($url, $args = array()) {
|
75 |
+
Lingotek::log("DELETE " . $url);
|
76 |
+
if (!empty($args)) {
|
77 |
+
Lingotek::log($args);
|
78 |
+
}
|
79 |
+
return wp_remote_request($url, array('method' => 'DELETE', 'headers' => $this->headers, 'body' => $args));
|
80 |
+
}
|
81 |
+
|
82 |
+
/*
|
83 |
+
* send a PATCH request
|
84 |
+
*
|
85 |
+
* @since 0.1
|
86 |
+
*/
|
87 |
+
public function patch($url, $args = array()) {
|
88 |
+
Lingotek::log("PATCH " . $url);
|
89 |
+
if (!empty($args)) {
|
90 |
+
Lingotek::log($args);
|
91 |
+
}
|
92 |
+
return wp_remote_request($url, array('method' => 'PATCH', 'headers' => $this->headers, 'body' => $args));
|
93 |
+
}
|
94 |
+
}
|
include/model.php
ADDED
@@ -0,0 +1,563 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* Manages interactions with database
|
5 |
+
* Factory for Lingotek_Group objects
|
6 |
+
*
|
7 |
+
* @since 0.1
|
8 |
+
*/
|
9 |
+
class Lingotek_Model {
|
10 |
+
public $pllm; // Polylang model
|
11 |
+
|
12 |
+
/*
|
13 |
+
* constructor
|
14 |
+
*
|
15 |
+
* @since 0.1
|
16 |
+
*/
|
17 |
+
public function __construct() {
|
18 |
+
$this->pllm = $GLOBALS['polylang']->model;
|
19 |
+
}
|
20 |
+
|
21 |
+
/*
|
22 |
+
* get the strings groups as well as their count
|
23 |
+
*
|
24 |
+
* @since 0.2
|
25 |
+
*
|
26 |
+
* @return array
|
27 |
+
*/
|
28 |
+
public static function get_strings() {
|
29 |
+
static $strings = array();
|
30 |
+
if (empty($strings)) {
|
31 |
+
PLL_Admin_Strings::init(); // enables sanitization filter
|
32 |
+
|
33 |
+
foreach (PLL_Admin_Strings::get_strings() as $string) {
|
34 |
+
$strings[$string['context']]['context'] = $string['context'];
|
35 |
+
$strings[$string['context']]['count'] = empty($strings[$string['context']]['count']) ? 1 : $strings[$string['context']]['count'] + 1;
|
36 |
+
}
|
37 |
+
$strings = array_values($strings);
|
38 |
+
}
|
39 |
+
return $strings;
|
40 |
+
}
|
41 |
+
|
42 |
+
/*
|
43 |
+
* create a translation group object from a translation term
|
44 |
+
*
|
45 |
+
* @since 0.2
|
46 |
+
*
|
47 |
+
* @param object $term
|
48 |
+
* @return object
|
49 |
+
*/
|
50 |
+
protected function convert_term($term) {
|
51 |
+
switch($term->taxonomy) {
|
52 |
+
case 'term_translations':
|
53 |
+
return new Lingotek_Group_Term($term, $this->pllm);
|
54 |
+
|
55 |
+
case 'post_translations':
|
56 |
+
$class = $term->name == $term->slug ? 'Lingotek_Group_Post' : 'Lingotek_Group_String';
|
57 |
+
return new $class($term, $this->pllm);
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
/*
|
62 |
+
* get the translation term of an object
|
63 |
+
*
|
64 |
+
* @since 0.2
|
65 |
+
*
|
66 |
+
* @param string $type either 'post' or 'term' or 'string'
|
67 |
+
* @param int|string $id post id or term id or strings translations group name
|
68 |
+
* @return object translation term
|
69 |
+
*/
|
70 |
+
public function get_group($type, $id) {
|
71 |
+
switch ($type) {
|
72 |
+
case 'post':
|
73 |
+
case 'term':
|
74 |
+
return ($term = $this->pllm->get_object_term((int) $id, $type . '_translations')) && !empty($term) ? $this->convert_term($term) : false;
|
75 |
+
case 'string':
|
76 |
+
if (is_numeric($id)) {
|
77 |
+
$strings = self::get_strings();
|
78 |
+
$id = $strings[$id]['context'];
|
79 |
+
}
|
80 |
+
return ($term = get_term_by('name', $id, 'post_translations')) && !empty($term) ? $this->convert_term($term) : false;
|
81 |
+
default:
|
82 |
+
return false;
|
83 |
+
}
|
84 |
+
}
|
85 |
+
|
86 |
+
/*
|
87 |
+
* get the translation term of an object by its Lingotek document id
|
88 |
+
*
|
89 |
+
* @since 0.2
|
90 |
+
*
|
91 |
+
* @param string|object $document_id
|
92 |
+
* @return object translation term
|
93 |
+
*/
|
94 |
+
public function get_group_by_id($document_id) {
|
95 |
+
// we already passed a translation group object
|
96 |
+
if (is_object($document_id))
|
97 |
+
return $document_id;
|
98 |
+
|
99 |
+
$terms = get_terms(array('post_translations', 'term_translations'), array('slug' => $document_id));
|
100 |
+
return is_wp_error($terms) || empty($terms) ? false : $this->convert_term(reset($terms));
|
101 |
+
}
|
102 |
+
|
103 |
+
/*
|
104 |
+
* get a translation profile
|
105 |
+
*
|
106 |
+
* @since 0.2
|
107 |
+
*
|
108 |
+
* @param string $type post type or taxonomy
|
109 |
+
* @param object $language
|
110 |
+
* @return array
|
111 |
+
*/
|
112 |
+
static public function get_profile($type, $language) {
|
113 |
+
$content_types = get_option('lingotek_content_type');
|
114 |
+
$profiles = get_option('lingotek_profiles');
|
115 |
+
|
116 |
+
// default profile is manual except for post
|
117 |
+
$default = 'post' == $type ? 'automatic' : 'manual';
|
118 |
+
|
119 |
+
$profile = isset($content_types[$type]['sources'][$language->slug]) ?
|
120 |
+
$content_types[$type]['sources'][$language->slug] :
|
121 |
+
(isset($content_types[$type]['profile']) ? $content_types[$type]['profile'] : $default);
|
122 |
+
|
123 |
+
return $profiles[$profile];
|
124 |
+
}
|
125 |
+
|
126 |
+
static public function get_prefs() {
|
127 |
+
$default = array(
|
128 |
+
'download_post_status' => Lingotek_Group_Post::SAME_AS_SOURCE,
|
129 |
+
'auto_upload_post_statuses' => array(
|
130 |
+
'draft' => 0, // ignore auto-upload
|
131 |
+
'pending' => 1, // auto-upload
|
132 |
+
'publish' => 1,
|
133 |
+
'future' => 1,
|
134 |
+
'private' => 0,
|
135 |
+
)
|
136 |
+
);
|
137 |
+
$prefs = get_option('lingotek_prefs', $default);
|
138 |
+
return $prefs;
|
139 |
+
}
|
140 |
+
|
141 |
+
/*
|
142 |
+
* get a profile option
|
143 |
+
*
|
144 |
+
* @since 0.2
|
145 |
+
*
|
146 |
+
* @param string $item 'project_id' | 'workflow_id' | 'upload' | 'download'
|
147 |
+
* @param string $type post type or taxonomy
|
148 |
+
* @param object $source_language
|
149 |
+
* @param object $target_language optional, needed to get custom target informations 'workflow_id' | 'download'
|
150 |
+
* @return string | bool either the option or false if the translation is disabled
|
151 |
+
*/
|
152 |
+
static public function get_profile_option($item, $type, $source_language, $target_language = false) {
|
153 |
+
$profile = self::get_profile($type, $source_language);
|
154 |
+
if ('disabled' == $profile['profile'])
|
155 |
+
return false;
|
156 |
+
|
157 |
+
if (!empty($target_language) && isset($profile['targets'][$target_language->slug]) && !empty($profile['custom'][$item][$target_language->slug]))
|
158 |
+
return $profile['custom'][$item][$target_language->slug];
|
159 |
+
|
160 |
+
if (!empty($profile[$item]))
|
161 |
+
return $profile[$item];
|
162 |
+
|
163 |
+
$defaults = get_option('lingotek_defaults');
|
164 |
+
return $defaults[$item];
|
165 |
+
}
|
166 |
+
|
167 |
+
/*
|
168 |
+
* uploads a new post to Lingotek TMS
|
169 |
+
*
|
170 |
+
* @since 0.1
|
171 |
+
*
|
172 |
+
* @param int $post_id
|
173 |
+
*/
|
174 |
+
public function upload_post($post_id) {
|
175 |
+
$post = get_post($post_id);
|
176 |
+
$language = $this->pllm->get_post_language($post_id);
|
177 |
+
if (empty($post) || empty($language))
|
178 |
+
return;
|
179 |
+
|
180 |
+
$profile = self::get_profile($post->post_type, $language);
|
181 |
+
if ('disabled' == $profile['profile'])
|
182 |
+
return;
|
183 |
+
|
184 |
+
$client = new Lingotek_API();
|
185 |
+
$external_url = add_query_arg(array('lingotek' => 1, 'document_id' => '{document_id}', 'locale' => '{locale}', 'type' => 'get'), site_url());
|
186 |
+
|
187 |
+
$params = array(
|
188 |
+
'title' => $post->post_title,
|
189 |
+
'content' => Lingotek_Group_Post::get_content($post),
|
190 |
+
'locale_code' => $language->lingotek_locale,
|
191 |
+
'project_id' => self::get_profile_option('project_id', $post->post_type, $language),
|
192 |
+
'workflow_id' => self::get_profile_option('workflow_id', $post->post_type, $language),
|
193 |
+
'external_url' => $external_url,
|
194 |
+
);
|
195 |
+
|
196 |
+
$filter_ids = array();
|
197 |
+
if (self::get_profile_option('primary_filter_id', $post->post_type, $language)) {
|
198 |
+
$filter_ids['fprm_id'] = self::get_profile_option('primary_filter_id',$post->post_type, $language);
|
199 |
+
}
|
200 |
+
if (self::get_profile_option('secondary_filter_id', $post->post_type, $language)) {
|
201 |
+
$filter_ids['fprm_subfilter_id'] = self::get_profile_option('secondary_filter_id',$post->post_type, $language);
|
202 |
+
}
|
203 |
+
$params = array_merge($params, $filter_ids);
|
204 |
+
|
205 |
+
if (($document = $this->get_group('post', $post_id)) && 'edited' == $document->status) {
|
206 |
+
$document->patch($post->post_title, $post, $external_url, $filter_ids);
|
207 |
+
}
|
208 |
+
|
209 |
+
elseif (!Lingotek_Group::$creating_translation) {
|
210 |
+
$document_id = $client->upload_document($params);
|
211 |
+
|
212 |
+
if ($document_id) {
|
213 |
+
Lingotek_Group_Post::create($post->ID , $language, $document_id);
|
214 |
+
}
|
215 |
+
}
|
216 |
+
}
|
217 |
+
|
218 |
+
/*
|
219 |
+
* uploads a new term to Lingotek TMS
|
220 |
+
*
|
221 |
+
* @since 0.2
|
222 |
+
*
|
223 |
+
* @param int $term_id
|
224 |
+
* @param string $taxonomy
|
225 |
+
*/
|
226 |
+
public function upload_term($term_id, $taxonomy) {
|
227 |
+
$term = get_term($term_id, $taxonomy);
|
228 |
+
$language = $this->pllm->get_term_language($term_id);
|
229 |
+
if (empty($term) || empty($language))
|
230 |
+
return;
|
231 |
+
|
232 |
+
$profile = self::get_profile($taxonomy, $language);
|
233 |
+
if ('disabled' == $profile['profile'])
|
234 |
+
return;
|
235 |
+
|
236 |
+
$client = new Lingotek_API();
|
237 |
+
|
238 |
+
$params = array(
|
239 |
+
'title' => $term->name,
|
240 |
+
'content' => Lingotek_Group_Term::get_content($term),
|
241 |
+
'locale_code' => $language->lingotek_locale,
|
242 |
+
'project_id' => self::get_profile_option('project_id', $taxonomy, $language),
|
243 |
+
'workflow_id' => self::get_profile_option('workflow_id', $taxonomy, $language)
|
244 |
+
);
|
245 |
+
|
246 |
+
$filter_ids = array();
|
247 |
+
if (self::get_profile_option('primary_filter_id', $taxonomy, $language)) {
|
248 |
+
$filter_ids['fprm_id'] = self::get_profile_option('primary_filter_id', $taxonomy, $language);
|
249 |
+
}
|
250 |
+
if (self::get_profile_option('secondary_filter_id', $taxonomy, $language)) {
|
251 |
+
$filter_ids['fprm_subfilter_id'] = self::get_profile_option('secondary_filter_id', $taxonomy, $language);
|
252 |
+
}
|
253 |
+
$params = array_merge($params, $filter_ids);
|
254 |
+
|
255 |
+
if (($document = $this->get_group('term', $term_id)) && 'edited' == $document->status) {
|
256 |
+
$document->patch($term->name, $term, '', $filter_ids);
|
257 |
+
}
|
258 |
+
|
259 |
+
elseif (!Lingotek_Group::$creating_translation) {
|
260 |
+
$document_id = $client->upload_document($params);
|
261 |
+
|
262 |
+
if ($document_id) {
|
263 |
+
Lingotek_Group_Term::create($term_id, $taxonomy , $language, $document_id);
|
264 |
+
}
|
265 |
+
}
|
266 |
+
}
|
267 |
+
|
268 |
+
/*
|
269 |
+
* uploads a strings group to Lingotek TMS
|
270 |
+
*
|
271 |
+
* @since 0.2
|
272 |
+
*
|
273 |
+
* @param string $group
|
274 |
+
*/
|
275 |
+
public function upload_strings($group) {
|
276 |
+
$language = $this->pllm->get_language($this->pllm->options['default_lang']);
|
277 |
+
$profile = self::get_profile('string', $language);
|
278 |
+
|
279 |
+
if ('disabled' == $profile['profile'])
|
280 |
+
return;
|
281 |
+
|
282 |
+
if (is_numeric($group)) {
|
283 |
+
$strings = self::get_strings();
|
284 |
+
$group = $strings[$group]['context'];
|
285 |
+
}
|
286 |
+
|
287 |
+
// check that we have a valid string group
|
288 |
+
if (!in_array($group, wp_list_pluck(self::get_strings(), 'context')))
|
289 |
+
return;
|
290 |
+
|
291 |
+
$client = new Lingotek_API();
|
292 |
+
|
293 |
+
$params = array(
|
294 |
+
'title' => $group,
|
295 |
+
'content' => Lingotek_Group_String::get_content($group),
|
296 |
+
'locale_code' => $language->lingotek_locale,
|
297 |
+
'project_id' => self::get_profile_option('project_id', 'string', $language),
|
298 |
+
'workflow_id' => self::get_profile_option('workflow_id', 'string', $language)
|
299 |
+
);
|
300 |
+
|
301 |
+
$filter_ids = array();
|
302 |
+
if (self::get_profile_option('primary_filter_id', 'string', $language)) {
|
303 |
+
$filter_ids['fprm_id'] = self::get_profile_option('primary_filter_id', 'string', $language);
|
304 |
+
}
|
305 |
+
if (self::get_profile_option('secondary_filter_id', 'string', $language)) {
|
306 |
+
$filter_ids['fprm_subfilter_id'] = self::get_profile_option('secondary_filter_id', 'string', $language);
|
307 |
+
}
|
308 |
+
$params = array_merge($params, $filter_ids);
|
309 |
+
|
310 |
+
if (($document = $this->get_group('string', $group)) && 'edited' == $document->status) {
|
311 |
+
$document->patch($group);
|
312 |
+
}
|
313 |
+
else {
|
314 |
+
$document_id = $client->upload_document($params);
|
315 |
+
|
316 |
+
if ($document_id) {
|
317 |
+
Lingotek_Group_String::create($group, $language, $document_id);
|
318 |
+
}
|
319 |
+
}
|
320 |
+
}
|
321 |
+
|
322 |
+
/*
|
323 |
+
* checks if the document can be upload to Lingotek
|
324 |
+
*
|
325 |
+
* @since 0.1
|
326 |
+
*
|
327 |
+
* @param string $type either 'post' or 'term'
|
328 |
+
* @param int $object_id post id or term id
|
329 |
+
* @return bool
|
330 |
+
*/
|
331 |
+
// FIXME should I check for disabled profile here?
|
332 |
+
public function can_upload($type, $object_id) {
|
333 |
+
$document = $this->get_group($type, $object_id);
|
334 |
+
|
335 |
+
switch ($type) {
|
336 |
+
case 'string':
|
337 |
+
/*
|
338 |
+
$profile = self::get_profile('string', $this->pllm->get_language($this->pllm->options['default_lang']));
|
339 |
+
if ('disabled' == $profile['profile'])
|
340 |
+
return false;
|
341 |
+
*/
|
342 |
+
if (empty($document))
|
343 |
+
return true;
|
344 |
+
|
345 |
+
elseif ($document->md5 != md5(Lingotek_Group_String::get_content($object_id))) { // check if source strings have not been modified
|
346 |
+
$document->source_edited();
|
347 |
+
return true;
|
348 |
+
}
|
349 |
+
|
350 |
+
return false;
|
351 |
+
|
352 |
+
case 'post':
|
353 |
+
case 'term':
|
354 |
+
// first check that a language is associated to the object
|
355 |
+
$language = call_user_func(array(&$this->pllm, 'get_'.$type.'_language'), $object_id);
|
356 |
+
|
357 |
+
// FIXME how to get profile to check if disabled?
|
358 |
+
|
359 |
+
return !empty($language) && (empty($document) ||
|
360 |
+
(1 == count($this->pllm->get_translations($type, $object_id)) && empty($document->source)) || // specific for terms as document is never empty
|
361 |
+
(isset($document) && 'edited' == $document->status && $document->source == $object_id));
|
362 |
+
}
|
363 |
+
}
|
364 |
+
|
365 |
+
/*
|
366 |
+
* deletes a post
|
367 |
+
*
|
368 |
+
* @since 0.1
|
369 |
+
*
|
370 |
+
* @param int $object_id post id
|
371 |
+
*/
|
372 |
+
public function delete_post($object_id) {
|
373 |
+
if ($document = $this->get_group('post', $object_id)) {
|
374 |
+
$client = new Lingotek_API();
|
375 |
+
|
376 |
+
if ($document->source == $object_id) {
|
377 |
+
$client->delete_document($document->document_id);
|
378 |
+
}
|
379 |
+
else {
|
380 |
+
$this->pllm->delete_translation('post', $object_id);
|
381 |
+
$lang = $this->pllm->get_post_language($object_id);
|
382 |
+
$client->delete_translation($document->document_id, $lang->lingotek_locale);
|
383 |
+
}
|
384 |
+
}
|
385 |
+
}
|
386 |
+
|
387 |
+
/*
|
388 |
+
* deletes a term
|
389 |
+
*
|
390 |
+
* @since 0.2
|
391 |
+
*
|
392 |
+
* @param int $object_id term id
|
393 |
+
*/
|
394 |
+
public function delete_term($object_id) {
|
395 |
+
if ($document = $this->get_group('term', $object_id)) {
|
396 |
+
$client = new Lingotek_API();
|
397 |
+
|
398 |
+
if ($document->source == $object_id) {
|
399 |
+
$client->delete_document($document->document_id);
|
400 |
+
}
|
401 |
+
else {
|
402 |
+
$lang = $this->pllm->get_term_language($object_id);
|
403 |
+
$this->pllm->delete_term_language($object_id);
|
404 |
+
$this->pllm->delete_translation('term', $object_id);
|
405 |
+
$client->delete_translation($document->document_id, $lang->lingotek_locale);
|
406 |
+
}
|
407 |
+
}
|
408 |
+
}
|
409 |
+
|
410 |
+
/*
|
411 |
+
* counts the number of targets per language
|
412 |
+
*
|
413 |
+
* @since 0.2
|
414 |
+
*
|
415 |
+
* @param array $groups array of serialized 'post_translations' or 'term_translations' description
|
416 |
+
* @return array number of targets per language
|
417 |
+
*/
|
418 |
+
protected function get_target_count($groups) {
|
419 |
+
$targets = array_fill_keys($this->pllm->get_languages_list(array('fields' => 'slug')), 0);
|
420 |
+
|
421 |
+
foreach ($groups as $group) {
|
422 |
+
$group = unserialize($group);
|
423 |
+
if (isset($group['lingotek']['translations'])) {
|
424 |
+
foreach ($group['lingotek']['translations'] as $locale => $status) {
|
425 |
+
if ('current' == $status && $language = $this->pllm->get_language($locale))
|
426 |
+
$targets[$language->slug]++;
|
427 |
+
}
|
428 |
+
}
|
429 |
+
}
|
430 |
+
return $targets;
|
431 |
+
}
|
432 |
+
|
433 |
+
/*
|
434 |
+
* counts the number of sources and targets per language for a certain post type
|
435 |
+
*
|
436 |
+
* @since 0.2
|
437 |
+
*
|
438 |
+
* @param string $post_type
|
439 |
+
* @return array
|
440 |
+
*/
|
441 |
+
public function count_posts($post_type) {
|
442 |
+
global $wpdb;
|
443 |
+
|
444 |
+
static $r = array();
|
445 |
+
if (!empty($r[$post_type]))
|
446 |
+
return $r[$post_type];
|
447 |
+
|
448 |
+
if (!post_type_exists($post_type))
|
449 |
+
return;
|
450 |
+
|
451 |
+
// gets all translations groups for the post type
|
452 |
+
$groups = $wpdb->get_col($wpdb->prepare("
|
453 |
+
SELECT DISTINCT tt.description FROM $wpdb->term_taxonomy AS tt
|
454 |
+
INNER JOIN $wpdb->term_relationships AS tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
|
455 |
+
INNER JOIN $wpdb->posts AS p ON p.ID = tr.object_id
|
456 |
+
WHERE tt.taxonomy = %s
|
457 |
+
AND p.post_type = %s
|
458 |
+
AND p.post_status NOT IN ('trash', 'auto-draft')",
|
459 |
+
'post_translations', $post_type
|
460 |
+
));
|
461 |
+
|
462 |
+
$targets = $this->get_target_count($groups);
|
463 |
+
|
464 |
+
foreach ($this->pllm->get_languages_list() as $language) {
|
465 |
+
// counts all the posts in one language
|
466 |
+
$n = $wpdb->get_var($wpdb->prepare("
|
467 |
+
SELECT COUNT(*) FROM $wpdb->term_relationships AS tr
|
468 |
+
INNER JOIN $wpdb->posts AS p ON p.ID = tr.object_id
|
469 |
+
WHERE tr.term_taxonomy_id = %d
|
470 |
+
AND p.post_type = %s
|
471 |
+
AND p.post_status NOT IN ('trash', 'auto-draft')",
|
472 |
+
$language->term_taxonomy_id, $post_type
|
473 |
+
));
|
474 |
+
|
475 |
+
// if a post is not a target, then it is source
|
476 |
+
$sources[$language->slug] = $n - $targets[$language->slug];
|
477 |
+
}
|
478 |
+
|
479 |
+
// untranslated posts have no associated translation group in DB
|
480 |
+
// so let's count them indirectly
|
481 |
+
|
482 |
+
// counts the number of translated posts
|
483 |
+
$n_translated = $wpdb->get_var($wpdb->prepare("
|
484 |
+
SELECT COUNT(*) FROM $wpdb->term_relationships AS tr
|
485 |
+
INNER JOIN $wpdb->posts AS p ON p.ID = tr.object_id
|
486 |
+
INNER JOIN $wpdb->term_taxonomy AS tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
|
487 |
+
WHERE tt.taxonomy = %s
|
488 |
+
AND p.post_type = %s
|
489 |
+
AND p.post_status NOT IN ('trash', 'auto-draft')",
|
490 |
+
'post_translations', $post_type
|
491 |
+
));
|
492 |
+
|
493 |
+
|
494 |
+
|
495 |
+
// untranslated = total - translated
|
496 |
+
// total of posts translations groups = untranslated + number of translation groups stored in DB
|
497 |
+
$count_posts = (array) wp_count_posts($post_type);
|
498 |
+
unset($count_posts['trash'], $count_posts['auto-draft']); // don't count trash and auto-draft
|
499 |
+
$total = array_sum($count_posts) - $n_translated + count($groups);
|
500 |
+
|
501 |
+
return $r[$post_type] = compact('sources', 'targets', 'total');
|
502 |
+
}
|
503 |
+
|
504 |
+
/*
|
505 |
+
* counts the number of sources and targets per language for a certain taxonomy
|
506 |
+
*
|
507 |
+
* @since 0.2
|
508 |
+
*
|
509 |
+
* @param string $taxonomy
|
510 |
+
* @return array
|
511 |
+
*/
|
512 |
+
public function count_terms($taxonomy) {
|
513 |
+
global $wpdb;
|
514 |
+
|
515 |
+
static $r = array();
|
516 |
+
if (!empty($r[$taxonomy]))
|
517 |
+
return $r[$taxonomy];
|
518 |
+
|
519 |
+
if (!taxonomy_exists($taxonomy))
|
520 |
+
return;
|
521 |
+
|
522 |
+
// gets all translations groups for the taxonomy
|
523 |
+
$groups = $wpdb->get_col($wpdb->prepare("
|
524 |
+
SELECT DISTINCT tt1.description FROM $wpdb->term_taxonomy AS tt1
|
525 |
+
INNER JOIN $wpdb->term_relationships AS tr ON tt1.term_taxonomy_id = tr.term_taxonomy_id
|
526 |
+
INNER JOIN $wpdb->term_taxonomy AS tt2 ON tt2.term_id = tr.object_id
|
527 |
+
WHERE tt1.taxonomy = %s
|
528 |
+
AND tt2.taxonomy = %s",
|
529 |
+
'term_translations', $taxonomy
|
530 |
+
));
|
531 |
+
|
532 |
+
$targets = $this->get_target_count($groups);
|
533 |
+
|
534 |
+
foreach ($this->pllm->get_languages_list() as $language) {
|
535 |
+
// counts all the terms in one language
|
536 |
+
$n = $wpdb->get_var($wpdb->prepare("
|
537 |
+
SELECT COUNT(*) FROM $wpdb->term_relationships AS tr
|
538 |
+
INNER JOIN $wpdb->term_taxonomy AS tt ON tt.term_id = tr.object_id
|
539 |
+
WHERE tr.term_taxonomy_id = %d
|
540 |
+
AND tt.taxonomy = %s",
|
541 |
+
$language->tl_term_taxonomy_id, $taxonomy
|
542 |
+
));
|
543 |
+
|
544 |
+
// if a term is not a target, then it is a source
|
545 |
+
$sources[$language->slug] = $n - $targets[$language->slug];
|
546 |
+
}
|
547 |
+
|
548 |
+
$total = count($groups);
|
549 |
+
|
550 |
+
// default categories are created by Polylang in all languages
|
551 |
+
// don't count them as sources if they are not associated to the TMS
|
552 |
+
if ('category' === $taxonomy) {
|
553 |
+
$term_id = get_option('default_category');
|
554 |
+
$group = $this->get_group('term', $term_id);
|
555 |
+
foreach($this->pllm->get_languages_list() as $language) {
|
556 |
+
if (empty($group->source) || ($group->get_source_language()->slug != $language->slug && empty($group->translations[$language->locale])))
|
557 |
+
$sources[$language->slug]--;
|
558 |
+
}
|
559 |
+
}
|
560 |
+
|
561 |
+
return $r[$taxonomy] = compact('sources', 'targets', 'total');
|
562 |
+
}
|
563 |
+
}
|
include/pointer.php
ADDED
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// code borrowed from Polylang
|
3 |
+
class Lingotek_Pointer {
|
4 |
+
protected $args;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Constructor
|
8 |
+
* Enqueues the pointer script
|
9 |
+
*
|
10 |
+
* List of parameters accepted in $args:
|
11 |
+
*
|
12 |
+
* pointer => required, unique identifier of the pointer
|
13 |
+
* id => required, the pointer will be attached to this html id
|
14 |
+
* position => optional array, if used both sub parameters are required
|
15 |
+
* edge => 'top' or 'bottom'
|
16 |
+
* align => 'right' or 'left'
|
17 |
+
* width => optional, the width in px
|
18 |
+
* title => required, title
|
19 |
+
* content => required, content
|
20 |
+
* buttons => optional array of arrays, by default the pointer uses the standard dismiss button offered by WP
|
21 |
+
* label => the label of the button
|
22 |
+
* link => optional link for the button. By default, the button just dismisses the pointer
|
23 |
+
*
|
24 |
+
* @since 1.0.1
|
25 |
+
*
|
26 |
+
* @param array $args
|
27 |
+
*/
|
28 |
+
public function __construct($args) {
|
29 |
+
$this->args = $args;
|
30 |
+
add_action('admin_enqueue_scripts', array(&$this, 'enqueue_scripts'));
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Enqueue JavaScript and styles if the pointer has not been dismissed
|
35 |
+
*
|
36 |
+
* @since 1.0.1
|
37 |
+
*/
|
38 |
+
public function enqueue_scripts() {
|
39 |
+
$dismissed = explode(',', get_user_meta(get_current_user_id(), 'dismissed_wp_pointers', true));
|
40 |
+
|
41 |
+
// comment the two lines below to make the pointer non dismissable
|
42 |
+
if (in_array($this->args['pointer'], $dismissed) || !current_user_can('manage_options'))
|
43 |
+
return;
|
44 |
+
|
45 |
+
// Add pointer JavaScript
|
46 |
+
add_action('admin_print_footer_scripts', array(&$this, 'print_js'));
|
47 |
+
|
48 |
+
wp_enqueue_style('wp-pointer');
|
49 |
+
wp_enqueue_script('wp-pointer');
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Adds the JavaScript of our pointer to the page
|
54 |
+
*
|
55 |
+
* @since 1.0.1
|
56 |
+
*/
|
57 |
+
public function print_js() {
|
58 |
+
|
59 |
+
// add optional buttons
|
60 |
+
if (!empty($this->args['buttons'])) {
|
61 |
+
$b = "
|
62 |
+
var widget = pointer.pointer('widget');
|
63 |
+
var buttons = $('.wp-pointer-buttons', widget);
|
64 |
+
$('a.close', widget).remove();"; // removes the WP button
|
65 |
+
|
66 |
+
// all the buttons use the standard WP ajax action to remember the pointer has been dismissed
|
67 |
+
foreach ($this->args['buttons'] as $button) {
|
68 |
+
$b .= sprintf("
|
69 |
+
$('<a>').addClass('%s').html('%s').css('margin-left', '10px').click(function() {
|
70 |
+
$.post(ajaxurl, {
|
71 |
+
pointer: '%s',
|
72 |
+
action: 'dismiss-wp-pointer'
|
73 |
+
}, function(response) {
|
74 |
+
%s
|
75 |
+
});
|
76 |
+
}).appendTo(buttons);",
|
77 |
+
empty($button['link']) ? 'button' : 'button button-primary',
|
78 |
+
$button['label'],
|
79 |
+
$this->args['pointer'],
|
80 |
+
empty($button['link']) ? "pointer.pointer('close')" : sprintf("location.href = '%s'", $button['link'])
|
81 |
+
);
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
$js = sprintf("
|
86 |
+
//<![CDATA[
|
87 |
+
jQuery(document).ready(function($) {
|
88 |
+
var pointer = $('#%s').pointer({
|
89 |
+
content: '%s',
|
90 |
+
%s
|
91 |
+
%s
|
92 |
+
});
|
93 |
+
pointer.pointer('open');
|
94 |
+
%s
|
95 |
+
});
|
96 |
+
// ]]>",
|
97 |
+
$this->args['id'],
|
98 |
+
sprintf('<h3>%s</h3><p>%s</p>', $this->args['title'], $this->args['content']),
|
99 |
+
empty($this->args['position']) ? '' : sprintf('position: {edge: "%s", align: "%s",},', $this->args['position']['edge'], $this->args['position']['align']),
|
100 |
+
empty($this->args['width']) ? '' : sprintf('pointerWidth: %d,', $this->args['width']),
|
101 |
+
empty($b) ? '' : $b
|
102 |
+
);
|
103 |
+
echo "<script type='text/javascript'>" .$js. "</script>";
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
+
?>
|
js/defaults.js
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function toggleTextbox () {
|
2 |
+
var box = document.getElementById('new_project');
|
3 |
+
if (box.style.display === 'none') {
|
4 |
+
box.style.display = 'inline';
|
5 |
+
document.getElementById('project_id').style.display = 'none';
|
6 |
+
document.getElementById('update_callback').style.visibility = 'hidden';
|
7 |
+
document.getElementById('callback_label').style.display = 'none';
|
8 |
+
document.getElementById('update_callback').checked = false;
|
9 |
+
document.getElementById('create').innerHTML = '- Use Existing Project';
|
10 |
+
}
|
11 |
+
else if (box.style.display === 'inline') {
|
12 |
+
box.style.display = 'none';
|
13 |
+
document.getElementById('project_id').style.display= 'initial';
|
14 |
+
document.getElementById('update_callback').style.visibility = 'visible';
|
15 |
+
document.getElementById('callback_label').style.display = 'initial';
|
16 |
+
document.getElementById('create').innerHTML = '+ Create New Project';
|
17 |
+
}
|
18 |
+
}
|
js/progress.js
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(document).ready(function($) {
|
2 |
+
|
3 |
+
function lingotek_progress(i) {
|
4 |
+
if (i < lingotek_data.ids.length) {
|
5 |
+
var data = {
|
6 |
+
action: 'lingotek_progress_'+lingotek_data.action,
|
7 |
+
taxonomy: lingotek_data.taxonomy, // empty for posts
|
8 |
+
id: lingotek_data.ids[i],
|
9 |
+
_lingotek_nonce: lingotek_data.nonce
|
10 |
+
}
|
11 |
+
|
12 |
+
$.post(ajaxurl, data , function(response) {
|
13 |
+
$("#lingotek-progressbar").progressbar({
|
14 |
+
value: ++i / lingotek_data.ids.length * 100
|
15 |
+
});
|
16 |
+
lingotek_progress(i);
|
17 |
+
});
|
18 |
+
}
|
19 |
+
|
20 |
+
else
|
21 |
+
jQuery(location).attr('href', lingotek_data.sendback);
|
22 |
+
}
|
23 |
+
|
24 |
+
if ('undefined' != typeof(lingotek_data)) {
|
25 |
+
if ('' == lingotek_data.warning || confirm(lingotek_data.warning)) {
|
26 |
+
var d = $("#lingotek-progressdialog");
|
27 |
+
if (d.length) {
|
28 |
+
d.dialog({
|
29 |
+
dialogClass: "wp-dialog",
|
30 |
+
width: 400
|
31 |
+
});
|
32 |
+
$("#lingotek-progressbar").progressbar();
|
33 |
+
lingotek_progress(0);
|
34 |
+
}
|
35 |
+
}
|
36 |
+
else
|
37 |
+
jQuery(location).attr('href', lingotek_data.sendback);
|
38 |
+
}
|
39 |
+
});
|
languages/wp-lingotek-fr_FR.mo
ADDED
Binary file
|
languages/wp-lingotek-fr_FR.po
ADDED
@@ -0,0 +1,1203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (C) 2015 Lingotek Translation
|
2 |
+
# This file is distributed under the same license as the Lingotek Translation package.
|
3 |
+
msgid ""
|
4 |
+
msgstr ""
|
5 |
+
"Project-Id-Version: Lingotek Translation 1.0.0\n"
|
6 |
+
"Report-Msgid-Bugs-To: http://wordpress.org/support/plugin/wp-lingotek\n"
|
7 |
+
"POT-Creation-Date: 2015-06-29 15:40:38+00:00\n"
|
8 |
+
"MIME-Version: 1.0\n"
|
9 |
+
"Content-Type: text/plain; charset=UTF-8\n"
|
10 |
+
"Content-Transfer-Encoding: 8bit\n"
|
11 |
+
"PO-Revision-Date: 2015-MO-DA HO:MI+ZONE\n"
|
12 |
+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
13 |
+
"Language-Team: LANGUAGE <LL@li.org>\n"
|
14 |
+
|
15 |
+
#: admin/actions.php:21 admin/actions.php:354
|
16 |
+
msgid "You are about to overwrite existing translations. Are you sure?"
|
17 |
+
msgstr "Vous êtes sur le point d'écraser les traductions existantes. Es-tu sûr?"
|
18 |
+
|
19 |
+
#: admin/actions.php:26
|
20 |
+
msgid "Upload to Lingotek"
|
21 |
+
msgstr "Télécharger sur Lingotek"
|
22 |
+
|
23 |
+
#: admin/actions.php:27
|
24 |
+
msgid "Uploading..."
|
25 |
+
msgstr "Téléchargement..."
|
26 |
+
|
27 |
+
#: admin/actions.php:28
|
28 |
+
msgid "Upload this item to Lingotek TMS"
|
29 |
+
msgstr "Téléchargez cet article sur Lingotek TMS"
|
30 |
+
|
31 |
+
#: admin/actions.php:32
|
32 |
+
msgid "Request translations"
|
33 |
+
msgstr "Traductions de la demande"
|
34 |
+
|
35 |
+
#: admin/actions.php:33
|
36 |
+
msgid "Requesting translations..."
|
37 |
+
msgstr "Demander des traductions..."
|
38 |
+
|
39 |
+
#: admin/actions.php:34
|
40 |
+
msgid "Request translations of this item to Lingotek TMS"
|
41 |
+
msgstr "Demander des traductions de ce point de Lingotek TMS"
|
42 |
+
|
43 |
+
#: admin/actions.php:38
|
44 |
+
msgid "Update translations status"
|
45 |
+
msgstr "Mise à jour de statut de la traduction"
|
46 |
+
|
47 |
+
#: admin/actions.php:39
|
48 |
+
msgid "Updating translations status..."
|
49 |
+
msgstr "Mise à jour de statut de la traduction..."
|
50 |
+
|
51 |
+
#: admin/actions.php:40
|
52 |
+
msgid "Update translations status of this item in Lingotek TMS"
|
53 |
+
msgstr "Mise à jour de statut de la traduction de ce point de Lingotek TMS"
|
54 |
+
|
55 |
+
#: admin/actions.php:44 admin/admin.php:208
|
56 |
+
msgid "Download translations"
|
57 |
+
msgstr "Télécharger les traductions"
|
58 |
+
|
59 |
+
#: admin/actions.php:45
|
60 |
+
msgid "Downloading translations..."
|
61 |
+
msgstr "Téléchargement des traductions..."
|
62 |
+
|
63 |
+
#: admin/actions.php:46
|
64 |
+
msgid "Download translations of this item from Lingotek TMS"
|
65 |
+
msgstr "Télécharger les traductions de ce point de Lingotek TMS"
|
66 |
+
|
67 |
+
#: admin/actions.php:50
|
68 |
+
msgid "Disassociate translations"
|
69 |
+
msgstr "Dissocier les traductions"
|
70 |
+
|
71 |
+
#: admin/actions.php:51
|
72 |
+
msgid "Disassociating translations..."
|
73 |
+
msgstr "Association des traductions..."
|
74 |
+
|
75 |
+
#: admin/actions.php:52
|
76 |
+
msgid "Disassociate the translations of this item from Lingotek TMS"
|
77 |
+
msgstr "Dissocier les traductions de ce point de Lingotek TMS"
|
78 |
+
|
79 |
+
#: admin/actions.php:59
|
80 |
+
msgid "Upload Now"
|
81 |
+
msgstr "Télécharger maintenant"
|
82 |
+
|
83 |
+
#: admin/actions.php:64
|
84 |
+
msgid "Importing source"
|
85 |
+
msgstr "Importation de source"
|
86 |
+
|
87 |
+
#: admin/actions.php:69
|
88 |
+
msgid "Source uploaded"
|
89 |
+
msgstr "Source téléchargée"
|
90 |
+
|
91 |
+
#: admin/actions.php:74
|
92 |
+
msgid "Request a translation"
|
93 |
+
msgstr "Une demande de traduction"
|
94 |
+
|
95 |
+
#: admin/actions.php:79 admin/tutorial/content.php:72
|
96 |
+
msgid "In Progress"
|
97 |
+
msgstr "En cours"
|
98 |
+
|
99 |
+
#: admin/actions.php:84
|
100 |
+
msgid "Ready to download"
|
101 |
+
msgstr "Prêt à télécharger"
|
102 |
+
|
103 |
+
#: admin/actions.php:89
|
104 |
+
msgid "current"
|
105 |
+
msgstr "actuel"
|
106 |
+
|
107 |
+
#: admin/actions.php:94
|
108 |
+
msgid ""
|
109 |
+
"The target translation is no longer current as the source content has been "
|
110 |
+
"updated"
|
111 |
+
msgstr "La traduction de cible n'est plus actuelle que le contenu de la source a été mis à jour"
|
112 |
+
|
113 |
+
#: admin/admin.php:85 admin/admin.php:105 admin/settings.php:2
|
114 |
+
msgid "Settings"
|
115 |
+
msgstr "Paramètres"
|
116 |
+
|
117 |
+
#: admin/admin.php:96
|
118 |
+
msgid "Translation"
|
119 |
+
msgstr "Traduction"
|
120 |
+
|
121 |
+
#: admin/admin.php:103 admin/tutorial/faq.php:58
|
122 |
+
msgid "Translation Dashboard"
|
123 |
+
msgstr "Tableau de bord de traduction"
|
124 |
+
|
125 |
+
#: admin/admin.php:103 admin/view-dashboard.php:2
|
126 |
+
msgid "Dashboard"
|
127 |
+
msgstr "Tableau de bord"
|
128 |
+
|
129 |
+
#: admin/admin.php:104
|
130 |
+
msgid "Translation Management"
|
131 |
+
msgstr "Gestion des traductions"
|
132 |
+
|
133 |
+
#: admin/admin.php:104 admin/view-manage.php:2
|
134 |
+
msgid "Manage"
|
135 |
+
msgstr "Gérer"
|
136 |
+
|
137 |
+
#: admin/admin.php:105
|
138 |
+
msgid "Translation Settings"
|
139 |
+
msgstr "Paramètres de translation"
|
140 |
+
|
141 |
+
#: admin/admin.php:106
|
142 |
+
msgid "Lingotek Tutorial"
|
143 |
+
msgstr "Tutoriel de Lingotek"
|
144 |
+
|
145 |
+
#: admin/admin.php:106 admin/view-tutorial.php:5
|
146 |
+
msgid "Tutorial"
|
147 |
+
msgstr "Tutorial"
|
148 |
+
|
149 |
+
#: admin/admin.php:130
|
150 |
+
msgid "Your Lingotek account has been successfully connected."
|
151 |
+
msgstr "Votre compte de Lingotek a été connecté avec succès."
|
152 |
+
|
153 |
+
#: admin/admin.php:133
|
154 |
+
msgid ""
|
155 |
+
"Your Lingotek account was not connected.\tThe Access Token received was "
|
156 |
+
"invalid."
|
157 |
+
msgstr "Votre compte de Lingotek n'était pas connecté\t. Le jeton d'accès reçue n'était pas valide."
|
158 |
+
|
159 |
+
#: admin/admin.php:147
|
160 |
+
msgid "Your community has been successfully saved."
|
161 |
+
msgstr "Votre collectivité a été enregistrée avec succès."
|
162 |
+
|
163 |
+
#: admin/admin.php:152
|
164 |
+
msgid "Select and save the community that you would like to use."
|
165 |
+
msgstr "Sélectionnez et enregistrez la communauté que vous souhaitez utiliser."
|
166 |
+
|
167 |
+
#: admin/admin.php:176
|
168 |
+
msgid "Redirecting to Lingotek to connect your account..."
|
169 |
+
msgstr "Redirection vers Lingotek pour vous connecter à votre compte..."
|
170 |
+
|
171 |
+
#: admin/admin.php:197 lingotek.php:199
|
172 |
+
msgid "Manual"
|
173 |
+
msgstr "Manuelle"
|
174 |
+
|
175 |
+
#: admin/admin.php:198 lingotek.php:193
|
176 |
+
msgid "Automatic"
|
177 |
+
msgstr "Automatique"
|
178 |
+
|
179 |
+
#: admin/admin.php:203
|
180 |
+
msgid "Upload content"
|
181 |
+
msgstr "Télécharger du contenu"
|
182 |
+
|
183 |
+
#: admin/admin.php:205
|
184 |
+
msgid "How should new and modified content be uploaded to Lingotek?"
|
185 |
+
msgstr "Comment les nouveaux et mis à jour le contenu doit être téléchargé de Lingotek ?"
|
186 |
+
|
187 |
+
#: admin/admin.php:210
|
188 |
+
msgid "How should completed translations be downloaded to WordPress?"
|
189 |
+
msgstr "Comment les traductions dûment remplies doivent être téléchargées pour WordPress ?"
|
190 |
+
|
191 |
+
#: admin/admin.php:213
|
192 |
+
msgid "Default Project"
|
193 |
+
msgstr "Projet par défaut"
|
194 |
+
|
195 |
+
#: admin/admin.php:213
|
196 |
+
msgid "Project"
|
197 |
+
msgstr "Projet"
|
198 |
+
|
199 |
+
#: admin/admin.php:215
|
200 |
+
msgid "Changes will affect new entities only"
|
201 |
+
msgstr "Changements affecteront les nouvelles entités seulement"
|
202 |
+
|
203 |
+
#: admin/admin.php:218
|
204 |
+
msgid "Default Workflow"
|
205 |
+
msgstr "Flux de travail par défaut"
|
206 |
+
|
207 |
+
#: admin/admin.php:218
|
208 |
+
msgid "Workflow"
|
209 |
+
msgstr "Flux de travail"
|
210 |
+
|
211 |
+
#: admin/admin.php:222
|
212 |
+
msgid "Primary Filter"
|
213 |
+
msgstr "Filtre primaire"
|
214 |
+
|
215 |
+
#: admin/admin.php:226
|
216 |
+
msgid "Secondary Filter"
|
217 |
+
msgstr "Filtre secondaire"
|
218 |
+
|
219 |
+
#: admin/admin.php:286
|
220 |
+
msgid "Your Community currently has no projects."
|
221 |
+
msgstr "Votre collectivité n'a actuellement aucun projet."
|
222 |
+
|
223 |
+
#: admin/admin.php:289
|
224 |
+
msgid "Projects could not be refreshed"
|
225 |
+
msgstr "Impossible d'actualiser des projets"
|
226 |
+
|
227 |
+
#: admin/admin.php:302
|
228 |
+
msgid "Workflows could not be refreshed"
|
229 |
+
msgstr "Impossible d'actualiser les workflows"
|
230 |
+
|
231 |
+
#: admin/admin.php:371
|
232 |
+
msgid ""
|
233 |
+
"Your <a href=\"%s\"><i>Defaults</i></a> have been updated to valid options "
|
234 |
+
"for this community."
|
235 |
+
msgstr "Vos <a href=\"%s\"><i>paramètres par défaut</i></a> ont été upgradés dans options valides pour cette communauté."
|
236 |
+
|
237 |
+
#: admin/admin.php:398
|
238 |
+
msgid "Strings groups"
|
239 |
+
msgstr "Groupes de chaînes"
|
240 |
+
|
241 |
+
#: admin/admin.php:486
|
242 |
+
msgid "Lingotek Settings"
|
243 |
+
msgstr "Paramètres de Lingotek"
|
244 |
+
|
245 |
+
#: admin/content-table.php:61
|
246 |
+
msgid "%s source"
|
247 |
+
msgstr "%s source"
|
248 |
+
|
249 |
+
#: admin/content-table.php:85
|
250 |
+
msgid "Use content type default"
|
251 |
+
msgstr "Utilisez la valeur par défaut du type de contenu"
|
252 |
+
|
253 |
+
#: admin/content-table.php:153
|
254 |
+
msgid "Content Type"
|
255 |
+
msgstr "Type de contenu"
|
256 |
+
|
257 |
+
#: admin/content-table.php:154
|
258 |
+
msgid "Profile"
|
259 |
+
msgstr "Profil"
|
260 |
+
|
261 |
+
#: admin/content-table.php:155
|
262 |
+
msgid "Fields"
|
263 |
+
msgstr "Champs"
|
264 |
+
|
265 |
+
#: admin/manage/view-string-groups.php:1 admin/view-manage.php:7
|
266 |
+
msgid "String Groups"
|
267 |
+
msgstr "Groupes de chaîne"
|
268 |
+
|
269 |
+
#: admin/manage/view-string-groups.php:2
|
270 |
+
msgid ""
|
271 |
+
"Manage group translation of system, widget, and plugin-specific strings. "
|
272 |
+
"View individual strings on the <a href=\"%s\"><b>Strings</b></a> page."
|
273 |
+
msgstr "Gérer la traduction de groupe du système, widget et des chaînes spécifiques plugin. Affichage des chaînes individuelles sur la page <a href=\"%s\"><b>chaînes</b></a> ."
|
274 |
+
|
275 |
+
#: admin/manage/view-string-groups.php:9
|
276 |
+
msgid "The strings translation is disabled in %sContent Type Configuration%s."
|
277 |
+
msgstr "La traduction de chaînes est désactivée dans %sla Configuration de Type de contenu%s."
|
278 |
+
|
279 |
+
#: admin/manage/view-strings.php:1 admin/settings/view-content.php:29
|
280 |
+
#: admin/view-manage.php:8
|
281 |
+
msgid "Strings"
|
282 |
+
msgstr "Chaînes"
|
283 |
+
|
284 |
+
#: admin/manage/view-strings.php:1
|
285 |
+
msgid "Edit on Polylang Strings Translation page"
|
286 |
+
msgstr "Modifier sur la page de traduction de chaînes de Polylang"
|
287 |
+
|
288 |
+
#: admin/manage/view-strings.php:45
|
289 |
+
msgid "Search translations"
|
290 |
+
msgstr "Recherche de traductions"
|
291 |
+
|
292 |
+
#: admin/profiles-table.php:44
|
293 |
+
msgid "No content types"
|
294 |
+
msgstr "Aucun des types de contenu"
|
295 |
+
|
296 |
+
#: admin/profiles-table.php:45
|
297 |
+
msgid "1 content type"
|
298 |
+
msgid_plural "%d content types"
|
299 |
+
msgstr[0] "1 type de contenu"
|
300 |
+
msgstr[1] "%d types de contenu"
|
301 |
+
|
302 |
+
#: admin/profiles-table.php:63
|
303 |
+
msgid "Edit"
|
304 |
+
msgstr "Edit"
|
305 |
+
|
306 |
+
#: admin/profiles-table.php:70 admin/settings/view-edit-profile.php:195
|
307 |
+
msgid "You are about to permanently delete this profile. Are you sure?"
|
308 |
+
msgstr "Vous êtes sur le point de supprimer définitivement ce profil. Es-tu sûr?"
|
309 |
+
|
310 |
+
#: admin/profiles-table.php:71 admin/settings/view-edit-profile.php:196
|
311 |
+
msgid "Delete"
|
312 |
+
msgstr "Supprimer"
|
313 |
+
|
314 |
+
#: admin/profiles-table.php:86 admin/settings/view-edit-profile.php:64
|
315 |
+
msgid "Profile name"
|
316 |
+
msgstr "Nom du profil"
|
317 |
+
|
318 |
+
#: admin/profiles-table.php:87
|
319 |
+
msgid "Usage"
|
320 |
+
msgstr "Utilisation"
|
321 |
+
|
322 |
+
#: admin/profiles-table.php:88
|
323 |
+
msgid "Actions"
|
324 |
+
msgstr "Actions"
|
325 |
+
|
326 |
+
#: admin/settings/connect-account.php:16
|
327 |
+
msgid "Connect Your Account"
|
328 |
+
msgstr "Se connecter à votre compte"
|
329 |
+
|
330 |
+
#: admin/settings/connect-account.php:19
|
331 |
+
msgid ""
|
332 |
+
"Get started by clicking the button below to connect your Lingotek account to "
|
333 |
+
"this Wordpress installation."
|
334 |
+
msgstr "Commencez en cliquant sur le bouton ci-dessous pour vous connecter à votre compte de Lingotek pour cette installation de Wordpress."
|
335 |
+
|
336 |
+
#: admin/settings/connect-account.php:24
|
337 |
+
msgid "Connect New Account"
|
338 |
+
msgstr "Se connecter nouveau compte"
|
339 |
+
|
340 |
+
#: admin/settings/connect-account.php:28
|
341 |
+
msgid ""
|
342 |
+
"Do you already have a Lingotek account? <a href=\"%s\">Connect Lingotek "
|
343 |
+
"Account</a>"
|
344 |
+
msgstr "Vous possédez déjà un compte de Lingotek? <a href=\"%s\">Connecter compte Lingotek</a>"
|
345 |
+
|
346 |
+
#: admin/settings/connect-account.php:29
|
347 |
+
msgid ""
|
348 |
+
"Do you have a Lingotek sandbox account? <a href=\"%s\">Connect Sandbox "
|
349 |
+
"Account</a>"
|
350 |
+
msgstr "Vous avez un compte de bac à sable de Lingotek? <a href=\"%s\">Connecter compte Sandbox</a>"
|
351 |
+
|
352 |
+
#: admin/settings/view-account.php:14 admin/settings.php:11
|
353 |
+
#: admin/view-network.php:139
|
354 |
+
msgid "Account"
|
355 |
+
msgstr "Compte"
|
356 |
+
|
357 |
+
#: admin/settings/view-account.php:15
|
358 |
+
msgid "Lingotek account connection and community selection."
|
359 |
+
msgstr "Sélection de connexion et de la communauté Lingotek compte."
|
360 |
+
|
361 |
+
#: admin/settings/view-account.php:20 admin/settings/view-account.php:25
|
362 |
+
msgid "Connected"
|
363 |
+
msgstr "Connecté"
|
364 |
+
|
365 |
+
#: admin/settings/view-account.php:25
|
366 |
+
msgid "Yes"
|
367 |
+
msgstr "Oui"
|
368 |
+
|
369 |
+
#: admin/settings/view-account.php:30
|
370 |
+
msgid "Login ID"
|
371 |
+
msgstr "ID de connexion"
|
372 |
+
|
373 |
+
#: admin/settings/view-account.php:42
|
374 |
+
msgid "Access Token"
|
375 |
+
msgstr "Jeton d'accès"
|
376 |
+
|
377 |
+
#: admin/settings/view-account.php:57
|
378 |
+
msgid "API Endpoint"
|
379 |
+
msgstr "Point de terminaison API"
|
380 |
+
|
381 |
+
#: admin/settings/view-account.php:72
|
382 |
+
msgid ""
|
383 |
+
"Are you sure you would like to disconnect your Lingotek account? \\n\\nAfter "
|
384 |
+
"disconnecting, you will need to re-connect an account to continue using "
|
385 |
+
"Lingotek."
|
386 |
+
msgstr "Etes-vous sûr que vous souhaitez déconnecter votre compte Lingotek? \\n\\Anter déconnexion, vous aurez besoin de re-connecter un compte pour continuer à utiliser Lingotek."
|
387 |
+
|
388 |
+
#: admin/settings/view-account.php:73
|
389 |
+
msgid "Disconnect"
|
390 |
+
msgstr "Déconnecter"
|
391 |
+
|
392 |
+
#: admin/settings/view-account.php:87 admin/view-network.php:140
|
393 |
+
msgid "Community"
|
394 |
+
msgstr "Communauté"
|
395 |
+
|
396 |
+
#: admin/settings/view-account.php:107
|
397 |
+
msgid "Select"
|
398 |
+
msgstr "Sélectionnez"
|
399 |
+
|
400 |
+
#: admin/settings/view-account.php:119 admin/settings/view-content.php:90
|
401 |
+
#: admin/settings/view-defaults.php:138
|
402 |
+
#: admin/settings/view-edit-profile.php:188
|
403 |
+
#: admin/settings/view-preferences.php:83
|
404 |
+
msgid "Save Changes"
|
405 |
+
msgstr "Enregistrer les modifications"
|
406 |
+
|
407 |
+
#: admin/settings/view-content.php:68
|
408 |
+
msgid "Your content types were sucessfully saved."
|
409 |
+
msgstr "Vos types de contenu ont été correctement enregistrée."
|
410 |
+
|
411 |
+
#: admin/settings/view-content.php:81 admin/settings.php:17
|
412 |
+
msgid "Content Type Configuration"
|
413 |
+
msgstr "Configuration du Type de contenu"
|
414 |
+
|
415 |
+
#: admin/settings/view-content.php:82
|
416 |
+
msgid ""
|
417 |
+
"Content types can be configured to use any translation profile. "
|
418 |
+
"Additionally, translation profiles can be set based on the language the "
|
419 |
+
"content was authored in."
|
420 |
+
msgstr "Types de contenu peuvent être configurés pour utiliser n'importe quel profil de traduction. En outre, les profils de traduction peuvent être définies basées sur la langue en que le contenu a été rédigé."
|
421 |
+
|
422 |
+
#: admin/settings/view-defaults.php:13
|
423 |
+
msgid ""
|
424 |
+
"Resources from Lingotek were successfully updated for projects and workflows."
|
425 |
+
msgstr "Ressources de Lingotek ont été mis à jour pour les projets et les workflows."
|
426 |
+
|
427 |
+
#: admin/settings/view-defaults.php:16
|
428 |
+
msgid "Resources from Lingotek were successfully updated for projects."
|
429 |
+
msgstr "Ressources de Lingotek ont été mis à jour pour les projets."
|
430 |
+
|
431 |
+
#: admin/settings/view-defaults.php:19
|
432 |
+
msgid "Resources from Lingotek were successfully updated for workflows."
|
433 |
+
msgstr "Ressources de Lingotek ont été mis à jour pour les workflows."
|
434 |
+
|
435 |
+
#: admin/settings/view-defaults.php:31
|
436 |
+
msgid "Your <i>Defaults</i> were sucessfully saved."
|
437 |
+
msgstr "Vos <i>paramètres par défaut</i> ont été correctement enregistrée."
|
438 |
+
|
439 |
+
#: admin/settings/view-defaults.php:36 admin/settings/view-profiles.php:77
|
440 |
+
msgid "Your callback url was successfully updated."
|
441 |
+
msgstr "Votre url de callback a été mis à jour."
|
442 |
+
|
443 |
+
#: admin/settings/view-defaults.php:45 admin/view-network.php:98
|
444 |
+
msgid "Your new project was successfully created."
|
445 |
+
msgstr "Votre nouveau projet a été correctement créé."
|
446 |
+
|
447 |
+
#: admin/settings/view-defaults.php:87 admin/settings.php:15
|
448 |
+
#: admin/view-network.php:141
|
449 |
+
msgid "Defaults"
|
450 |
+
msgstr "Valeurs par défaut"
|
451 |
+
|
452 |
+
#: admin/settings/view-defaults.php:88
|
453 |
+
msgid ""
|
454 |
+
"The default automation settings and resources that should be used for this "
|
455 |
+
"site. These settings can be overriden using translation profiles and "
|
456 |
+
"content type configuration."
|
457 |
+
msgstr "Les paramètres d'automation par défaut et les ressources qui doivent être utilisés pour ce site. Ces paramètres peuvent être remplacé à l'aide de profils de traduction et de la configuration du type de contenu."
|
458 |
+
|
459 |
+
#: admin/settings/view-defaults.php:110 admin/settings/view-defaults.php:114
|
460 |
+
msgid "Enter new project name"
|
461 |
+
msgstr "Entrez le nom du nouveau projet"
|
462 |
+
|
463 |
+
#: admin/settings/view-defaults.php:116
|
464 |
+
#: admin/settings/view-edit-profile.php:90
|
465 |
+
msgid "Update the callback url for this project."
|
466 |
+
msgstr "Mettre à jour l'url de callback pour ce projet."
|
467 |
+
|
468 |
+
#: admin/settings/view-defaults.php:118
|
469 |
+
msgid "Create New Project"
|
470 |
+
msgstr "Créer le nouveau projet"
|
471 |
+
|
472 |
+
#: admin/settings/view-defaults.php:126
|
473 |
+
#: admin/settings/view-edit-profile.php:101
|
474 |
+
msgid "Filters"
|
475 |
+
msgstr "Filtres"
|
476 |
+
|
477 |
+
#: admin/settings/view-defaults.php:126
|
478 |
+
#: admin/settings/view-edit-profile.php:101
|
479 |
+
msgid "Not configured"
|
480 |
+
msgstr "Non configuré"
|
481 |
+
|
482 |
+
#: admin/settings/view-defaults.php:139
|
483 |
+
msgid "Refresh Resources"
|
484 |
+
msgstr "Actualiser les ressources"
|
485 |
+
|
486 |
+
#: admin/settings/view-edit-profile.php:6
|
487 |
+
msgid "Use global default (%s)"
|
488 |
+
msgstr "Utiliser par défaut global (%s)"
|
489 |
+
|
490 |
+
#: admin/settings/view-edit-profile.php:15
|
491 |
+
msgid "Use default settings"
|
492 |
+
msgstr "Utiliser les paramètres par défaut"
|
493 |
+
|
494 |
+
#: admin/settings/view-edit-profile.php:16
|
495 |
+
msgid "Use custom settings"
|
496 |
+
msgstr "Utiliser les paramètres personnalisés"
|
497 |
+
|
498 |
+
#: admin/settings/view-edit-profile.php:17 lingotek.php:205
|
499 |
+
msgid "Disabled"
|
500 |
+
msgstr "Handicapés"
|
501 |
+
|
502 |
+
#: admin/settings/view-edit-profile.php:74
|
503 |
+
msgid "Default settings"
|
504 |
+
msgstr "Paramètres par défaut"
|
505 |
+
|
506 |
+
#: admin/settings/view-edit-profile.php:114
|
507 |
+
msgid "Target languages"
|
508 |
+
msgstr "Langues cibles"
|
509 |
+
|
510 |
+
#: admin/settings/view-edit-profile.php:198
|
511 |
+
msgid "Cancel"
|
512 |
+
msgstr "Annuler"
|
513 |
+
|
514 |
+
#: admin/settings/view-preferences.php:6
|
515 |
+
msgid "Download translation status"
|
516 |
+
msgstr "Télécharger le statut de la traduction"
|
517 |
+
|
518 |
+
#: admin/settings/view-preferences.php:7
|
519 |
+
msgid "The post status for newly downloaded translations"
|
520 |
+
msgstr "Le statut de la poste pour les traductions nouvellement téléchargées"
|
521 |
+
|
522 |
+
#: admin/settings/view-preferences.php:9
|
523 |
+
msgid "Same as source post"
|
524 |
+
msgstr "Identique au poste source"
|
525 |
+
|
526 |
+
#: admin/settings/view-preferences.php:10
|
527 |
+
#: admin/settings/view-preferences.php:21
|
528 |
+
msgid "Draft"
|
529 |
+
msgstr "Projet"
|
530 |
+
|
531 |
+
#: admin/settings/view-preferences.php:11
|
532 |
+
#: admin/settings/view-preferences.php:22
|
533 |
+
msgid "Pending Review"
|
534 |
+
msgstr "Examen en attente"
|
535 |
+
|
536 |
+
#: admin/settings/view-preferences.php:12
|
537 |
+
#: admin/settings/view-preferences.php:23
|
538 |
+
msgid "Published"
|
539 |
+
msgstr "Publié"
|
540 |
+
|
541 |
+
#: admin/settings/view-preferences.php:14
|
542 |
+
#: admin/settings/view-preferences.php:25
|
543 |
+
msgid "Privately Published"
|
544 |
+
msgstr "Privé publié"
|
545 |
+
|
546 |
+
#: admin/settings/view-preferences.php:18
|
547 |
+
msgid "Auto upload statuses"
|
548 |
+
msgstr "Statuts de chargement automatique"
|
549 |
+
|
550 |
+
#: admin/settings/view-preferences.php:19
|
551 |
+
msgid ""
|
552 |
+
"The post statuses checked above are enabled for automatic upload (when using "
|
553 |
+
"automatic uploading translation profiles)."
|
554 |
+
msgstr "Les statuts de la poste vérifiés ci-dessus sont activés pour téléchargement automatique (lors de l'utilisation de profils de traduction téléchargement automatique)."
|
555 |
+
|
556 |
+
#: admin/settings/view-preferences.php:24
|
557 |
+
msgid "Scheduled"
|
558 |
+
msgstr "À la demande"
|
559 |
+
|
560 |
+
#: admin/settings/view-preferences.php:40
|
561 |
+
msgid "Your preferences were successfully updated."
|
562 |
+
msgstr "Vos préférences ont été correctement mis à jour."
|
563 |
+
|
564 |
+
#: admin/settings/view-preferences.php:48 admin/settings.php:18
|
565 |
+
#: admin/view-network.php:145
|
566 |
+
msgid "Preferences"
|
567 |
+
msgstr "Préférences"
|
568 |
+
|
569 |
+
#: admin/settings/view-preferences.php:49
|
570 |
+
msgid "These are your preferred settings."
|
571 |
+
msgstr "Ce sont vos réglages préférés."
|
572 |
+
|
573 |
+
#: admin/settings/view-profiles.php:15
|
574 |
+
msgid "Your translation profile was sucessfully deleted."
|
575 |
+
msgstr "Votre profil de traduction a été correctement supprimé."
|
576 |
+
|
577 |
+
#: admin/settings/view-profiles.php:28
|
578 |
+
msgid "You must provide a name for your translation profile."
|
579 |
+
msgstr "Vous devez fournir un nom pour votre profil de traduction."
|
580 |
+
|
581 |
+
#: admin/settings/view-profiles.php:71
|
582 |
+
msgid "Your translation profile was sucessfully saved."
|
583 |
+
msgstr "Votre profil de traduction a été correctement enregistré."
|
584 |
+
|
585 |
+
#: admin/settings/view-profiles.php:84 admin/settings.php:16
|
586 |
+
msgid "Translation Profiles"
|
587 |
+
msgstr "Traduction des profils"
|
588 |
+
|
589 |
+
#: admin/settings/view-profiles.php:85
|
590 |
+
msgid ""
|
591 |
+
"Translation profiles allow you to quickly configure and re-use translation "
|
592 |
+
"settings."
|
593 |
+
msgstr "Profils de translation permettent de configurer rapidement et ré-utiliser les paramètres de translation."
|
594 |
+
|
595 |
+
#: admin/settings/view-profiles.php:92
|
596 |
+
msgid "Add New Profile"
|
597 |
+
msgstr "Ajouter nouveau profil"
|
598 |
+
|
599 |
+
#: admin/settings/view-utilities.php:11
|
600 |
+
msgid "Disassociating content..."
|
601 |
+
msgstr "Dissocier le contenu..."
|
602 |
+
|
603 |
+
#: admin/settings/view-utilities.php:25 admin/settings.php:21
|
604 |
+
msgid "Utilities"
|
605 |
+
msgstr "Utilitaires"
|
606 |
+
|
607 |
+
#: admin/settings/view-utilities.php:26
|
608 |
+
msgid ""
|
609 |
+
"These utilities are designed to help you prepare and maintain your "
|
610 |
+
"multilingual content."
|
611 |
+
msgstr "Ces utilitaires sont conçus pour vous aider à préparer et conserver votre contenu multilingue."
|
612 |
+
|
613 |
+
#: admin/settings/view-utilities.php:28 admin/view-network.php:155
|
614 |
+
msgid "Language"
|
615 |
+
msgstr "Langue"
|
616 |
+
|
617 |
+
#: admin/settings/view-utilities.php:35
|
618 |
+
msgid ""
|
619 |
+
"Set <i>default language</i> as the language for all content that has not "
|
620 |
+
"been assigned a language."
|
621 |
+
msgstr "Définir la <i>langue par défaut</i> comme langue de tout le contenu qui n'a pas reçu une langue."
|
622 |
+
|
623 |
+
#: admin/settings/view-utilities.php:39
|
624 |
+
msgid "Disassociation"
|
625 |
+
msgstr "Dissociation"
|
626 |
+
|
627 |
+
#: admin/settings/view-utilities.php:45
|
628 |
+
msgid "Disassociate all the content from Lingotek TMS."
|
629 |
+
msgstr "Dissocier tout le contenu de Lingotek TMS."
|
630 |
+
|
631 |
+
#: admin/settings/view-utilities.php:55
|
632 |
+
msgid "Delete all documents in Lingotek TMS."
|
633 |
+
msgstr "Supprimez tous les documents de Lingotek TMS."
|
634 |
+
|
635 |
+
#: admin/settings/view-utilities.php:62
|
636 |
+
msgid ""
|
637 |
+
"You are about to disassociate all your content from Lingotek TMS. Are you "
|
638 |
+
"sure ?"
|
639 |
+
msgstr "Vous êtes sur le point de dissocier tous vos contenus de Lingotek TMS. Es-tu sûr?"
|
640 |
+
|
641 |
+
#: admin/settings/view-utilities.php:63
|
642 |
+
msgid ""
|
643 |
+
"You are about to disassociate all your content and delete all documents in "
|
644 |
+
"Lingotek TMS. Are you sure ?"
|
645 |
+
msgstr "Vous êtes sur le point de dissocier tous vos contenus et supprimer tous les documents de Lingotek TMS. Es-tu sûr?"
|
646 |
+
|
647 |
+
#: admin/settings/view-utilities.php:75
|
648 |
+
msgid "Run Utilities"
|
649 |
+
msgstr "Exécutez les utilitaires"
|
650 |
+
|
651 |
+
#: admin/strings-table.php:99
|
652 |
+
msgid "Group"
|
653 |
+
msgstr "Groupe"
|
654 |
+
|
655 |
+
#: admin/strings-table.php:100
|
656 |
+
msgid "Count"
|
657 |
+
msgstr "Comte"
|
658 |
+
|
659 |
+
#: admin/tutorial/content.php:25
|
660 |
+
msgid "1. Create content"
|
661 |
+
msgstr "1. créer un contenu"
|
662 |
+
|
663 |
+
#: admin/tutorial/content.php:26
|
664 |
+
msgid ""
|
665 |
+
"Whether you write a blog post, create a page for your site, or have existing "
|
666 |
+
"posts and pages, any of your Wordpress content can be uploaded to "
|
667 |
+
"<i>Lingotek</i>."
|
668 |
+
msgstr "Que vous écrivez un blog, créez une page pour votre site ou avez des pages et des postes existants, une partie de votre contenu de Wordpress peut être téléchargée sur <i>Lingotek</i>."
|
669 |
+
|
670 |
+
#: admin/tutorial/content.php:27
|
671 |
+
msgid ""
|
672 |
+
"The examples shown below are for Pages but translation for other content "
|
673 |
+
"types works the same way!"
|
674 |
+
msgstr "Les exemples ci-dessous sont pour les Pages mais la traduction pour les autres types de contenu fonctionne de la même manière !"
|
675 |
+
|
676 |
+
#: admin/tutorial/content.php:29
|
677 |
+
msgid "Create a new page for translation."
|
678 |
+
msgstr "Créez une nouvelle page pour la traduction."
|
679 |
+
|
680 |
+
#: admin/tutorial/content.php:32
|
681 |
+
msgid "2. Upload content to Lingotek"
|
682 |
+
msgstr "2. Télécharger du contenu à Lingotek"
|
683 |
+
|
684 |
+
#: admin/tutorial/content.php:33
|
685 |
+
msgid ""
|
686 |
+
"Your Wordpress content can be uploaded to <i>Lingotek</i> with the simple "
|
687 |
+
"push of a button."
|
688 |
+
msgstr "Le contenu de votre Wordpress peut être téléchargé vers <i>Lingotek</i> avec la simple pression d'un bouton."
|
689 |
+
|
690 |
+
#: admin/tutorial/content.php:35
|
691 |
+
msgid "Content has been created and is ready for upload to Lingotek."
|
692 |
+
msgstr "Contenu a été créé et est prêt pour le téléchargement de Lingotek."
|
693 |
+
|
694 |
+
#: admin/tutorial/content.php:38
|
695 |
+
msgid "3. Request translations for target languages"
|
696 |
+
msgstr "3. demander des traductions en langues cibles"
|
697 |
+
|
698 |
+
#: admin/tutorial/content.php:39
|
699 |
+
msgid ""
|
700 |
+
"Request translation for a specific language by clicking on the orange plus "
|
701 |
+
"icon, for all languages at once, or in bulk by using the <i>Bulk Actions</i> "
|
702 |
+
"dropdown."
|
703 |
+
msgstr "Demande de traduction pour une langue spécifique en cliquant sur l'icône, pour toutes les langues à la fois, ou en vrac, orange plus en utilisant le menu déroulant <i>Actions en vrac</i> ."
|
704 |
+
|
705 |
+
#: admin/tutorial/content.php:41
|
706 |
+
msgid "The source content is uploaded and ready for target languages."
|
707 |
+
msgstr "Le contenu source est téléchargé et prêt pour les langues cibles."
|
708 |
+
|
709 |
+
#: admin/tutorial/content.php:44
|
710 |
+
msgid "4. Translate your content"
|
711 |
+
msgstr "4. traduire votre contenu"
|
712 |
+
|
713 |
+
#: admin/tutorial/content.php:45
|
714 |
+
msgid ""
|
715 |
+
"Your content will now be translated into your selected target languages by "
|
716 |
+
"free machine translation or, if you contract with <i>Lingotek</i>, "
|
717 |
+
"professional translation services."
|
718 |
+
msgstr "Votre contenu sera maintenant traduit dans vos langues cibles sélectionnés par traduction machine libre ou, si vous contractez avec <i>Lingotek</i>, services de traduction professionnels."
|
719 |
+
|
720 |
+
#: admin/tutorial/content.php:47
|
721 |
+
msgid "Your translations are underway."
|
722 |
+
msgstr "Vos traductions sont en cours."
|
723 |
+
|
724 |
+
#: admin/tutorial/content.php:50
|
725 |
+
msgid "5. Download translations"
|
726 |
+
msgstr "5. Télécharger les traductions"
|
727 |
+
|
728 |
+
#: admin/tutorial/content.php:51
|
729 |
+
msgid ""
|
730 |
+
"Once your translations are complete they will be marked ready for download. "
|
731 |
+
"You can download translations for all languages, each language individually, "
|
732 |
+
"or in bulk (using the <i>Bulk Actions</i> dropdown)."
|
733 |
+
msgstr "Une fois que vos traductions sont faites elles seront marquées prêts pour le téléchargement. Vous pouvez télécharger les traductions en toutes langues, chaque langue, en bloc ou individuellement (en utilisant le menu déroulant <i>Actions en vrac</i> )."
|
734 |
+
|
735 |
+
#: admin/tutorial/content.php:53
|
736 |
+
msgid "Your translations are ready for download."
|
737 |
+
msgstr "Vos traductions sont prêtes pour le téléchargement."
|
738 |
+
|
739 |
+
#: admin/tutorial/content.php:56
|
740 |
+
msgid "6. Your content is translated!"
|
741 |
+
msgstr "6. votre contenu est traduit !"
|
742 |
+
|
743 |
+
#: admin/tutorial/content.php:57
|
744 |
+
msgid ""
|
745 |
+
"The orange pencil icons indicate that your translations are finished, "
|
746 |
+
"downloaded, and current within your Wordpress site. Clicking on any one of "
|
747 |
+
"the pencils will direct you to the Lingotek Workbench for that specific "
|
748 |
+
"language. Here you can make updates and changes to your translations if "
|
749 |
+
"necessary."
|
750 |
+
msgstr "Les icônes de crayon orange indiquent que vos traductions sont finis, téléchargé et actuelle au sein de votre site Wordpress. En cliquant sur l'un des crayons vous dirigera vers le Workbench de Lingotek pour la langue en question. Ici vous pouvez faire des mises à jour et modifications à vos traductions si nécessaire."
|
751 |
+
|
752 |
+
#: admin/tutorial/content.php:59
|
753 |
+
msgid "Your content has been translated."
|
754 |
+
msgstr "Votre contenu a été traduit."
|
755 |
+
|
756 |
+
#: admin/tutorial/content.php:62
|
757 |
+
msgid "What do all the icons mean?"
|
758 |
+
msgstr "Que signifient toutes les icônes ?"
|
759 |
+
|
760 |
+
#: admin/tutorial/content.php:67
|
761 |
+
msgid "Upload Source"
|
762 |
+
msgstr "Télécharger la Source"
|
763 |
+
|
764 |
+
#: admin/tutorial/content.php:68
|
765 |
+
msgid "There is content ready to be uploaded to Lingotek."
|
766 |
+
msgstr "Il y a contenu prêt à être transféré à Lingotek."
|
767 |
+
|
768 |
+
#: admin/tutorial/content.php:73
|
769 |
+
msgid ""
|
770 |
+
"Content is importing to Lingotek or a target language is being added to "
|
771 |
+
"source content."
|
772 |
+
msgstr "Contenu consiste à importer de Lingotek ou un langage cible est ajouté au contenu source."
|
773 |
+
|
774 |
+
#: admin/tutorial/content.php:77
|
775 |
+
msgid "Source Uploaded"
|
776 |
+
msgstr "Source téléchargée"
|
777 |
+
|
778 |
+
#: admin/tutorial/content.php:78
|
779 |
+
msgid "The source content has been uploaded to Lingotek."
|
780 |
+
msgstr "Le contenu de la source a été téléchargé à Lingotek."
|
781 |
+
|
782 |
+
#: admin/tutorial/content.php:82
|
783 |
+
msgid "Request Translation"
|
784 |
+
msgstr "Demande de traduction"
|
785 |
+
|
786 |
+
#: admin/tutorial/content.php:83
|
787 |
+
msgid "Request a translation of the source content. (Add a target language)"
|
788 |
+
msgstr "Demander une traduction du contenu source. (Ajouter une langue cible)"
|
789 |
+
|
790 |
+
#: admin/tutorial/content.php:87
|
791 |
+
msgid "Download Translation"
|
792 |
+
msgstr "Télécharger Translation"
|
793 |
+
|
794 |
+
#: admin/tutorial/content.php:88
|
795 |
+
msgid "Download the translated content to Wordpress."
|
796 |
+
msgstr "Télécharger le contenu traduit pour Wordpress."
|
797 |
+
|
798 |
+
#: admin/tutorial/content.php:92
|
799 |
+
msgid "Translation Current"
|
800 |
+
msgstr "Traduction actuelle"
|
801 |
+
|
802 |
+
#: admin/tutorial/content.php:93
|
803 |
+
msgid ""
|
804 |
+
"The translation is complete. (Clicking on this icon will allow you to edit "
|
805 |
+
"translations in the Lingotek Workbench)"
|
806 |
+
msgstr "La traduction est terminée. (En cliquant sur cette icône vous permet d'éditer les traductions dans l'établi Lingotek)"
|
807 |
+
|
808 |
+
#: admin/tutorial/credits.php:45
|
809 |
+
msgid "The Lingotek plugin for WordPress is created with love."
|
810 |
+
msgstr "Le plugin de Lingotek pour WordPress est créé avec amour."
|
811 |
+
|
812 |
+
#: admin/tutorial/credits.php:47
|
813 |
+
msgid "Team"
|
814 |
+
msgstr "Équipe"
|
815 |
+
|
816 |
+
#: admin/tutorial/faq.php:10
|
817 |
+
msgid "Questions and answers..."
|
818 |
+
msgstr "Questions et réponses..."
|
819 |
+
|
820 |
+
#: admin/tutorial/faq.php:12
|
821 |
+
msgid "How does this really work?"
|
822 |
+
msgstr "Comment ça marche vraiment ?"
|
823 |
+
|
824 |
+
#: admin/tutorial/faq.php:13
|
825 |
+
msgid ""
|
826 |
+
"<i>Polylang</i> puts in the framework to make WordPress multilingual and "
|
827 |
+
"<i>Lingotek</i> leverages that framework to provide localization through "
|
828 |
+
"machine translation and professional translation services."
|
829 |
+
msgstr "<i>Polylang</i> place dans le cadre de faire WordPress multilingue et <i>Lingotek</i> s'appuie sur ce cadre afin de fournir une localisation à travers la traduction automatique et de services de traduction professionnels."
|
830 |
+
|
831 |
+
#: admin/tutorial/faq.php:15
|
832 |
+
msgid "What does the Lingotek plugin do?"
|
833 |
+
msgstr "Que signifie le Lingotek plugin faire ?"
|
834 |
+
|
835 |
+
#: admin/tutorial/faq.php:16
|
836 |
+
msgid ""
|
837 |
+
"<i>Lingotek</i> has teamed up with <i>Polylang</i> to offer a simple way to "
|
838 |
+
"make your WordPress site truly multilingual. Manage all your multilingual "
|
839 |
+
"content in the same site. No need to have a different site for each language!"
|
840 |
+
msgstr "<i>Lingotek</i> collabore avec <i>Polylang</i> pour offrir un moyen simple de rendre votre site WordPress multilingue. Gérer tous vos contenus multilingues dans le même site. Pas besoin d'avoir un site différent pour chaque langue !"
|
841 |
+
|
842 |
+
#: admin/tutorial/faq.php:18
|
843 |
+
msgid "How can I add a language?"
|
844 |
+
msgstr "Comment puis-je ajouter une langue ?"
|
845 |
+
|
846 |
+
#: admin/tutorial/faq.php:19
|
847 |
+
msgid ""
|
848 |
+
"On the <i>translation dashboard</i>, click on the <i>Translate my site "
|
849 |
+
"into...</i> textbox and choose from the list or start typing to quickly find "
|
850 |
+
"a language."
|
851 |
+
msgstr "Sur le <i>tableau de bord de traduction</i>, cliquez sur la zone de texte de <i>mon site dans la traduction...</i> et choisissez dans la liste ou commencez à taper pour trouver rapidement une langue."
|
852 |
+
|
853 |
+
#: admin/tutorial/faq.php:21
|
854 |
+
msgid "How can I remove a language?"
|
855 |
+
msgstr "Comment puis-je supprimer une langue ?"
|
856 |
+
|
857 |
+
#: admin/tutorial/faq.php:23
|
858 |
+
msgid ""
|
859 |
+
"On the <i>translation dashboard</i>, click on the blue check mark for the "
|
860 |
+
"language you would like to remove."
|
861 |
+
msgstr "Sur le <i>tableau de bord de traduction</i>, cliquez sur la coche bleue pour la langue que vous souhaitez supprimer."
|
862 |
+
|
863 |
+
#: admin/tutorial/faq.php:24
|
864 |
+
msgid ""
|
865 |
+
"Note: If you have translated content in a language you will not be able to "
|
866 |
+
"remove that language until that content has been deleted."
|
867 |
+
msgstr "Remarque : Si vous avez traduit le contenu dans une langue vous ne serez pas en mesure de supprimer cette langue jusqu'à ce que le contenu a été supprimé."
|
868 |
+
|
869 |
+
#: admin/tutorial/faq.php:27
|
870 |
+
msgid "Can I use my own translation agency with Lingotek?"
|
871 |
+
msgstr "Puis-je utiliser ma propre agence de traduction avec Lingotek ?"
|
872 |
+
|
873 |
+
#: admin/tutorial/faq.php:28 admin/tutorial/features.php:37
|
874 |
+
msgid ""
|
875 |
+
"Use your own translation agency or tap into Lingotek's network of more than "
|
876 |
+
"5,000+ in-country translators. Content transfer is fully automated between "
|
877 |
+
"WordPress and Lingotek. You'll have full visibility into the translation "
|
878 |
+
"process every step of the way. And once the translations are completed, "
|
879 |
+
"they'll automatically download and publish to your website according to the "
|
880 |
+
"preferences you've set."
|
881 |
+
msgstr "Utilisez votre propre agence de traduction ou puiser dans réseau de Lingotek de plus de 5 000 + traducteurs dans le pays. Transfert de contenu est entièrement automatisé entre WordPress et Lingotek. Vous aurez une visibilité complète sur la traduction traiter chaque étape de la voie. Et une fois que les traductions sont terminées, ils vont automatiquement télécharger et publier sur votre site Web selon les préférences que vous avez défini."
|
882 |
+
|
883 |
+
#: admin/tutorial/faq.php:30
|
884 |
+
msgid "How can I check the overall translation progress of my site?"
|
885 |
+
msgstr "Comment puis-je vérifier la progression globale de la traduction de mon site ?"
|
886 |
+
|
887 |
+
#: admin/tutorial/faq.php:31
|
888 |
+
msgid ""
|
889 |
+
"On the <i>translation dashboard</i>, the bars under <i>Completed Percentage</"
|
890 |
+
"i> show the translation progress of content for each language. You can "
|
891 |
+
"filter by content type or show progress for all content."
|
892 |
+
msgstr "Sur le <i>tableau de bord de translation</i>, les barres sous le <i>Pourcentage achevé</i> affichant l'avancement de la traduction de contenu pour chaque langue. Vous pouvez filtrer par type de contenu ou afficher la progression de tout le contenu."
|
893 |
+
|
894 |
+
#: admin/tutorial/faq.php:34
|
895 |
+
msgid "Why are there two different shades of blue in the progress bar?"
|
896 |
+
msgstr "Pourquoi y a-t-il deux différentes nuances de bleu dans la barre de progression ?"
|
897 |
+
|
898 |
+
#: admin/tutorial/faq.php:35
|
899 |
+
msgid ""
|
900 |
+
"The <i>translation dashboard</i> not only shows how much of your content is "
|
901 |
+
"translated, but also indicates the language that your source content was "
|
902 |
+
"authored in."
|
903 |
+
msgstr "Le <i>tableau de bord traduction</i> montre non seulement combien de votre contenu est traduit, mais il indique également la langue votre contenu source créé dans."
|
904 |
+
|
905 |
+
#: admin/tutorial/faq.php:38
|
906 |
+
msgid ""
|
907 |
+
"<i>Dark Blue:</i> Indicates that this is a source language that the content "
|
908 |
+
"was authored in."
|
909 |
+
msgstr "<i>Bleu foncé :</i> Indique qu'il s'agit d'une langue source le contenu créé dans."
|
910 |
+
|
911 |
+
#: admin/tutorial/faq.php:39
|
912 |
+
msgid ""
|
913 |
+
"<i>Light Blue:</i> Indicates that this is a target language that the content "
|
914 |
+
"was translated into."
|
915 |
+
msgstr "<i>Bleu clair :</i> Indique qu'il s'agit d'une langue cible que le contenu a été traduit en."
|
916 |
+
|
917 |
+
#: admin/tutorial/faq.php:43
|
918 |
+
msgid "What happens when I <i>Disassociate Translations</i>?"
|
919 |
+
msgstr "Que se passe-t-il lorsque je <i>Dissocier les traductions</i>?"
|
920 |
+
|
921 |
+
#: admin/tutorial/faq.php:44
|
922 |
+
msgid ""
|
923 |
+
"When content is disassociated the connection between WordPress and "
|
924 |
+
"<i>Lingotek</i> safely disconnected from Lingotek, so that translations can "
|
925 |
+
"be solely managed inside of WordPress."
|
926 |
+
msgstr "Lorsque le contenu est dissocié la connexion entre WordPress et <i>Lingotek</i> déconnecté en toute sécurité de Lingotek, afin que les traductions peuvent être gérées exclusivement à l'intérieur de WordPress."
|
927 |
+
|
928 |
+
#: admin/tutorial/faq.php:46
|
929 |
+
msgid ""
|
930 |
+
"How do I translate strings within widgets or general WordPress settings (e."
|
931 |
+
"g., Site Title, Tagline)?"
|
932 |
+
msgstr "Comment traduire les chaînes dans les gadgets ou les paramètres généraux de WordPress (Site titre, slogan) ?"
|
933 |
+
|
934 |
+
#: admin/tutorial/faq.php:47
|
935 |
+
msgid ""
|
936 |
+
"Groups of strings can be sent for translation and managed using the <a "
|
937 |
+
"href='%s'>String Groups</a> page. Individual strings may be viewed on the <a "
|
938 |
+
"href='%s'>Strings</a> page."
|
939 |
+
msgstr "Groupes de chaînes peuvent être envoyés pour traduction et gérés à l'aide de la page <a href='%s'>Groupes de chaîne</a> . Chaînes individuelles peuvent être consultés sur la page <a href='%s'>chaînes</a> ."
|
940 |
+
|
941 |
+
#: admin/tutorial/faq.php:53
|
942 |
+
msgid "Lingotek Workbench"
|
943 |
+
msgstr "Lingotek Workbench"
|
944 |
+
|
945 |
+
#: admin/tutorial/faq.php:54
|
946 |
+
msgid ""
|
947 |
+
"Lingotek Translation is the only WordPress plugin to integrate a Translation "
|
948 |
+
"Management System directly into WordPress, thus allowing the WordPress "
|
949 |
+
"community to use professional-grade translation technologies (e.g. machine "
|
950 |
+
"translation, translation memory, CAT tool) without ever having to leave the "
|
951 |
+
"comfort of the WordPress environment."
|
952 |
+
msgstr "Traduction de Lingotek est le seul plugin WordPress pour intégrer un système de gestion de traduction directement dans WordPress, permettant ainsi à la communauté WordPress d'utiliser les technologies de traduction de qualité professionnelle (p. ex., traduction automatique, mémoire de traduction, outil de TAO) sans jamais avoir à quitter le confort de l'environnement WordPress."
|
953 |
+
|
954 |
+
#: admin/tutorial/faq.php:59
|
955 |
+
msgid ""
|
956 |
+
"The <i>translation dashboard</i> allows you to view your site languages, add "
|
957 |
+
"and remove new languages, check the overall translation progress of your "
|
958 |
+
"site, see site analytics, and connect with Lingotek support."
|
959 |
+
msgstr "Le <i>tableau de bord de traduction</i> permet de voir votre site langues, ajouter et supprimer des nouvelles langues, vérifier la progression globale de traduction de votre site, voir analytique de site et se connecter avec l'aide Lingotek."
|
960 |
+
|
961 |
+
#: admin/tutorial/features.php:5
|
962 |
+
msgid "Translate into new languages"
|
963 |
+
msgstr "Traduire dans nouvelles langues"
|
964 |
+
|
965 |
+
#: admin/tutorial/features.php:6
|
966 |
+
msgid ""
|
967 |
+
"Easily translate your site into new languages by adding the desired language "
|
968 |
+
"to your site. Lingotek allows you to quickly add any of the most frequently "
|
969 |
+
"used locales using the <a href=\"%s\" title=\"Translation > Dashboard"
|
970 |
+
"\">Translation Dashboard</a>."
|
971 |
+
msgstr "Easily translate your site into new languages by adding the desired language to your site. Lingotek allows you to quickly add any of the most frequently used locales using the <a href=\"%s\" title=\"Translation > Dashboard\">Translation Dashboard</a>."
|
972 |
+
|
973 |
+
#: admin/tutorial/features.php:10
|
974 |
+
msgid "Automatically translate content"
|
975 |
+
msgstr "Traduire automatiquement le contenu"
|
976 |
+
|
977 |
+
#: admin/tutorial/features.php:11
|
978 |
+
msgid ""
|
979 |
+
"Machine translation is an excellent option if you're on a tight budget, "
|
980 |
+
"looking for near-instant results, and are okay with less-than-perfect "
|
981 |
+
"quality. The plugin allows you to quickly and automatically translate your "
|
982 |
+
"site (the cost is covered by Lingotek for up to 100,000 characters)."
|
983 |
+
msgstr "Traduction automatique est une excellente option si vous êtes sur un budget serré, vous cherchez des résultats quasi instantané et sont d'accord avec qualité de moins-que-parfait. Le plugin vous permet de rapidement et automatiquement traduire votre site (le coût est couvert par Lingotek pour jusqu'à 100 000 caractères)."
|
984 |
+
|
985 |
+
#: admin/tutorial/features.php:15
|
986 |
+
msgid "Fully compatible with Polylang"
|
987 |
+
msgstr "Entièrement compatible avec Polylang"
|
988 |
+
|
989 |
+
#: admin/tutorial/features.php:16
|
990 |
+
msgid ""
|
991 |
+
"Polylang and Lingotek work together seamlessly. Continue to use Polylang "
|
992 |
+
"for content that you want to translate inside WordPress, while sending other "
|
993 |
+
"content to be translated by Lingotek. The <b style=\"color: %s\">orange</b> "
|
994 |
+
"icons indicate Lingotek statuses/actions while the <b style=\"color: %s"
|
995 |
+
"\">blue</b> icons continue to represent Polylang actions."
|
996 |
+
msgstr "Polylang et Lingotek travaillent ensemble de façon transparente. Continuer à utiliser Polylang pour le contenu que vous souhaitez traduire à l'intérieur de WordPress, lors de l'envoi de tout autre contenu à traduire par Lingotek. Les icônes <b style=\"color: %s\">orange</b> indiquent Lingotek statuts/actions alors que les icônes <b style=\"color: %s\">bleues</b> continuent de représenter les actions de Polylang."
|
997 |
+
|
998 |
+
#: admin/tutorial/features.php:25
|
999 |
+
msgid "Use translation profiles"
|
1000 |
+
msgstr "Utilisation des profils de traduction"
|
1001 |
+
|
1002 |
+
#: admin/tutorial/features.php:26
|
1003 |
+
msgid ""
|
1004 |
+
"One of the most time-consuming activities of any multilingual web-site "
|
1005 |
+
"project is managing the ongoing flow of changes and additions to site "
|
1006 |
+
"content and configurations. Translation profiles were created to allow you "
|
1007 |
+
"to create and save and re-use your translation settings."
|
1008 |
+
msgstr "Une des activités plus fastidieuses de tout projet de site web multilingue gère le flux continu des changements et des ajouts au contenu du site et des configurations. Les profils de traduction ont été créés pour vous permettre de créer et d'enregistrer et de réutiliser vos paramètres de translation."
|
1009 |
+
|
1010 |
+
#: admin/tutorial/features.php:30
|
1011 |
+
msgid "Content type profiles"
|
1012 |
+
msgstr "Profils de type de contenu"
|
1013 |
+
|
1014 |
+
#: admin/tutorial/features.php:31
|
1015 |
+
msgid ""
|
1016 |
+
"Content type profiles. Manually choosing which content to upload and "
|
1017 |
+
"download is rarely what a content administrator wants to do, and automating "
|
1018 |
+
"the upload of every change is not workable because there are various types "
|
1019 |
+
"of content. Each type of translatable content can be assigned to a "
|
1020 |
+
"customizable profile. For example, by default, we like to have Posts use an "
|
1021 |
+
"<i>Automatic</i> profile so that content will automatically be uploaded for "
|
1022 |
+
"translation and the resulting translations automatically be downloaded back "
|
1023 |
+
"into WordPress."
|
1024 |
+
msgstr "Profils de type de contenu. Choisir manuellement quel contenu à télécharger est rarement ce qu'un administrateur de contenu veut faire, et automatiser le téléchargement de chaque changement n'est pas réalisable car il existe différents types de contenus. Chaque type de contenu traduisible peut être assignée à un profil personnalisable. Par exemple, par défaut, nous aimons avoir de messages utilisation profil un <i>automatique</i> afin que le contenu sera automatiquement téléchargé pour la traduction et les traductions qui en résulte automatiquement être téléchargé dans WordPress."
|
1025 |
+
|
1026 |
+
#: admin/tutorial/features.php:36
|
1027 |
+
msgid "Request professional translation"
|
1028 |
+
msgstr "Demande de traduction professionnelle"
|
1029 |
+
|
1030 |
+
#: admin/utilities.php:78
|
1031 |
+
msgid "The language update utility ran successfully."
|
1032 |
+
msgstr "L'utilitaire de mise à jour de langue a été correctement exécuté."
|
1033 |
+
|
1034 |
+
#: admin/view-network.php:78
|
1035 |
+
msgid "The language utility ran successfully."
|
1036 |
+
msgstr "L'utilité de la langue a été correctement exécuté."
|
1037 |
+
|
1038 |
+
#: admin/view-network.php:80
|
1039 |
+
msgid "Your chosen settings have updated successfully for all selected sites."
|
1040 |
+
msgstr "Vos paramètres choisis ont mis à jour avec succès pour tous les sites sélectionnés."
|
1041 |
+
|
1042 |
+
#: admin/view-network.php:83
|
1043 |
+
msgid "Please choose at least one destination site."
|
1044 |
+
msgstr "Veuillez choisir au moins un site de destination."
|
1045 |
+
|
1046 |
+
#: admin/view-network.php:95
|
1047 |
+
msgid "Your new projects were successfully created."
|
1048 |
+
msgstr "Vos nouveaux projets ont été créés avec succès."
|
1049 |
+
|
1050 |
+
#: admin/view-network.php:112
|
1051 |
+
msgid "Lingotek Network Settings"
|
1052 |
+
msgstr "Paramètres réseau de Lingotek"
|
1053 |
+
|
1054 |
+
#: admin/view-network.php:113
|
1055 |
+
msgid "Copy Lingotek settings from the source site to multiple sites"
|
1056 |
+
msgstr "Paramètres de Lingotek copie sur le site de la source à plusieurs sites"
|
1057 |
+
|
1058 |
+
#: admin/view-network.php:119
|
1059 |
+
msgid "Source Site"
|
1060 |
+
msgstr "Source Site"
|
1061 |
+
|
1062 |
+
#: admin/view-network.php:128
|
1063 |
+
msgid "Destination Site"
|
1064 |
+
msgstr "Site de destination"
|
1065 |
+
|
1066 |
+
#: admin/view-network.php:137
|
1067 |
+
msgid "Settings to copy"
|
1068 |
+
msgstr "Pour copier les paramètres"
|
1069 |
+
|
1070 |
+
#: admin/view-network.php:142
|
1071 |
+
msgid "Resources"
|
1072 |
+
msgstr "Ressources"
|
1073 |
+
|
1074 |
+
#: admin/view-network.php:143
|
1075 |
+
msgid "Profiles"
|
1076 |
+
msgstr "Profils"
|
1077 |
+
|
1078 |
+
#: admin/view-network.php:144
|
1079 |
+
msgid "Content Types"
|
1080 |
+
msgstr "Types de contenu"
|
1081 |
+
|
1082 |
+
#: admin/view-network.php:149
|
1083 |
+
msgid "New Project"
|
1084 |
+
msgstr "Nouveau projet"
|
1085 |
+
|
1086 |
+
#: admin/view-network.php:151
|
1087 |
+
msgid ""
|
1088 |
+
"Create a new project using the name of the selected site (Recommended for a "
|
1089 |
+
"newly created site)"
|
1090 |
+
msgstr "Créez un nouveau projet en utilisant le nom du site sélectionné (recommandé pour un site nouvellement créé)"
|
1091 |
+
|
1092 |
+
#: admin/view-network.php:157
|
1093 |
+
msgid ""
|
1094 |
+
"Set <i>default language</i> as the language for all existing content that "
|
1095 |
+
"has not been assigned a language."
|
1096 |
+
msgstr "Définir la <i>langue par défaut</i> comme langue pour tout le contenu existant qui n'a pas reçu une langue."
|
1097 |
+
|
1098 |
+
#: admin/view-network.php:163
|
1099 |
+
msgid "Update Options"
|
1100 |
+
msgstr "Options de mise à jour"
|
1101 |
+
|
1102 |
+
#: admin/view-tutorial.php:4
|
1103 |
+
msgid "Features"
|
1104 |
+
msgstr "Caractéristiques"
|
1105 |
+
|
1106 |
+
#: admin/view-tutorial.php:6
|
1107 |
+
msgid "FAQ"
|
1108 |
+
msgstr "FAQ"
|
1109 |
+
|
1110 |
+
#: admin/view-tutorial.php:7
|
1111 |
+
msgid "Credits"
|
1112 |
+
msgstr "Crédits"
|
1113 |
+
|
1114 |
+
#: admin/view-tutorial.php:15
|
1115 |
+
msgid "Welcome to Lingotek"
|
1116 |
+
msgstr "Bienvenue chez Lingotek"
|
1117 |
+
|
1118 |
+
#: admin/view-tutorial.php:17
|
1119 |
+
msgid ""
|
1120 |
+
"Thank you for updating! Lingotek offers convenient cloud-based localization "
|
1121 |
+
"and translation."
|
1122 |
+
msgstr "Je vous remercie pour la mise à jour ! Lingotek offre de traduction et localisation commode de nuage."
|
1123 |
+
|
1124 |
+
#: admin/view-tutorial.php:20
|
1125 |
+
msgid "Version %s"
|
1126 |
+
msgstr "Version %s"
|
1127 |
+
|
1128 |
+
#: include/dashboard.php:79
|
1129 |
+
msgid "You must keep at least one language."
|
1130 |
+
msgstr "Vous devez conserver au moins une langue."
|
1131 |
+
|
1132 |
+
#: include/dashboard.php:103
|
1133 |
+
msgid ""
|
1134 |
+
"The language can only be removed when no existing content is using it. If "
|
1135 |
+
"you would like to remove this language from the site, then first remove any "
|
1136 |
+
"content assigned to this language."
|
1137 |
+
msgstr "La langue peut être supprimée uniquement lorsque aucun contenu existant n'est de l'utiliser. Si vous souhaitez supprimer cette langue du site, puis désinstallez n'importe quel contenu assigné à cette langue."
|
1138 |
+
|
1139 |
+
#: include/group-post.php:46 include/group-post.php:52
|
1140 |
+
msgid "Title"
|
1141 |
+
msgstr "Titre"
|
1142 |
+
|
1143 |
+
#: include/group-post.php:47
|
1144 |
+
msgid "Caption"
|
1145 |
+
msgstr "Caption"
|
1146 |
+
|
1147 |
+
#: include/group-post.php:48
|
1148 |
+
msgid "Alternative Text"
|
1149 |
+
msgstr "Texte de remplacement"
|
1150 |
+
|
1151 |
+
#: include/group-post.php:49 include/group-term.php:47
|
1152 |
+
msgid "Description"
|
1153 |
+
msgstr "Description"
|
1154 |
+
|
1155 |
+
#: include/group-post.php:53 include/group-term.php:46
|
1156 |
+
msgid "Slug"
|
1157 |
+
msgstr "Limace"
|
1158 |
+
|
1159 |
+
#: include/group-post.php:54
|
1160 |
+
msgid "Content"
|
1161 |
+
msgstr "Contenu"
|
1162 |
+
|
1163 |
+
#: include/group-post.php:55
|
1164 |
+
msgid "Excerpt"
|
1165 |
+
msgstr "Extrait"
|
1166 |
+
|
1167 |
+
#: include/group-term.php:44
|
1168 |
+
msgid "Name"
|
1169 |
+
msgstr "Nom"
|
1170 |
+
|
1171 |
+
#: lingotek.php:356
|
1172 |
+
msgid ""
|
1173 |
+
"Lingotek Translation requires Polylang to work. Please install Polylang."
|
1174 |
+
msgstr "Lingotek Traduction exige Polylang de travailler. S'il vous plaît installer Polylang."
|
1175 |
+
|
1176 |
+
#: lingotek.php:369
|
1177 |
+
msgid ""
|
1178 |
+
"Lingotek Translation requires Polylang %s to work. Please upgrade Polylang."
|
1179 |
+
msgstr "Lingotek Traduction exige Polylang %s de travailler. Veuillez mettre à jour Polylang."
|
1180 |
+
|
1181 |
+
#. Plugin Name of the plugin/theme
|
1182 |
+
msgid "Lingotek Translation"
|
1183 |
+
msgstr "Lingotek Traduction"
|
1184 |
+
|
1185 |
+
#. Plugin URI of the plugin/theme
|
1186 |
+
msgid ""
|
1187 |
+
"http://lingotek.com/"
|
1188 |
+
"wordpress#utm_source=wpadmin&utm_medium=plugin&utm_campaign=wplingotektranslationplugin"
|
1189 |
+
msgstr "http://Lingotek.com/WordPress#utm_source=wpadmin&utm_medium=plugin&utm_campaign=wplingotektranslationplugin"
|
1190 |
+
|
1191 |
+
#. Description of the plugin/theme
|
1192 |
+
msgid ""
|
1193 |
+
"Provides a seamless integration to the Lingotek Translation Management "
|
1194 |
+
"System (TMS)."
|
1195 |
+
msgstr "Fournit une intégration transparente à la Lingotek Translation Management System (TMS)."
|
1196 |
+
|
1197 |
+
#. Author of the plugin/theme
|
1198 |
+
msgid "Lingotek and Frédéric Demarle"
|
1199 |
+
msgstr "Lingotek et Frédéric Demarle"
|
1200 |
+
|
1201 |
+
#. Author URI of the plugin/theme
|
1202 |
+
msgid "http://lingotek.com"
|
1203 |
+
msgstr "http://Lingotek.com"
|
lingotek.php
ADDED
@@ -0,0 +1,524 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Plugin name: Lingotek Translation
|
4 |
+
Plugin URI: http://lingotek.com/wordpress#utm_source=wpadmin&utm_medium=plugin&utm_campaign=wplingotektranslationplugin
|
5 |
+
Version: 1.0.0
|
6 |
+
Author: Lingotek and Frédéric Demarle
|
7 |
+
Author uri: http://lingotek.com
|
8 |
+
Description: Lingotek offers convenient cloud-based localization and translation.
|
9 |
+
Text Domain: wp-lingotek
|
10 |
+
Domain Path: /languages
|
11 |
+
GitHub Plugin URI: https://github.com/lingotek/wp-lingotek
|
12 |
+
*/
|
13 |
+
|
14 |
+
// don't access directly
|
15 |
+
if (!function_exists('add_action'))
|
16 |
+
exit();
|
17 |
+
|
18 |
+
define('LINGOTEK_VERSION', '1.0.0'); // plugin version (should match above meta)
|
19 |
+
define('LINGOTEK_MIN_PLL_VERSION', '1.7.4.2');
|
20 |
+
define('LINGOTEK_BASENAME', plugin_basename(__FILE__)); // plugin name as known by WP
|
21 |
+
define('LINGOTEK_PLUGIN_SLUG', 'wp-lingotek');// plugin slug (should match above meta: Text Domain)
|
22 |
+
define('LINGOTEK_DIR', dirname(__FILE__)); // our directory
|
23 |
+
define('LINGOTEK_INC', LINGOTEK_DIR . '/include');
|
24 |
+
define('LINGOTEK_ADMIN_INC', LINGOTEK_DIR . '/admin');
|
25 |
+
define('LINGOTEK_URL', plugins_url('', __FILE__));
|
26 |
+
|
27 |
+
class Lingotek {
|
28 |
+
public $model; // Lingotek model
|
29 |
+
public $callback;
|
30 |
+
|
31 |
+
// array to map Lingotek locales to WP locales
|
32 |
+
// map as 'WP locale' => 'Lingotek locale'
|
33 |
+
public static $lingotek_locales = array(
|
34 |
+
'af' => 'af-ZA', 'ak' => 'ak-GH', 'am' => 'am-ET', 'ar' => 'ar', 'as' => 'as-IN', 'az' => 'az-AZ',
|
35 |
+
'ba' => 'ba-RU', 'bel' => 'be-BY', 'bg_BG' => 'bg-BG', 'bn_BD' => 'bn-BD', 'bo' => 'bo-CN', 'bs_BA' => 'bs-BA',
|
36 |
+
'ca' => 'ca-ES', 'co' => 'co-FR', 'cs_CZ' => 'cs-CZ', 'cy' => 'cy-GB', 'da_DK' => 'da-DK', 'de_CH' => 'de-CH',
|
37 |
+
'de_DE' => 'de-DE', 'dv' => 'dv-MV', 'el' => 'el-GR', 'en_AU' => 'en-AU', 'en_CA' => 'en-CA', 'en_GB' => 'en-GB',
|
38 |
+
'en_US' => 'en-US', 'eo' => 'eo-FR', 'es_AR' => 'es-AR', 'es_CL' => 'es-CL', 'es_CO' => 'es-CO', 'es_ES' => 'es-ES',
|
39 |
+
'es_MX' => 'es-MX', 'es_PE' => 'es-PE', 'es_PR' => 'es-PR', 'es_VE' => 'es-VE', 'et' => 'et-EE', 'eu' => 'eu-ES',
|
40 |
+
'fa_IR' => 'fa-IR', 'fi' => 'fi-FI', 'fr_FR' => 'fr-FR', 'ga' => 'ga-IE', 'gd' => 'gd-GB', 'gl_ES' => 'gl-ES',
|
41 |
+
'gn' => 'gn-BO', 'haw_US' => 'haw-US', 'he_IL' => 'he-IL', 'hi_IN' => 'hi-IN', 'hr' => 'hr-HR', 'hu_HU' => 'hu-HU',
|
42 |
+
'hy' => 'hy-AM', 'id_ID' => 'id-ID', 'is_IS' => 'is-IS', 'it_IT' => 'it-IT', 'ja' => 'ja-JP', 'jv_ID' => 'jv-ID',
|
43 |
+
'ka_GE' => 'ka-GE', 'kin' => 'kin-RW', 'kk' => 'kk-KZ', 'kn' => 'kn-IN', 'ko_KR' => 'ko-KR', 'ky_KY' => 'ky-KG',
|
44 |
+
'lb_LU' => 'lb-LU', 'lo' => 'lo-LA', 'lt_LT' => 'lt-LT', 'lv' => 'lv-LV', 'mg_MG' => 'mg-MG', 'mk_MK' => 'mk-MK',
|
45 |
+
'ml_IN' => 'ml-IN', 'mn' => 'mn-MN', 'mr' => 'mr-IN', 'ms_MY' => 'ms-MY', 'my_MM' => 'my-MM', 'ne_NP' => 'ne-NP',
|
46 |
+
'nl_BE' => 'nl-BE', 'nl_NL' => 'nl-NL', 'nn_NO' => 'nn-NO', 'pa_IN' => 'pa-IN', 'pl_PL' => 'pl-PL', 'ps' => 'ps-AF',
|
47 |
+
'pt_BR' => 'pt-BR', 'pt_PT' => 'pt-PT', 'ro_RO' => 'ro-RO', 'ru_RU' => 'ru-RU', 'sa_IN' => 'sa-IN', 'sd_PK' => 'sd-PK',
|
48 |
+
'si_LK' => 'si-LK', 'sk_SK' => 'sk-SK', 'sl_SI' => 'sl-SI', 'so_SO' => 'so-SO', 'sq' => 'sq-SQ', 'sr_RS' => 'sr-CS',
|
49 |
+
'su_ID' => 'su-ID', 'sv_SE' => 'sv-SE', 'sw' => 'sw-TZ', 'ta_IN' => 'ta-IN', 'te' => 'te-IN', 'tg' => 'tg-TJ',
|
50 |
+
'th' => 'th-TH', 'tir' => 'ti-ER', 'tl' => 'tl-PH', 'tr_TR' => 'tr-TR', 'ug_CN' => 'ug-CN', 'uk' => 'uk-UA',
|
51 |
+
'ur' => 'ur-PK', 'uz_UZ' => 'uz-UZ', 'vi' => 'vi-VN', 'zh_CN' => 'zh-CN', 'zh_HK' => 'zh-HK', 'zh_TW' => 'zh-TW',
|
52 |
+
);
|
53 |
+
|
54 |
+
/**
|
55 |
+
*
|
56 |
+
* Unique identifier for your plugin.
|
57 |
+
*
|
58 |
+
*
|
59 |
+
* The variable name is used as the text domain when internationalizing strings
|
60 |
+
* of text. Its value should match the Text Domain file header in the main
|
61 |
+
* plugin file.
|
62 |
+
*
|
63 |
+
* @since 1.0.0
|
64 |
+
*
|
65 |
+
* @var string
|
66 |
+
*/
|
67 |
+
protected $plugin_slug = LINGOTEK_PLUGIN_SLUG;
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Instance of this class.
|
71 |
+
*
|
72 |
+
* @since 1.0.0
|
73 |
+
*
|
74 |
+
* @var object
|
75 |
+
*/
|
76 |
+
protected static $instance = null;
|
77 |
+
|
78 |
+
protected static $logging = FALSE;
|
79 |
+
|
80 |
+
/*
|
81 |
+
* constructor
|
82 |
+
*
|
83 |
+
* @since 0.1
|
84 |
+
*/
|
85 |
+
public function __construct() {
|
86 |
+
// manages plugin activation and deactivation
|
87 |
+
register_activation_hook( __FILE__, array(&$this, 'activate'));
|
88 |
+
register_deactivation_hook( __FILE__, array(&$this, 'deactivate'));
|
89 |
+
|
90 |
+
// stopping here if we are going to deactivate the plugin (avoids breaking rewrite rules)
|
91 |
+
if (isset($_GET['action'], $_GET['plugin']) && 'deactivate' == $_GET['action'] && plugin_basename(__FILE__) == $_GET['plugin'])
|
92 |
+
return;
|
93 |
+
|
94 |
+
// loads the admin side of Polylang for the dashboard
|
95 |
+
if (defined('DOING_AJAX') && DOING_AJAX && isset($_REQUEST['action']) && 'lingotek_language' == $_REQUEST['action']) {
|
96 |
+
define('PLL_AJAX_ON_FRONT', false);
|
97 |
+
add_filter('pll_model', create_function('$c', 'return "PLL_Admin_Model";'));
|
98 |
+
}
|
99 |
+
|
100 |
+
spl_autoload_register(array(&$this, 'autoload')); // autoload classes
|
101 |
+
|
102 |
+
// init
|
103 |
+
add_filter('pll_model', array(&$this, 'pll_model'));
|
104 |
+
add_action('init', array(&$this, 'init'));
|
105 |
+
add_action('admin_init', array(&$this, 'admin_init'));
|
106 |
+
|
107 |
+
// add Lingotek locale to languages
|
108 |
+
add_filter('pll_languages_list', array(&$this, 'pre_set_languages_list'));
|
109 |
+
|
110 |
+
// flag title
|
111 |
+
add_filter('pll_flag_title', array(&$this, 'pll_flag_title'), 10, 3);
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Return the plugin slug.
|
116 |
+
*
|
117 |
+
* @since 0.1
|
118 |
+
*
|
119 |
+
* @return Plugin slug variable.
|
120 |
+
*/
|
121 |
+
public function get_plugin_slug() {
|
122 |
+
return $this->plugin_slug;
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Return an instance of this class.
|
127 |
+
*
|
128 |
+
* @since 1.0.0
|
129 |
+
*
|
130 |
+
* @return object A single instance of this class.
|
131 |
+
*/
|
132 |
+
public static function get_instance() {
|
133 |
+
|
134 |
+
// If the single instance hasn't been set, set it now.
|
135 |
+
if ( null == self::$instance ) {
|
136 |
+
self::$instance = new self;
|
137 |
+
}
|
138 |
+
|
139 |
+
return self::$instance;
|
140 |
+
}
|
141 |
+
|
142 |
+
/*
|
143 |
+
* activation or deactivation for all blogs
|
144 |
+
* method taken from Polylang
|
145 |
+
*
|
146 |
+
* @since 0.1
|
147 |
+
*
|
148 |
+
* @param string $what either 'activate' or 'deactivate'
|
149 |
+
*/
|
150 |
+
protected function do_for_all_blogs($what) {
|
151 |
+
// network
|
152 |
+
if (is_multisite() && isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
|
153 |
+
global $wpdb;
|
154 |
+
|
155 |
+
foreach ($wpdb->get_col("SELECT blog_id FROM $wpdb->blogs") as $blog_id) {
|
156 |
+
switch_to_blog($blog_id);
|
157 |
+
$what == 'activate' ? $this->_activate() : $this->_deactivate();
|
158 |
+
}
|
159 |
+
restore_current_blog();
|
160 |
+
}
|
161 |
+
|
162 |
+
// single blog
|
163 |
+
else
|
164 |
+
$what == 'activate' ? $this->_activate() : $this->_deactivate();
|
165 |
+
}
|
166 |
+
|
167 |
+
/*
|
168 |
+
* plugin activation for multisite
|
169 |
+
*
|
170 |
+
* @since 0.1
|
171 |
+
*/
|
172 |
+
public function activate() {
|
173 |
+
$this->do_for_all_blogs('activate');
|
174 |
+
}
|
175 |
+
|
176 |
+
/*
|
177 |
+
* plugin activation
|
178 |
+
*
|
179 |
+
* @since 0.1
|
180 |
+
*/
|
181 |
+
protected function _activate() {
|
182 |
+
global $polylang;
|
183 |
+
|
184 |
+
if (isset($polylang)) {
|
185 |
+
$polylang->model->clean_languages_cache(); // to add lingotek_locale property
|
186 |
+
}
|
187 |
+
|
188 |
+
// default profiles
|
189 |
+
if (false === get_option('lingotek_profiles')) {
|
190 |
+
$profiles = array(
|
191 |
+
'automatic' => array(
|
192 |
+
'profile' => 'automatic',
|
193 |
+
'name' => __('Automatic', 'wp-lingotek'),
|
194 |
+
'upload' => 'automatic',
|
195 |
+
'download' => 'automatic'
|
196 |
+
),
|
197 |
+
'manual' => array(
|
198 |
+
'profile' => 'manual',
|
199 |
+
'name' => __('Manual', 'wp-lingotek'),
|
200 |
+
'upload' => 'manual',
|
201 |
+
'download' => 'manual'
|
202 |
+
),
|
203 |
+
'disabled' => array(
|
204 |
+
'profile' => 'disabled',
|
205 |
+
'name' => __('Disabled', 'wp-lingotek'),
|
206 |
+
),
|
207 |
+
);
|
208 |
+
update_option('lingotek_profiles', $profiles);
|
209 |
+
}
|
210 |
+
|
211 |
+
// for the end point for the Lingoteck callback in rewrite rules
|
212 |
+
// don't use flush_rewrite_rules at network activation. See #32471
|
213 |
+
delete_option('rewrite_rules');
|
214 |
+
}
|
215 |
+
|
216 |
+
/*
|
217 |
+
* provides localized version of the canned translation profiles
|
218 |
+
*
|
219 |
+
* @since 1.0
|
220 |
+
*
|
221 |
+
* @return array
|
222 |
+
*/
|
223 |
+
public static function get_profiles() {
|
224 |
+
$profiles = get_option('lingotek_profiles');
|
225 |
+
|
226 |
+
//localize canned profile names
|
227 |
+
foreach($profiles as $k=>$v){
|
228 |
+
if(in_array($k,array('automatic','manual','disabled'))){
|
229 |
+
$profile_name = $profiles[$k]['name'];
|
230 |
+
$profiles[$k]['name'] = __($profile_name,'wp-lingotek');// localize canned profile names
|
231 |
+
}
|
232 |
+
}
|
233 |
+
|
234 |
+
return $profiles;
|
235 |
+
}
|
236 |
+
|
237 |
+
/*
|
238 |
+
* plugin deactivation for multisite
|
239 |
+
*
|
240 |
+
* @since 0.1
|
241 |
+
*/
|
242 |
+
public function deactivate() {
|
243 |
+
$this->do_for_all_blogs('deactivate');
|
244 |
+
}
|
245 |
+
|
246 |
+
/*
|
247 |
+
* plugin deactivation
|
248 |
+
*
|
249 |
+
* @since 0.5
|
250 |
+
*/
|
251 |
+
protected function _deactivate() {
|
252 |
+
delete_option('rewrite_rules');
|
253 |
+
}
|
254 |
+
|
255 |
+
/*
|
256 |
+
* blog creation on multisite (to set default options)
|
257 |
+
*
|
258 |
+
* @since 0.1
|
259 |
+
*
|
260 |
+
* @param int $blog_id
|
261 |
+
*/
|
262 |
+
public function wpmu_new_blog($blog_id) {
|
263 |
+
switch_to_blog($blog_id);
|
264 |
+
$this->_activate();
|
265 |
+
restore_current_blog();
|
266 |
+
}
|
267 |
+
|
268 |
+
/*
|
269 |
+
* autoload classes
|
270 |
+
*
|
271 |
+
* @since 0.1
|
272 |
+
*
|
273 |
+
* @param string $class
|
274 |
+
*/
|
275 |
+
public function autoload($class) {
|
276 |
+
// not a Lingotek class
|
277 |
+
if (0 !== strncmp('Lingotek_', $class, 9))
|
278 |
+
return;
|
279 |
+
|
280 |
+
$class = str_replace('_', '-', strtolower(substr($class, 9)));
|
281 |
+
foreach (array(LINGOTEK_INC, LINGOTEK_ADMIN_INC) as $path) {
|
282 |
+
if (file_exists($file = "$path/$class.php")) {
|
283 |
+
require_once($file);
|
284 |
+
break;
|
285 |
+
}
|
286 |
+
}
|
287 |
+
}
|
288 |
+
|
289 |
+
/*
|
290 |
+
* set the Polylang model class to PLL_Admin_Model on Lingotek admin pages
|
291 |
+
*
|
292 |
+
* @since 0.2
|
293 |
+
*
|
294 |
+
* @param string $class
|
295 |
+
* @return string modified class 'PLL_Model' | 'PLL_Admin_Model'
|
296 |
+
*/
|
297 |
+
public function pll_model($class) {
|
298 |
+
if (PLL_ADMIN && isset($_GET['page']) && in_array($_GET['page'], array('wp-lingotek', 'wp-lingotek_manage', 'wp-lingotek_settings', 'wp-lingotek_network')))
|
299 |
+
return 'PLL_Admin_Model';
|
300 |
+
return $class;
|
301 |
+
}
|
302 |
+
|
303 |
+
/*
|
304 |
+
* setups Lingotek model and callback
|
305 |
+
* sets filters to call Lingotek child classes instead of Polylang classes
|
306 |
+
*
|
307 |
+
* @since 0.1
|
308 |
+
*
|
309 |
+
*/
|
310 |
+
public function init() {
|
311 |
+
if (!defined('POLYLANG_VERSION'))
|
312 |
+
return;
|
313 |
+
|
314 |
+
add_rewrite_rule( 'lingotek/?$', 'index.php?lingotek=1&$matches[1]', 'top' );
|
315 |
+
|
316 |
+
if (is_admin())
|
317 |
+
new Lingotek_Admin();
|
318 |
+
|
319 |
+
// admin side
|
320 |
+
if (PLL_ADMIN && !PLL_SETTINGS) {
|
321 |
+
$this->model = new Lingotek_Model();
|
322 |
+
|
323 |
+
// overrides Polylang classes
|
324 |
+
$classes = array('Filters_Post', 'Filters_Term', 'Filters_Media', 'Filters_Columns');
|
325 |
+
foreach ($classes as $class)
|
326 |
+
add_filter('pll_' . strtolower($class) , create_function('$v', "return 'Lingotek_$class';"));
|
327 |
+
|
328 |
+
// add actions to posts, media and terms list
|
329 |
+
// no need to load this if there is no language yet
|
330 |
+
if ($GLOBALS['polylang']->model->get_languages_list()) {
|
331 |
+
$this->post_actions = new Lingotek_Post_Actions();
|
332 |
+
$this->term_actions = new Lingotek_Term_Actions();
|
333 |
+
$this->string_actions = new Lingotek_String_actions();
|
334 |
+
}
|
335 |
+
|
336 |
+
$this->utilities = new Lingotek_Utilities();
|
337 |
+
}
|
338 |
+
|
339 |
+
// callback
|
340 |
+
elseif (!PLL_ADMIN && !PLL_AJAX_ON_FRONT) {
|
341 |
+
$GLOBALS['wp']->add_query_var('lingotek');
|
342 |
+
|
343 |
+
$this->model = new Lingotek_Model();
|
344 |
+
$this->callback = new Lingotek_Callback($this->model);
|
345 |
+
}
|
346 |
+
}
|
347 |
+
|
348 |
+
/*
|
349 |
+
* some init
|
350 |
+
*
|
351 |
+
* @since 0.1
|
352 |
+
*/
|
353 |
+
public function admin_init() {
|
354 |
+
// plugin i18n, only needed for backend
|
355 |
+
load_plugin_textdomain('wp-lingotek', false, basename(LINGOTEK_DIR).'/languages');
|
356 |
+
|
357 |
+
if (!defined('POLYLANG_VERSION'))
|
358 |
+
add_action('all_admin_notices', array(&$this, 'pll_inactive_notice'));
|
359 |
+
|
360 |
+
elseif (version_compare(POLYLANG_VERSION, LINGOTEK_MIN_PLL_VERSION, '<'))
|
361 |
+
add_action('all_admin_notices', array(&$this, 'pll_old_notice'));
|
362 |
+
|
363 |
+
elseif (isset($GLOBALS['polylang']) && !count($GLOBALS['polylang']->model->get_languages_list()))
|
364 |
+
self::create_first_language();
|
365 |
+
|
366 |
+
wp_enqueue_style('lingotek_admin', LINGOTEK_URL .'/css/admin.css', array(), LINGOTEK_VERSION);
|
367 |
+
}
|
368 |
+
|
369 |
+
/*
|
370 |
+
* displays a notice if Polylang is inactive
|
371 |
+
*
|
372 |
+
* @since 0.1
|
373 |
+
*/
|
374 |
+
public function pll_inactive_notice() {
|
375 |
+
printf(
|
376 |
+
'<div class="error"><p>%s</p></div>',
|
377 |
+
__('Lingotek Translation requires Polylang to work. Please install Polylang.', 'wp-lingotek')
|
378 |
+
);
|
379 |
+
}
|
380 |
+
|
381 |
+
/*
|
382 |
+
* displays a notice if Polylang is obsolete
|
383 |
+
*
|
384 |
+
* @since 0.1
|
385 |
+
*/
|
386 |
+
public function pll_old_notice() {
|
387 |
+
printf(
|
388 |
+
'<div class="error"><p>%s</p></div>',
|
389 |
+
sprintf(
|
390 |
+
__('Lingotek Translation requires Polylang %s to work. Please upgrade Polylang.', 'wp-lingotek'),
|
391 |
+
'<strong>' . LINGOTEK_MIN_PLL_VERSION . '</strong>'
|
392 |
+
)
|
393 |
+
);
|
394 |
+
}
|
395 |
+
|
396 |
+
/*
|
397 |
+
* creates at least on language to avoid breaking the Lingotek Dashboard
|
398 |
+
*
|
399 |
+
* @since 0.2
|
400 |
+
*/
|
401 |
+
static protected function create_first_language() {
|
402 |
+
global $polylang;
|
403 |
+
|
404 |
+
include(PLL_ADMIN_INC.'/languages.php');
|
405 |
+
$locale = get_locale();
|
406 |
+
|
407 |
+
// attempts to set the default language from the current locale
|
408 |
+
foreach ($languages as $lang) {
|
409 |
+
if (get_locale() == $lang[1])
|
410 |
+
$language = $lang;
|
411 |
+
}
|
412 |
+
|
413 |
+
// defaults to en_US
|
414 |
+
if (empty($language))
|
415 |
+
$language = array('en', 'en_US', 'English');
|
416 |
+
|
417 |
+
$pll_model = new PLL_Admin_Model($polylang->options); // need admin model
|
418 |
+
$pll_model->add_language(array(
|
419 |
+
'slug' => $language[0],
|
420 |
+
'locale' => $language[1],
|
421 |
+
'name' => $language[2],
|
422 |
+
'rtl' => isset($language[3]) ? 1 : 0,
|
423 |
+
'term_group' => 0
|
424 |
+
));
|
425 |
+
}
|
426 |
+
|
427 |
+
/*
|
428 |
+
* adds Lingotek locale to the PLL_Language objects
|
429 |
+
* uses the map otherwise uses a stupid fallback
|
430 |
+
*
|
431 |
+
* @since 0.1
|
432 |
+
*
|
433 |
+
* @param array $languages list of language objects
|
434 |
+
* @return array
|
435 |
+
*/
|
436 |
+
public function pre_set_languages_list($languages) {
|
437 |
+
foreach ($languages as $key => $language) {
|
438 |
+
if (is_object($language))
|
439 |
+
$languages[$key]->lingotek_locale = self::map_to_lingotek_locale($language->locale); // backward compatibility with Polylang < 1.7.3
|
440 |
+
else
|
441 |
+
$languages[$key]['lingotek_locale'] = self::map_to_lingotek_locale($language['locale']);
|
442 |
+
}
|
443 |
+
|
444 |
+
return $languages;
|
445 |
+
}
|
446 |
+
|
447 |
+
/*
|
448 |
+
* maps a Lingotek locale to a WordPress locale
|
449 |
+
*
|
450 |
+
* @since 0.3
|
451 |
+
*
|
452 |
+
* @param string $lingotek_locale Lingotek locale
|
453 |
+
* @return string WordPress locale
|
454 |
+
*/
|
455 |
+
public static function map_to_wp_locale($lingotek_locale) {
|
456 |
+
// look for the locale in the map (take care that Lingotek sends locales with either '_' or '-'
|
457 |
+
// if not found just replace '-' by '_'
|
458 |
+
$wp_locale = array_search(str_replace('_', '-', $lingotek_locale), self::$lingotek_locales);
|
459 |
+
return $wp_locale ? $wp_locale : str_replace('-', '_', $lingotek_locale);
|
460 |
+
}
|
461 |
+
|
462 |
+
/*
|
463 |
+
* maps a WordPres locale to a Lingotek locale
|
464 |
+
*
|
465 |
+
* @since 0.3
|
466 |
+
*
|
467 |
+
* @param string $wp_locale WordPress locale
|
468 |
+
* @return string Lingotek locale
|
469 |
+
*/
|
470 |
+
public static function map_to_lingotek_locale($wp_locale) {
|
471 |
+
// look for the locale in the map
|
472 |
+
// if not found just replace '_ 'by '-'
|
473 |
+
return isset(self::$lingotek_locales[$wp_locale]) ? self::$lingotek_locales[$wp_locale] : str_replace('_', '-', $wp_locale);
|
474 |
+
}
|
475 |
+
|
476 |
+
/*
|
477 |
+
* modifies the flag title to add the locale
|
478 |
+
*
|
479 |
+
* @since 0.3
|
480 |
+
*
|
481 |
+
* @param string $name language name
|
482 |
+
* @param string $slug language code
|
483 |
+
* @param string $locale language locale
|
484 |
+
* @return string
|
485 |
+
*/
|
486 |
+
public function pll_flag_title($name, $slug, $locale) {
|
487 |
+
return "$name ($locale)";
|
488 |
+
}
|
489 |
+
|
490 |
+
public static function log($data, $label = NULL) {
|
491 |
+
if (self::$logging) {
|
492 |
+
$log_string = "";
|
493 |
+
if (is_string($label))
|
494 |
+
$log_string .= $label . "\n";
|
495 |
+
if (is_string($data)) {
|
496 |
+
$log_string .= $data;
|
497 |
+
}
|
498 |
+
else {
|
499 |
+
$log_string .= print_r($data, TRUE);
|
500 |
+
}
|
501 |
+
error_log($log_string);
|
502 |
+
}
|
503 |
+
}
|
504 |
+
}
|
505 |
+
|
506 |
+
// Helpers - development functions
|
507 |
+
if (!function_exists('dc')) {
|
508 |
+
function dc($data, $label = NULL, $die = FALSE) {
|
509 |
+
echo '<pre style="background: #f3f3f3; color: #000">';
|
510 |
+
if (is_string($label))
|
511 |
+
echo '<h1>' . $label . '</h1>';
|
512 |
+
print_r($data);
|
513 |
+
echo '</pre>';
|
514 |
+
if ($die || (is_bool($label) && $label))
|
515 |
+
die();
|
516 |
+
}
|
517 |
+
}
|
518 |
+
if (!function_exists('dd')) {
|
519 |
+
function dd($data, $label = NULL, $die = FALSE) {
|
520 |
+
return dc($data, $label, TRUE);
|
521 |
+
}
|
522 |
+
}
|
523 |
+
|
524 |
+
$GLOBALS['wp_lingotek'] = Lingotek::get_instance();
|
readme.txt
ADDED
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== Lingotek Translation ===
|
2 |
+
Contributors: Chouby, msmith, erichie
|
3 |
+
Donate link: http://lingotek.com/
|
4 |
+
Tags: Lingotek, lingotek, multilingual, bilingual, translate, translation, language, multilanguage, international, localization
|
5 |
+
Requires at least: 3.8
|
6 |
+
Tested up to: 4.2
|
7 |
+
Stable tag: 1.0
|
8 |
+
License: GPLv2 or later
|
9 |
+
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
+
|
11 |
+
Lingotek Translation offers convenient cloud-based localization and translation solutions for your WordPress content.
|
12 |
+
|
13 |
+
== Description ==
|
14 |
+
|
15 |
+
Lingotek offers convenient cloud-based localization and translation.
|
16 |
+
|
17 |
+
Lingotek Translation simplifies the process of creating and maintaining your WordPress multilingual website. Features include machine, professional, and community translation solutions that ease the manual burden of launching in new markets while improving language consistency, cutting costs, and enabling you to deliver your brand to consumers abroad in the quickest and most effective way possible.
|
18 |
+
|
19 |
+
Make your WordPress website content truly multilingual. The power to translate is now inside WordPress!
|
20 |
+
|
21 |
+
= Customizable Translation Workflows =
|
22 |
+
|
23 |
+
WordPress administrators use Translation Profiles to categorize content by its relative value. You associate each content type with a Translation Profile, and the plugin carries out the appropriate workflow:
|
24 |
+
|
25 |
+
= Professional =
|
26 |
+
|
27 |
+
The plugin enables you to use your own translation agency or tap into Lingotek's marketplace of more than 5,000+ in-country translators. Don't have time to manage your own translation project? Let Lingotek take care of it for you. The plugin fully automates file transfer between Wordpress and Lingotek. You'll have full visibility into the translation process every step of the way. And once the translations are completed, they'll automatically download and publish to your website according to the preferences you've set.
|
28 |
+
|
29 |
+
= Community =
|
30 |
+
|
31 |
+
If you're looking to save money by avoiding professional translation, you can take the do-it-yourself approach and have your bilingual employees, partners and/or users perform translations right within Wordpress. The plugin integrates with and provides use of the Lingotek Workbench, a professional-grade text editor used for translating, reviewing, and post-editing multilingual content.
|
32 |
+
|
33 |
+
= Free Automatic =
|
34 |
+
|
35 |
+
Machine translation is an excellent option if you're on a tight budget, looking for near-instant results, and are okay with less-than-perfect quality. The plugin allows you to quickly and automatically translate your site by providing use of the commercial API for Microsoft Translator (the cost is covered by Lingotek for up to 100,000 words). Machine translations can be post-edited at any time using the Lingotek Workbench.
|
36 |
+
|
37 |
+
= Cloud-Based Translation Management System =
|
38 |
+
|
39 |
+
Need access to a enterprise level Translation Management System designed to work directly with Wordpress and other content management systems allowing you can get complete transparent access with all your translation projects? The cloud-based Lingotek Translation Management Systems helps your business access new markets and customers. Contact sales@lingotek.com for more information and pricing of these features.
|
40 |
+
|
41 |
+
= Benefits =
|
42 |
+
|
43 |
+
* Cost Savings
|
44 |
+
* Faster Translation Times
|
45 |
+
* Higher Quality
|
46 |
+
* Real-time Monitoring
|
47 |
+
* Eliminate the Copy/Paste Method of Translating
|
48 |
+
* Increased Involvement and Loyalty
|
49 |
+
* In-context Review
|
50 |
+
|
51 |
+
= Features =
|
52 |
+
|
53 |
+
Lingotek works in conjuction with the [Polylang](https://wordpress.org/plugins/polylang/) plugin (the plumbing to make WordPress multilingual ready) allowing you to create a bilingual or multilingual WordPress site. You write posts, pages, and create categories and post tags as usual, and then define the language for each of them.
|
54 |
+
|
55 |
+
* You can use as many languages as you want. RTL language scripts are supported. WordPress languages packs are automatically downloaded and updated.
|
56 |
+
* You can translate posts, pages, media, categories, post tags, menus, widgets...
|
57 |
+
* Custom post types, custom taxonomies, sticky posts and post formats, RSS feeds and all default WordPress widgets are supported.
|
58 |
+
* The language is either set by the content or by the language code in the url, or you can use one different subdomain or domain per language.
|
59 |
+
* Categories, post tags as well as some other metas are automatically copied when adding a new post or page translation.
|
60 |
+
* A customizable language switcher is provided as a widget or in the nav menu.
|
61 |
+
* The admin interface is of course multilingual too and each user can set the WordPress admin language in its profile.
|
62 |
+
|
63 |
+
= Credits =
|
64 |
+
|
65 |
+
Wherever third party code has been used, credit has been given in the code’s comments.
|
66 |
+
|
67 |
+
= Do you like Lingotek? =
|
68 |
+
|
69 |
+
Don't hesitate to [give your feedback](http://wordpress.org/support/view/plugin-reviews/lingotek#postform). It will help make the plugin better. Other [contributions](http://lingotek.wordpress.com/documentation/contribute/) (helping other users on the support forum) are welcome!
|
70 |
+
|
71 |
+
== Installation ==
|
72 |
+
|
73 |
+
1. Make sure you have [Polylang](https://wordpress.org/plugins/polylang/) installed as it provides the framework for the Lingotek plugin.
|
74 |
+
1. Upload the `wp-lingotek` folder to the `/wp-content/plugins/` directory.
|
75 |
+
1. Activate the Lingotek plugin through the 'Plugins' menu in Wordpress.
|
76 |
+
1. Create a Lingotek account by going to the `Translation` menu that appears in your admin menu.
|
77 |
+
|
78 |
+
== Frequently Asked Questions ==
|
79 |
+
|
80 |
+
Visit the [Lingotek documentation site](https://lingotek.atlassian.net/wiki/display/PDOC/WordPress)
|
81 |
+
|
82 |
+
== Screenshots ==
|
83 |
+
|
84 |
+
1. The translation dashboard allows you to view your site languages, add and remove new languages, check the overall translation progress of your site, and see site analytics.
|
85 |
+
2. Polylang and Lingotek work together seamlessly. Continue to use Polylang for content that you want to translate inside WordPress, while sending other content to be translated by Lingotek. The orange icons indicate Lingotek statuses/actions while the blue icons continue to represent Polylang actions.
|
86 |
+
3. Use translation profiles. One of the most time-consuming activities of any multilingual web-site project is managing the ongoing flow of changes and additions to site content and configurations. Translation profiles were created to allow you to create and save and re-use your translation settings.
|
87 |
+
4. Content type profiles. Manually choosing which content to upload and download is rarely what a content administrator wants to do, and automating the upload of every change is not workable because there are various types of content. Each type of translatable content can be assigned to a customizable profile. For example, by default, we like to have Posts use an Automatic profile so that content will automatically be uploaded for translation and the resulting translations automatically be downloaded back into WordPress.
|
88 |
+
|
89 |
+
== Changelog ==
|
90 |
+
|
91 |
+
= 1.0 (2015-06-22) =
|
92 |
+
|
93 |
+
* Released on June 22, 2015
|
94 |
+
|
95 |
+
== Upgrade Notice ==
|
96 |
+
|
97 |
+
= 1.0 =
|
98 |
+
The fully featured version is now released publicly. Upgrade!
|
uninstall.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
//if uninstall not called from WordPress exit
|
4 |
+
if (!defined('WP_UNINSTALL_PLUGIN'))
|
5 |
+
exit();
|
6 |
+
|
7 |
+
class Lingotek_Uninstall {
|
8 |
+
|
9 |
+
/*
|
10 |
+
* constructor: manages uninstall for multisite
|
11 |
+
*
|
12 |
+
* @since 0.1
|
13 |
+
*/
|
14 |
+
function __construct() {
|
15 |
+
global $wpdb;
|
16 |
+
|
17 |
+
// check if it is a multisite uninstall - if so, run the uninstall function for each blog id
|
18 |
+
if (is_multisite()) {
|
19 |
+
foreach ($wpdb->get_col("SELECT blog_id FROM $wpdb->blogs") as $blog_id) {
|
20 |
+
switch_to_blog($blog_id);
|
21 |
+
$this->uninstall();
|
22 |
+
}
|
23 |
+
restore_current_blog();
|
24 |
+
}
|
25 |
+
else
|
26 |
+
$this->uninstall();
|
27 |
+
}
|
28 |
+
|
29 |
+
/*
|
30 |
+
* removes ALL plugin options
|
31 |
+
* do not remove the data merged with Polylang data in translations groups
|
32 |
+
* these data are removed when uninstalling Polylang
|
33 |
+
*
|
34 |
+
* @since 0.1
|
35 |
+
*/
|
36 |
+
function uninstall() {
|
37 |
+
delete_option('lingotek_prefs');
|
38 |
+
delete_option('lingotek_content_type');
|
39 |
+
delete_option('lingotek_community');
|
40 |
+
delete_option('lingotek_defaults');
|
41 |
+
delete_option('lingotek_profiles');
|
42 |
+
delete_option('lingotek_token');
|
43 |
+
delete_option('lingotek_community_resources');
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
new Lingotek_Uninstall();
|