PluginProbe
Booking Calendar / 10.11.2
Booking Calendar v10.11.2
11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 10.11.2 10.11.3 All 202 releases
booking / core / wpbc-translation.php

wpbc-translation.php in Booking Calendar 10.11.2, at core/wpbc-translation.php

1,632 lines 62.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @version 1.0
4 * @package Booking Calendar
5 * @subpackage Translations Functions
6 * @category Functions
7 *
8 * @author wpdevelop
9 * @link https://wpbookingcalendar.com/
10 * @email info@wpbookingcalendar.com
11 *
12 * @modified 29.09.2015
13 */
14
15 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
16
17
18
19
20
21
22 /**
23 * Rechecking about the locale on this hook:
24 * add_action( 'plugins_loaded', 'wpbc_load_translation', 1000 );
25 * which is executed early then
26 * add_action( 'admin_init', 'wpbc_check_...' );
27 */
28 add_action( 'plugins_loaded', 'wpbc_load_translation', 1000 ); // Load translation
29
30
31 /**
32 * Load translation - Load country list after locale defined by some other translation plugin.
33 */
34 function wpbc_load_translation(){
35
36 //define( 'WPBC_LOCALE_RELOAD', 'fr_FR' ); wpbc_load_plugin_translation_file__mo( WPBC_LOCALE_RELOAD );
37
38
39 // Get reloaded 'booking' or current WordPress locale
40 $locale = wpbc_get_maybe_reloaded_booking_locale(); // if NOT defined WPBC_LOCALE_RELOAD define by current WordPress locale
41
42 // FixIn: 8.9.4.5.
43 if ( is_admin() && ( defined( 'DOING_AJAX' ) ) && ( DOING_AJAX ) ) {
44 //Reload locale for Ajax request
45 wpbc_check_ajax_locale__reload_it( $locale ); //
46 }
47
48 wpbc_load_country_list_file_php( $locale );
49
50 if ( ! wpbc_load_plugin_translation_file__mo( $locale ) ) {
51 wpbc_load_plugin_translation_file__mo( 'en_US' ); // Load default English translation, if other not available
52 }
53 }
54
55
56 /**
57 * Check ( $_REQUEST['wpdev_active_locale'] ) and Reload specific Locale for the Ajax request
58 */
59 function wpbc_check_ajax_locale__reload_it( $reloaded_locale ) { // FixIn: 8.4.5.1.
60
61 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
62 if ( ( isset( $_REQUEST['wpdev_active_locale'] ) ) || ( isset( $_REQUEST['wpbc_ajx_locale'] ) ) ) { // Reload locale according request parameter.
63
64 unload_textdomain( 'booking' );
65
66 /*
67 * Removed because, it's configured in $locale = wpbc_get_maybe_reloaded_booking_locale(); which is executed before this action
68 *
69 if ( ! defined( 'WPBC_LOCALE_RELOAD' ) ) { // $
70 define( 'WPBC_LOCALE_RELOAD', ( $_REQUEST['wpdev_active_locale'] ) );
71 }
72 */
73 add_filter( 'locale', 'wpbc_get_maybe_reloaded_booking_locale', 999 ); // Set filter to load the locale of the Booking Calendar
74
75 /**
76 * It's commented because inside of the function load_default_textdomain(); exist: unload_textdomain( 'default' ); which is unset( $l10n[ 'default' ] );
77 *
78 // Reload locale settings, it's required for the correct dates format
79 //if ( isset( $l10n['default'] ) ) { unset( $l10n['default'] ); } // Unload locale
80 */
81 load_default_textdomain(); // Load default locale
82
83 global $wp_locale;
84 $wp_locale = new WP_Locale(); // Reload class
85
86 wpbc_load_plugin_translation_file__mo( $reloaded_locale );
87
88
89 $current_locale = wpbc_get_current_wordpress_locale(); // 'en_US' or 'it_IT', etc...
90
91 if ( $current_locale != $reloaded_locale ) {
92
93 // The switch_to_locale() function is loaded before it can actually be used.
94 if ( function_exists( 'switch_to_locale' ) && isset( $GLOBALS['wp_locale_switcher'] ) ) {
95 $switched_locale = switch_to_locale( $reloaded_locale );
96 } else {
97 load_default_textdomain( $reloaded_locale );
98 }
99 }
100
101 }
102 }
103
104
105 /**
106 * Load MO translation file of plugin, like ../wp-content/plugins/booking/languages/booking-fr_FR.mo
107 *
108 * System firstly try to load MO from dir: ../wp-content/plugins/booking/languages
109 * then from: ../wp-content/languages/plugins/'
110 * otherwise: unload 'booking' textdomain
111 *
112 * @param string $locale default ''
113 *
114 * can be passed like: 'en_US' or 'it_IT'
115 *
116 * if '' then get WPBC_LOCALE_RELOAD locale,
117 * or if not reloaded then get current WordPress locale
118 * and define WPBC_LOCALE_RELOAD
119 *
120 * @return bool
121 */
122 function wpbc_load_plugin_translation_file__mo( $locale = '' ) {
123
124 $is_mo_loaded = false;
125 $domain = 'booking';
126
127 if ( empty( $locale ) ) {
128 $locale = wpbc_get_maybe_reloaded_booking_locale();
129 }
130
131
132 if ( ! empty( $locale ) ) {
133
134 $mofile_in_plugin_folder = WPBC_PLUGIN_DIR . '/languages/' . $domain . '-' . $locale . '.mo';
135
136 // we have long locale like en_US, get only 2 first letters, for general locale, like 'en'
137 $mofile_local_short = WPBC_PLUGIN_DIR . '/languages/' . $domain . '-' . substr( $locale, 0 , 2 ) . '.mo';
138
139 // Load from General folder /wp-content/languages/plugins/plugin-name-xx_XX.mo
140 $mofile_in_wp_folder = WP_LANG_DIR . '/plugins/' . $domain . '-' . $locale . '.mo'; //FixIn: 8.9.4.6 Fix '/languages/plugin/' to '/languages/plugins/ // FixIn: 8.7.7.1.
141
142
143 /**
144 * Try to load from the languages' directory first -> WP_LANG_DIR . '/plugins/' . $mofile
145 * If not possible, then from -> WP_PLUGIN_DIR . '/' . trim( $plugin_rel_path, '/' )
146 *
147 */
148 $is_load_from_wp_repository = get_bk_option( 'booking_translation_load_from' );
149 if ( ( empty( $is_load_from_wp_repository ) ) || ( 'wp.org' == $is_load_from_wp_repository ) ) {
150
151 /**
152 * This function 'load_plugin_textdomain' load firstly from the '/wp-content/languages/plugins/' directory
153 *
154 * load_plugin_textdomain( $domain, false, WPBC_PLUGIN_DIRNAME . '/languages' )
155 *
156 * --> ../wp-content/languages/plugins/booking-fr_FR.mo !!!!
157 *
158 * In case if need to load directly, then use:
159 *
160 * load_textdomain( $domain, WPBC_PLUGIN_DIR . '/languages/' . $domain . '-' . $locale . '.mo' );
161 */
162
163 $plugin_rel_path = WPBC_PLUGIN_DIRNAME . '/languages';
164 $is_mo_loaded = load_plugin_textdomain( $domain, false, $plugin_rel_path );
165 }
166
167
168 if ( ! $is_mo_loaded ) {
169
170 if ( file_exists( $mofile_in_plugin_folder ) ) {
171
172 /**
173 * Direct load from ../wp-content/plugins/booking/languages/booking-fr_FR.mo
174 */
175
176 $is_mo_loaded = load_textdomain( $domain, $mofile_in_plugin_folder ); // FixIn: 8.9.4.5.
177
178 } elseif ( ( ! empty( $mofile_local_short ) ) && ( file_exists( $mofile_local_short ) ) ) { // FixIn: 8.1.3.13.
179
180 /**
181 * Direct load of short " booking-en.mo " MO file
182 */
183
184 $is_mo_loaded = load_textdomain( $domain, $mofile_local_short );
185
186 } elseif ( file_exists( $mofile_in_wp_folder ) ) { // FixIn: 8.9.4.6.
187
188 /**
189 * Here possible to use
190 * return load_plugin_textdomain( $domain, false, $plugin_rel_path );
191 *
192 * which firstly try to load from the language directory: ../wp-content/languages/plugins/booking-fr_FR.mo !!!!
193 *
194 * like this: load_textdomain( $domain, WP_LANG_DIR . '/plugins/' . $mofile )
195 * and only after this try uses this: load_textdomain( $domain, WP_PLUGIN_DIR . '/' . trim( $plugin_rel_path, '/' ) . '/' . $mofile );
196 *
197 * so that's why we are using direct loadinf: load_textdomain( $domain, $mofile_in_wp_folder ) ../wp-content/languages/plugin/booking-fr_FR.mo
198 */
199
200 $is_mo_loaded = load_textdomain( $domain, $mofile_in_wp_folder );
201 } else { // FixIn: 7.2.1.21.
202
203 $is_unloaded = unload_textdomain( $domain );
204 }
205 }
206 }
207
208 return $is_mo_loaded;
209 }
210
211
212 /**
213 * Load Country List file depends on plugin 'booking' locale
214 *
215 * @string $locale '' || 'en_US' || 'it_IT'
216 */
217 function wpbc_load_country_list_file_php( $locale ){ // FixIn: 8.8.2.5.
218
219 if ( ! empty( $locale ) ) {
220 $locale_lang = strtolower( substr( $locale, 0, 2 ) );
221 $locale_country = strtolower( substr( $locale, 3 ) );
222
223 // FixIn: 8.9.4.12.
224 if ( ( $locale_lang !== 'en' ) && ( wpbc_is_file_exist( '/core/lang/wpdev-country-list-' . $locale . '.php' ) ) ) {
225 require_once WPBC_PLUGIN_DIR . '/core/lang/wpdev-country-list-' . $locale . '.php';
226 } else {
227 require_once WPBC_PLUGIN_DIR . '/core/lang/wpdev-country-list.php';
228 }
229 } else {
230 require_once WPBC_PLUGIN_DIR . '/core/lang/wpdev-country-list.php';
231 }
232
233 do_action( 'wpbc_country_list_loaded' ); // FixIn: 8.9.4.9.
234 }
235
236
237 /**
238 * Get maybe reloaded 'booking' locale ( WPBC_LOCALE_RELOAD ) and if not defined WPBC_LOCALE_RELOAD define it.
239 *
240 * @return string
241 */
242 function wpbc_get_maybe_reloaded_booking_locale() {
243
244 if ( ( is_admin() && ( defined( 'DOING_AJAX' ) ) && ( DOING_AJAX ) ) ) {
245 $is_ajax = true;
246 } else {
247 $is_ajax = false;
248 }
249
250
251 /**
252 * Check active locale in some other translation plugins, like Polylang (NOT in Ajax), etc...
253 */
254 if ( ! $is_ajax ) { // FixIn: 8.9.4.7.
255
256 // Exception for Polylang plugin. It will force loading locale of Polylang plugin.
257 if ( function_exists( 'pll_current_language' ) ) { // FixIn: 8.1.2.5.
258 if ( defined( 'POLYLANG_VERSION' ) ) { // FixIn: 8.8.3.16.
259 if (
260 ( version_compare( POLYLANG_VERSION, '2.6.5', '<' ) ) // FixIn: 8.7.1.3.
261 || ( version_compare( POLYLANG_VERSION, '2.7.1', '>' ) ) // FixIn: 8.7.7.11.
262 ) {
263 $locale = pll_current_language( 'locale' );
264 if ( ! empty( $locale ) ) { // FixIn: 8.7.7.11.
265 return $locale;
266 }
267 }
268 }
269 }
270 }
271
272 $wpbc_ajx_locale = false;
273 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
274 if ( isset( $_REQUEST['wpdev_active_locale'] ) ) {
275 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.NonceVerification.Recommended
276 $wpbc_ajx_locale = sanitize_text_field( $_REQUEST['wpdev_active_locale'] );
277 }
278 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
279 if ( isset( $_REQUEST['wpbc_ajx_locale'] ) ) {
280 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.NonceVerification.Recommended
281 $wpbc_ajx_locale = sanitize_text_field( $_REQUEST['wpbc_ajx_locale'] );
282 }
283
284 // Reload locale ONLY in AJAX, and if `isset $_REQUEST['wpdev_active_locale']
285 if (
286 ( ! defined( 'WPBC_LOCALE_RELOAD' ) )
287 && ( ! empty( $wpbc_ajx_locale ) )
288 ){
289 if (
290 ( $is_ajax )
291 || (
292 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
293 ( isset( $_REQUEST['wpbc_ajx_locale_reload'] ) ) && ( 'force' == $_REQUEST['wpbc_ajx_locale_reload'] )
294 )
295 ) { // Reload locale according request parameter
296 define( 'WPBC_LOCALE_RELOAD', $wpbc_ajx_locale );
297 }
298 }
299
300
301
302 // If not defined than get current WordPress locale and define
303 if ( ! defined( 'WPBC_LOCALE_RELOAD' ) ) { // FixIn: 7.2.1.21.
304
305 $locale = wpbc_get_current_wordpress_locale(); // 'en_US' or 'it_IT', etc...
306
307 define( 'WPBC_LOCALE_RELOAD', $locale );
308 }
309
310 return WPBC_LOCALE_RELOAD;
311 }
312
313
314 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
315 /// Support
316 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
317
318 /**
319 * Get current WordPress locale, it is not relative to the Booking Calendar
320 *
321 * @return string 'en_US'
322 */
323 function wpbc_get_current_wordpress_locale(){
324
325 if ( function_exists( 'determine_locale' ) ) { //FixIn: 8.7.5.1 // FixIn: 8.7.3.15.
326 $current_locale = determine_locale();
327 } else {
328 if ( function_exists( 'get_user_locale' ) ) {
329 $current_locale = is_admin() ? get_user_locale() : get_locale();
330 } else {
331 $current_locale = get_locale();
332 }
333 }
334
335 return $current_locale; // 'en_US'
336 }
337
338
339 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
340 /// Filters for Locale of Booking Calendar
341 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
342
343 /**
344 * Check locale of plugin, and if previously were defined WPBC_LOCALE_RELOAD, then return our WPBC_LOCALE_RELOAD locale
345 *
346 * @param $locale 'en_US'
347 * @param string $plugin_domain 'booking' - it's Booking Calendar plugin locale
348 *
349 * @return mixed|string 'it_IT'
350 */
351 function wpbc_filter_recheck_plugin_locale( $locale, $plugin_domain = '' ) { // FixIn: 8.4.4.2.
352
353 if (
354 ( 'booking' == $plugin_domain )
355 && ( defined( 'WPBC_LOCALE_RELOAD' ) )
356 ) {
357 return WPBC_LOCALE_RELOAD;
358 }
359
360 return $locale;
361 }
362 add_filter( 'plugin_locale', 'wpbc_filter_recheck_plugin_locale', 100, 2 ); // When load_plugin_textdomain() is run, its get default locale and not that, we reupdate - WPBC_LOCALE_RELOAD
363
364
365
366 /**
367 * Overload loading of plugin translation files from "wp-content/languages/plugins" -> "wp-content/plugins/plugin_name/languages"
368 *
369 * W:\home\beta\www/wp-content/languages/plugins/booking-it_IT.mo -> W:\home\beta\www\wp-content\plugins\booking/languages/booking-it_IT.mo
370 *
371 * @param string $mofile
372 * @param type $domain
373 * @return string
374 */
375 function wpbc_filter_load_custom_plugin_translation_file( $mofile, $domain ) {
376
377 if ( $domain == 'booking' ) {
378 $mofile = WPBC_PLUGIN_DIR . '/languages/' . basename( $mofile );
379 }
380 return $mofile;
381 }
382 //add_filter( 'load_textdomain_mofile', 'wpbc_filter_load_custom_plugin_translation_file' , 10, 2 );
383
384
385
386 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
387 /// Support functions for [lang=xx_XX] shortcode
388 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
389
390 /**
391 * Translate content. Check for language sections -- [lang=xx_XX] shortcode. // FixIn: 10.0.0.46.
392 *
393 * @param $content_orig
394 *
395 * @return string
396 */
397 function wpbc_lang( $content_orig ) {
398 return wpdev_check_for_active_language( $content_orig );
399 }
400
401
402 /**
403 * Check plugin text for active language section -- [lang=xx_XX] shortcode
404 *
405 * @param string $content_orig
406 * @return string
407 * Usage:
408 * $text = wpbc_lang( $text );
409 */
410 function wpdev_check_for_active_language( $content_orig ) {
411
412 $content = $content_orig;
413
414 $languages = array();
415 $content_ex = explode('[lang',$content);
416
417 foreach ( $content_ex as $value ) {
418
419 if ( '=' == substr( $value, 0, 1 ) ) {
420
421 $pos_s = strpos( $value, '=' );
422 $pos_f = strpos( $value, ']' );
423 $key = trim( substr( $value, ( $pos_s + 1 ), ( $pos_f - $pos_s - 1 ) ) );
424 $value_l = trim( substr( $value, $pos_f + 1 ) );
425 $languages[ $key ] = $value_l;
426
427 } else {
428 $languages['default'] = $value;
429 }
430 }
431
432 $locale = wpbc_get_maybe_reloaded_booking_locale(); // $locale = 'fr_FR';
433
434 if ( isset( $languages[ $locale ] ) ) {
435 $return_text = $languages[ $locale ];
436 } else {
437 $return_text = $languages['default'];
438 }
439
440 $return_text = wpbc_bk_check_qtranslate( $return_text, $locale );
441 $return_text = wpbc_check_wpml_tags( $return_text, $locale ); // FixIn: 5.4.5.8.
442
443 return $return_text;
444 }
445
446
447 /**
448 * Get help rows about configuration in_several languages with [lang=xx_XX] shortcode
449 *
450 * @return array - each item of array is text row for showing.
451 */
452 function wpbc_get_help_rows_about_config_in_several_languges() {
453
454 $field_options = array();
455 $field_options[] = '<strong>' . esc_html__('Configuration in several languages' ,'booking') . '</strong>';
456 /* translators: 1: ... */
457 $field_options[] = sprintf( __( '%1$s - start new translation section, where %2$s - locale of translation', 'booking' ),'<code>[lang=LOCALE]</code>','<code>LOCALE</code>');
458 /* translators: 1: ... */
459 $field_options[] = sprintf(__( 'Example #1: %s - start French translation section' ,'booking'),'<code>[lang=fr_FR]</code>');
460 /* translators: 1: ... */
461 $field_options[] = sprintf(__( 'Example #2: "%s" - English and French translation of some message' ,'booking'),'<code>Thank you for your booking.[lang=fr_FR]Je vous remercie de votre reservation.</code>');
462
463 return $field_options;
464 }
465
466
467 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
468 /// Support functions for Other Translation Plugins like WPML, qTranslate, etc...
469 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
470
471 /**
472 * Support function for WPML plugin
473 * Register and Translate everything in [wpml]Some Text to translate[/wpml] tags.
474 *
475 * @param string $text
476 * @param string $locale
477 *
478 * @return string
479 */
480 function wpbc_check_wpml_tags( $text, $locale='' ) { // FixIn: 5.4.5.8.
481
482 if ( $locale == '' ) {
483 $locale = wpbc_get_maybe_reloaded_booking_locale();
484 }
485 if ( strlen( $locale ) > 2 ) {
486 $locale = substr($locale, 0, 2 );
487 }
488
489 $is_tranlsation_exist_s = strpos( $text, '[wpml]' );
490 $is_tranlsation_exist_f = strpos( $text, '[/wpml]' );
491
492 if ( ( $is_tranlsation_exist_s !== false ) && ( $is_tranlsation_exist_f !== false ) ) {
493
494 $shortcode = 'wpml';
495
496 // Find anything between [wpml] and [/wpml] shortcodes. Magic here: [\s\S]*? - fit to any text
497 preg_match_all( '/\[' . $shortcode . '\]([\s\S]*?)\[\/' . $shortcode . '\]/i', $text, $wpml_translations, PREG_SET_ORDER );
498 //debuge( $wpml_translations );
499
500 foreach ( $wpml_translations as $translation ) {
501 $text_to_replace = $translation[0];
502 $translation_to_check = $translation[1];
503
504 if ( function_exists ( 'icl_register_string' ) ){
505
506 if ( false ) { // Depricated functions
507
508 // Help: https://wpml.org/documentation/support/translation-for-texts-by-other-plugins-and-themes/
509 icl_register_string('Booking Calendar', 'wpbc-' . tag_escape( $translation_to_check ) , $translation_to_check );
510
511 //TODO: Need to execurte this after deactivation of plugin or after updating of some option...
512 //icl_unregister_string ( 'Booking Calendar', 'wpbc-' . tag_escape( $translation_to_check ) );
513
514 if ( function_exists ( 'icl_translate' ) ){
515 $translation_to_check = icl_translate ( 'Booking Calendar', 'wpbc-' . tag_escape( $translation_to_check ) , $translation_to_check );
516 }
517
518 } else { // WPML Version: 3.2
519
520 // Help info: do_action( 'wpml_register_single_string', string $context, string $name, string $value )
521 // https://wpml.org/wpml-hook/wpml_register_string_for_translation/
522 do_action( 'wpml_register_single_string', 'Booking Calendar', 'wpbc-' . tag_escape( $translation_to_check ) , $translation_to_check );
523
524
525 // Help info: apply_filters( 'wpml_translate_single_string', string $original_value, string $context, string $name, string $$language_code )
526 // https://wpml.org/wpml-hook/wpml_translate_single_string/
527 //$translation_to_check = apply_filters( 'wpml_translate_single_string', $translation_to_check, 'Booking Calendar', 'wpbc-' . tag_escape( $translation_to_check ) );
528 $language_code = $locale;
529 $translation_to_check = apply_filters( 'wpml_translate_single_string', $translation_to_check, 'Booking Calendar', 'wpbc-' . tag_escape( $translation_to_check ), $language_code );
530
531 }
532 }
533 $text = str_replace( $text_to_replace, $translation_to_check, $text );
534 }
535 }
536
537 return $text;
538 }
539
540
541 /**
542 * Support function for qTranslate plugin
543 *
544 * @param $text
545 * @param string $locale
546 *
547 * @return false|mixed|string
548 */
549 function wpbc_bk_check_qtranslate( $text, $locale='' ){
550
551 if ($locale == '') {
552 $locale = wpbc_get_maybe_reloaded_booking_locale();
553 }
554 if (strlen($locale)>2) {
555 $locale = substr($locale, 0 ,2);
556 }
557
558 $is_tranlsation_exist = strpos($text, '<!--:'.$locale.'-->');
559
560 if ($is_tranlsation_exist !== false) {
561 $tranlsation_end = strpos($text, '<!--:-->', $is_tranlsation_exist);
562
563 $text = substr($text, $is_tranlsation_exist , ($tranlsation_end - $is_tranlsation_exist ) );
564 }
565
566 return $text;
567 }
568
569
570
571 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
572 // Translation Settings
573 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
574
575 /**
576 * Show translation buttons at Booking > Settings General page
577 */
578 function wpbc_translation_buttons_settings_section(){
579
580 if ( ( ! wpbc_is_this_demo() ) && ( current_user_can( 'activate_plugins' ) ) ){
581
582 ?><div class="wpbc_booking_system_info_buttons_align"><?php
583
584 echo
585 '<a class="button button tooltip_top"
586 data-original-title="'
587 /* translators: 1: ... */
588 . esc_attr( sprintf( __( 'Download translation PO files from %s and update the current translation version.', 'booking' ), 'wp.org / wpbookingcalendar.com' ) )
589 . '" href="'
590 . esc_url( wpbc_get_settings_url()
591 . '&system_info=show&_wpnonce='. wp_create_nonce( 'wpbc_settings_url_nonce' ) ) .'&update_translations=1#wpbc_general_settings_system_info_metabox">'
592 . esc_html__( 'Update Translations', 'booking' )
593 . '</a>';
594
595 echo '<a class="button button tooltip_top"
596 data-original-title="' . esc_attr( __( 'Show exist translations status', 'booking' ) ) . '"
597 href="' . esc_url( wpbc_get_settings_url() . '&system_info=show&_wpnonce=' . wp_create_nonce( 'wpbc_settings_url_nonce' ) ) . '&show_translation_status=1#wpbc_general_settings_system_info_metabox">' .
598 esc_html( __( 'Show translations status', 'booking' ) ) . '</a>';
599
600
601 if ( ( isset( $_SERVER['HTTP_HOST'] ) ) && ( 'beta' === $_SERVER['HTTP_HOST'] ) ) {
602
603 ?><div style="width:100%;height:2em;border-bottom:1px dashed #777;margin-bottom:1em;"></div><?php
604
605 // Link: http://server.com/wp-admin/admin.php?page=wpbc-settings&system_info=show&pot=1#wpbc_general_settings_system_info_metabox
606 echo
607 '<a class="button button-secondary tooltip_top"
608 data-original-title="Delete wpbc_all_translations(*).php files, before Updating POT file (manually)"
609 style="background:#fff9e6;" href="'
610 . esc_url( wpbc_get_settings_url()
611 . '&system_info=show&_wpnonce='. wp_create_nonce( 'wpbc_settings_url_nonce' ) ) .'&pot=erase__wpbc_all_translations#wpbc_general_settings_system_info_metabox">'
612 . '1. Erase Translation PHP files'
613 . '</a>';
614 echo
615 '<a class="button button-secondary tooltip_top"
616 data-original-title="Create or update wpbc_all_translations(*).php files, from actual POT file"
617 style="background:#fff9e6;"
618 href="'
619 . esc_url( wpbc_get_settings_url()
620 . '&system_info=show&_wpnonce='. wp_create_nonce( 'wpbc_settings_url_nonce' ) ) .'&pot=1#wpbc_general_settings_system_info_metabox">'
621 . '2. Generate Translation PHP from POT file'
622 . '</a>';
623
624 echo
625 '<a class="button button-secondary tooltip_top"
626 data-original-title="Just show WP.ORG translation status from ' . esc_attr( WP_LANG_DIR ) . '/plugins/' . ' "
627 style="background:#fff9e6;"
628 href="'
629 . esc_url( wpbc_get_settings_url()
630 . '&system_info=show&_wpnonce='. wp_create_nonce( 'wpbc_settings_url_nonce' ) ) .'&show_translation_status=2#wpbc_general_settings_system_info_metabox">'
631 . 'Translation status WP.ORG'
632 . '</a>';
633
634
635 echo
636 '<a class="button button-secondary tooltip_top"
637 data-original-title="Just show LOCAL translation status from ' . esc_attr( WPBC_PLUGIN_DIR ) . '/languages/' . ' "
638 style="background:#fff9e6;"
639 href="'
640 . esc_url( wpbc_get_settings_url()
641 . '&system_info=show&_wpnonce='. wp_create_nonce( 'wpbc_settings_url_nonce' ) ) .'&show_translation_status=3#wpbc_general_settings_system_info_metabox">'
642 . 'Translation status WPBC'
643 . '</a>';
644 }
645
646 ?></div><?php
647
648 }
649 }
650
651
652 // ======================================================================================================================
653 // Update Translations -- DOWNLOAD from WP.ORG and WPBC
654 // ======================================================================================================================
655
656
657 /**
658 * Update transaltions of plugin from WP repository
659 */
660 function wpbc_update_translations__from_wp() {
661
662 echo '<h2>' . esc_html__( 'Start updating translation files', 'booking' ) . '</h2>';
663 WPBC_Action_Scheduler_Compatibility::raise_memory_limit();
664 WPBC_Action_Scheduler_Compatibility::raise_time_limit( 300 );
665
666 $wpbc_download_result = false;
667 if ( 'translations_updated_from_wpbc' !== get_bk_option( 'booking_translation_update_status' ) ) {
668 $wpbc_download_result = wpbc_translation_download_from_wpbc();
669 }
670 if ( ( ! is_wp_error( $wpbc_download_result ) ) && ( false !== $wpbc_download_result ) ) {
671 update_bk_option( 'booking_translation_update_status', 'translations_updated_from_wpbc' );
672 }
673
674 $wp_org_translation_packages_arr = wpbc_get_translation_packages_arr_from_wp();
675 /**
676 * ..., array ( [language] => sk_SK
677 * [version] => 8.9.3
678 * [updated] => 2020-03-11 17:10:35
679 * [english_name] => Slovak
680 * [native_name] => Slovenčina
681 * [package] => https://downloads.wordpress.org/translation/plugin/booking/8.9.3/sk_SK.zip
682 * [iso] => Array ( [1] => sk, [2] => slk )
683 * ),
684 * ...
685 */
686
687 $download_result_arr = wpbc_transaltion_download_from_wp_org( $wp_org_translation_packages_arr );
688
689 echo '<h2>' . esc_html__( 'End updating translation files', 'booking' ) . '</h2>';
690 echo '<a class="button button-secondary" style="margin:10px 0;" href="' . esc_url( wpbc_get_settings_url() ) . '" >' . esc_html__( 'Go to Settings', 'booking' ) . '</a>';
691
692 update_bk_option( 'booking_translation_update_status', 'translations_updated_from_wpbc_and_wp' );
693 }
694
695
696 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
697 /// Support functions for Update Translations
698 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
699
700 /**
701 * Update translation option, just after activation of plugin.
702 * It must be 0
703 */
704 function wpbc_update_translation_status_after_plugin_activation(){
705 update_bk_option( 'booking_translation_update_status', '0' );
706 }
707 add_bk_action( 'wpbc_other_versions_activation', 'wpbc_update_translation_status_after_plugin_activation' );
708
709
710 /**
711 * Download translations from wordpress.org, unpack it to the ../WP_LANG_DIR/plugins folder
712 *
713 * @param $wp_org_translation_packages_arr array of translations data from wp.org
714 * - required one option - $translation_package['package']
715 * - it's URL to zip archive of specific translation
716 *
717 * @return array or results
718 */
719 function wpbc_transaltion_download_from_wp_org( $wp_org_translation_packages_arr ){
720
721 $my_upgrader = wpbc_get_translation_upgrader_obj();
722
723 $result = array();
724
725 foreach ( $wp_org_translation_packages_arr as $translation_package ) {
726
727 $result[] = $my_upgrader->run( array(
728 'package' => $translation_package['package'], // Please always pass this.
729 'destination' => WP_LANG_DIR . '/plugins/', // WPBC_PLUGIN_DIR . '/lang/wp_org/', // ...and this.
730 'clear_destination' => false,
731 'abort_if_destination_exists' => false, // Abort if the destination directory exists. Pass clear_destination as false please.
732 'clear_working' => true,
733 'is_multi' => true,
734 'hook_extra' => array(), // Pass any extra $hook_extra args here, this will be passed to any hooked filters.
735 ) );
736 }
737
738 return $result;
739 }
740
741
742 /**
743 * Download translations from wpbookingcalendar.com, unpack it to the ../WPBC_PLUGIN_DIR/languages/' folder
744 *
745 * @return array|bool|string|WP_Error - result
746 */
747 function wpbc_translation_download_from_wpbc(){
748
749 $my_upgrader = wpbc_get_translation_upgrader_obj();
750
751 $result = $my_upgrader->run( array(
752 'package' => 'https://wpbookingcalendar.com/download/languages/languages.zip', // Please always pass this.
753 'destination' => WPBC_PLUGIN_DIR . '/languages/', // WPBC_PLUGIN_DIR . '/lang/', // ...and this.
754 'clear_destination' => false,
755 'abort_if_destination_exists' => false, // Abort if the destination directory exists. Pass clear_destination as false please.
756 'clear_working' => true,
757 'is_multi' => false,
758 'hook_extra' => array(), // Pass any extra $hook_extra args here, this will be passed to any hooked filters.
759 ) );
760
761 return $result;
762 }
763
764
765 /**
766 * Get translation Upgrader object
767 *
768 * @return WP_Upgrader obj
769 */
770 function wpbc_get_translation_upgrader_obj(){
771
772 require_once ABSPATH . 'wp-admin/includes/file.php';
773 require_once ABSPATH . 'wp-admin/includes/plugin.php';
774 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
775 require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
776
777 require_once WPBC_PLUGIN_DIR . '/core/class/wpbc-class-upgrader-translation-skin.php';
778 $skin = new WPBC_Upgrader_Translation_Skin(
779 array( 'skip_header_footer' => true )
780 );
781
782 $my_upgrader = new WP_Upgrader( $skin );
783
784 $my_upgrader->init(); // it's required for defining skin messages
785
786 return $my_upgrader;
787 }
788
789
790 /**
791 * Get array of translation packages from WordPress.org
792 *
793 * @return array Array ( [0] => Array (
794 [language] => bg_BG
795 [version] => 8.9.3
796 [updated] => 2018-03-13 19:55:57
797 [english_name] => Bulgarian
798 [native_name] => Български
799 [package] => https://downloads.wordpress.org/translation/plugin/booking/8.9.3/bg_BG.zip
800 [iso] => Array ( [1] => bg, [2] => bul )
801 )
802 [1] ....
803 */
804 function wpbc_get_translation_packages_arr_from_wp(){
805
806 $translations_arr = array();
807
808 if ( ! is_admin() ) {
809 return $translations_arr;
810 }
811
812 require_once ABSPATH . 'wp-admin/includes/translation-install.php';
813
814 $api = translations_api( 'plugins', array(
815 'slug' => 'booking',
816 'version' => WP_BK_VERSION_NUM, //'8.9.3',
817 ) );
818
819 if ( ( is_wp_error( $api ) ) || ( empty( $api['translations'] ) ) ) {
820 return $translations_arr;
821 } else {
822 $translations_arr = $api['translations'];
823 }
824
825 return $translations_arr;
826 }
827
828
829
830 //======================================================================================================================
831 // Get STATUS of translations in this website
832 //======================================================================================================================
833
834
835 function wpbc_show_translation_status_compare_wpbc_wp( ) {
836
837 WPBC_Action_Scheduler_Compatibility::raise_memory_limit();
838 WPBC_Action_Scheduler_Compatibility::raise_time_limit( 300 );
839
840 $params = array(
841 'sort_field_name' => 'locale'
842 , 'sort_order' => SORT_ASC
843 , 'sort_type' => SORT_STRING
844 );
845 $params['wp_available_languages'] = wpbc_get_available_language_locales_from_wp_org_api();
846
847 $current_locale = wpbc_get_maybe_reloaded_booking_locale(); // if NOT defined WPBC_LOCALE_RELOAD define by current WordPress locale
848
849 $is_echo = false;
850
851 $from_wp = wpbc_show_translation_status_from_wp( $is_echo, $params );
852 $from_wpbc = wpbc_show_translation_status_from_wpbc( $is_echo, $params );
853
854 $total_translations = 0;
855
856 $compared_translations = array();
857 // WPBC
858 foreach ( $from_wpbc as $po_translation ) {
859 $compared_translations[ $po_translation['locale'] ] = array(
860 'filename' => $po_translation['filename']
861 , 'locale' => $po_translation['locale']
862 , 'english_name' => $po_translation['english_name']
863 , 'total_wpbc' => $po_translation['total']
864 , 'error_wpbc' => $po_translation['error']
865 , 'percent_wpbc' => $po_translation['percent']
866 , 'done_wpbc' => $po_translation['done']
867 , 'untranslated_wpbc' => $po_translation['untranslated']
868 , 'fuzzy_wpbc' => $po_translation['fuzzy']
869
870 , 'total_wp' => 0
871 , 'error_wp' => 0
872 , 'percent_wp' => 0
873 , 'done_wp' => 0
874 , 'untranslated_wp' => 0
875 , 'fuzzy_wp' => 0
876 );
877 if ( $po_translation['total'] > $total_translations ) {
878 $total_translations = $po_translation['total'];
879 }
880 }
881
882
883 // WP_LANG_DIR
884 foreach ( $from_wp as $po_translation ) {
885
886 if ( isset( $compared_translations[ $po_translation['locale'] ] ) ) {
887 $default = $compared_translations[ $po_translation['locale'] ];
888 } else {
889 $default = array(
890 'total_wpbc' => 0
891 , 'error_wpbc' => 0
892 , 'percent_wpbc' => 0
893 , 'done_wpbc' => 0
894 , 'untranslated_wpbc' => 0
895 , 'fuzzy_wpbc' => 0
896 );
897 }
898
899 $compared_translations[ $po_translation['locale'] ] = wp_parse_args(
900 array(
901 'filename' => $po_translation['filename']
902 , 'locale' => $po_translation['locale']
903 , 'english_name' => $po_translation['english_name']
904 , 'total_wp' => $po_translation['total']
905 , 'error_wp' => $po_translation['error']
906 , 'percent_wp' => $po_translation['percent']
907 , 'done_wp' => $po_translation['done']
908 , 'untranslated_wp' => $po_translation['untranslated']
909 , 'fuzzy_wp' => $po_translation['fuzzy']
910 ),
911 $default
912 );
913 if ( $po_translation['total'] > $total_translations ) {
914 $total_translations = $po_translation['total'];
915 }
916 }
917
918 $new_compared_translations = array();
919 $current_active_translation = false;
920 foreach ( $compared_translations as $locale => $compared_translation ) {
921
922 $compared_translation['total'] = $total_translations;//( ( $compared_translation['total_wp'] > $compared_translation['total_wpbc'] ) ? $compared_translation['total_wp'] : $compared_translation['total_wpbc'] );
923
924 $compared_translation['done'] = ( ( $compared_translation['done_wp'] > $compared_translation['done_wpbc'] ) ? $compared_translation['done_wp'] : $compared_translation['done_wpbc'] );
925
926 $compared_translation['percent'] = round( ( $compared_translation['done'] * 100 ) / $compared_translation['total'], 2 );
927
928
929 $new_compared_translations[] = $compared_translation;
930 if ( $current_locale == $compared_translation['locale'] ) {
931 $current_active_translation = array();
932 $current_active_translation[] = $compared_translation;
933 }
934 }
935
936
937 //////////////////////////////////////////////////////////////////////////////////
938 // Sort translation array
939 //////////////////////////////////////////////////////////////////////////////////
940 $volume = array_column( $new_compared_translations, 'done' ); // default $params['sort_field_name'] = 'percent'
941 array_multisort( $volume, SORT_DESC, SORT_NUMERIC, $new_compared_translations );
942
943
944 //debuge( $new_compared_translations );
945
946 if ( ! empty( $current_active_translation ) ) {
947 $new_compared_translations = array_merge( $current_active_translation, $new_compared_translations );
948 }
949 $translation_message = '';
950 $is_already_shown_current_lang = false;
951 foreach ( $new_compared_translations as $translation_status ) {
952
953 if ( ( ! empty( $current_active_translation ) ) && ( $current_locale == $translation_status['locale'] ) && ($is_already_shown_current_lang)) {
954 continue;
955 }
956
957 $translation_message .= ( empty( $translation_status['english_name'] ) ? $translation_status['locale'] : $translation_status['english_name'] )
958 . " [{$translation_status['locale']}] "
959 . " better to use ". ( ( $translation_status['done_wpbc'] > $translation_status['done_wp'] ) ? "local" : "wordpress.org" ) . " translation"
960 . '<br/>'
961 . " Total translations: <strong>{$translation_status['percent']}%</strong> [ <strong>{$translation_status['done']}</strong> / {$translation_status['total']} ]"
962 . '<br/>'
963 . "Local translation. " //. esc_html( WPBC_PLUGIN_DIR . '/languages/' ) . " folder"
964 . " Translated <strong>{$translation_status['done_wpbc']}</strong>"
965 . ", fuzzy <strong>{$translation_status['fuzzy_wpbc']}</strong>"
966 . ", not translated <strong>{$translation_status['untranslated_wpbc']}</strong>"
967 . '<br/>'
968 . "wordpress.org translation. " //. esc_html( WP_LANG_DIR . '/plugins/' ) . " folder"
969 . " Translated <strong>{$translation_status['done_wp']}</strong>"
970 . ", fuzzy <strong>{$translation_status['fuzzy_wp']}</strong>"
971 . ", not translated <strong>{$translation_status['untranslated_wp']}</strong>"
972 . '<hr/>';
973
974 if ( ( ! empty( $current_active_translation ) ) && ( $current_locale == $translation_status['locale'] ) ) {
975 $is_already_shown_current_lang = true;
976 }
977 }
978
979 //////////////////////////////////////////////////////////////////////////////////
980
981 wpbc_show_message_in_settings( $translation_message, 'info' );
982
983 echo '<a class="button button-secondary" style="margin:10px 0;" href="' . esc_url( wpbc_get_settings_url() ) . '" >' . esc_html__( 'Go to Settings', 'booking' ) . '</a>';
984 }
985
986 /**
987 * Get or Show translation statuses from "WP_LANG_DIR" folder at Booking > Settings General page
988 *
989 * Link: http://server.com/wp-admin/admin.php?page=wpbc-settings&system_info=show&show_translation_status=1#wpbc_general_settings_system_info_metabox
990 *
991 * @param bool $is_echo
992 * @param array $params array(
993 'wp_available_languages' => array() - result of wpbc_get_available_language_locales_from_wp_org_api()
994 , 'sort_field_name' => 'percent'
995 , 'sort_order' => SORT_DESC
996 , 'sort_type' => SORT_NUMERIC
997 );
998 *
999 * @return array array ( array ( filename = "booking-ro_RO.po", total = {int} 1906
1000 error = false
1001 percent = {float} 98.11
1002 done = {int} 1870
1003 untranslated = {int} 16
1004 fuzzy = {int} 20
1005 english_name = "ro_RO"
1006 locale = "ro_RO"
1007 )
1008 , ...
1009 )
1010 */
1011 function wpbc_show_translation_status_from_wp( $is_echo = true, $params = array() ){
1012
1013 $defaults = array(
1014 'wp_available_languages' => array()
1015 , 'sort_field_name' => 'done'
1016 , 'sort_order' => SORT_DESC
1017 , 'sort_type' => SORT_NUMERIC
1018 );
1019 $params = wp_parse_args( $params, $defaults );
1020
1021
1022 if ( empty( $params['wp_available_languages'] ) ) {
1023 // Get available language locales from the WordPress.org API.
1024 $params['wp_available_languages'] = wpbc_get_available_language_locales_from_wp_org_api();
1025 }
1026
1027
1028 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1029 // Scan WP_LANG_DIR dir for PO files.
1030 if (1) {
1031 $plugin_translations_in_lang_dir = wp_get_installed_translations( 'plugins' );
1032
1033 $plugin_slug = 'booking';
1034
1035 if ( ! empty( $plugin_translations_in_lang_dir[ $plugin_slug ] ) ) {
1036 $plugin_translations_in_lang_dir = $plugin_translations_in_lang_dir[ $plugin_slug ];
1037 } else {
1038 $plugin_translations_in_lang_dir = array();
1039 }
1040
1041 $po_files_full_path_arr = array();
1042 foreach ( (array) $plugin_translations_in_lang_dir as $locale => $po_arr ) {
1043
1044 $po_files_full_path_arr[] = WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $locale . '.po';
1045 /**
1046 * array ( [0] => W:\w3\beta\www/wp-content/languages/plugins/booking-bg_BG.po
1047 * [1] => W:\w3\beta\www/wp-content/languages/plugins/booking-ca.po
1048 * ...
1049 * )
1050 */
1051 }
1052 }
1053 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1054
1055
1056 // Get array of translation statuses, like total, fuzzy, not translated...
1057 $translation_status_arr = wpbc_get_po_transaltion_statuses_of_files_arr( wp_parse_args(
1058 array(
1059 'po_files_full_path_arr' => $po_files_full_path_arr
1060 )
1061 , $params
1062 )
1063 );
1064 /**
1065 array ( array ( filename = "booking-ro_RO.po", total = {int} 1906
1066 error = false
1067 percent = {float} 98.11
1068 done = {int} 1870
1069 untranslated = {int} 16
1070 fuzzy = {int} 20
1071 english_name = "ro_RO"
1072 locale = "ro_RO"
1073 )
1074 , ...
1075 )
1076 */
1077
1078 if ( $is_echo ) {
1079
1080 $translation_message = '';
1081 foreach ( $translation_status_arr as $translation_status ) {
1082
1083 $translation_message .= ( empty( $translation_status['english_name'] ) ? $translation_status['locale'] : $translation_status['english_name'] )
1084 . " <strong>{$translation_status['percent']}%</strong> [ {$translation_status['done']} / {$translation_status['total']} ]"
1085 . ", fuzzy <strong>{$translation_status['fuzzy']}</strong>"
1086 . ", not translated <strong>{$translation_status['untranslated']}</strong>" . '<br/>';
1087
1088 }
1089
1090 wpbc_show_message_in_settings( $translation_message, 'info' );
1091
1092 echo '<a class="button button-secondary" style="margin:10px 0;" href="' . esc_url( wpbc_get_settings_url() ) . '" >' . esc_html__( 'Go to Settings', 'booking' ) . '</a>';
1093 }
1094
1095 return $translation_status_arr;
1096 }
1097
1098
1099 /**
1100 * Get or Show translation statuses from "{Booking Calendar Folder}" at Booking > Settings General page
1101 * Link: http://server.com/wp-admin/admin.php?page=wpbc-settings&system_info=show&show_translation_status=1#wpbc_general_settings_system_info_metabox
1102 *
1103 * @param bool $is_echo
1104 * @param array $params array(
1105 'wp_available_languages' => array() - result of wpbc_get_available_language_locales_from_wp_org_api()
1106 , 'sort_field_name' => 'percent'
1107 , 'sort_order' => SORT_DESC
1108 , 'sort_type' => SORT_NUMERIC
1109 );
1110 *
1111 * @return array array ( array ( filename = "booking-ro_RO.po", total = {int} 1906
1112 error = false
1113 percent = {float} 98.11
1114 done = {int} 1870
1115 untranslated = {int} 16
1116 fuzzy = {int} 20
1117 english_name = "ro_RO"
1118 locale = "ro_RO"
1119 )
1120 , ...
1121 )
1122 */
1123 function wpbc_show_translation_status_from_wpbc( $is_echo = true, $params = array() ){
1124
1125 $defaults = array(
1126 'wp_available_languages' => array()
1127 , 'sort_field_name' => 'percent'
1128 , 'sort_order' => SORT_DESC
1129 , 'sort_type' => SORT_NUMERIC
1130 );
1131 $params = wp_parse_args( $params, $defaults );
1132
1133
1134 if ( empty( $params['wp_available_languages'] ) ) {
1135 // Get available language locales from the WordPress.org API.
1136 $params['wp_available_languages'] = wpbc_get_available_language_locales_from_wp_org_api();
1137 }
1138
1139
1140 // Scan dir for PO files.
1141 if (1) {
1142 $po_files_array = wpbc_scan_dir_for_po_files( WPBC_PLUGIN_DIR . '/languages' ); // $po_files_array = array( "booking-ar.po", "booking-bel.po", "booking-bg_BG.po", ... )
1143 $po_files_full_path_arr = array();
1144 foreach ( $po_files_array as $po_file_name ) {
1145 $po_files_full_path_arr[] = WPBC_PLUGIN_DIR . '/languages/' . $po_file_name; // W:\w3\beta\www/wp-content/plugins/booking/languages/booking-ar.po
1146 }
1147 }
1148
1149 // Get array of translation statuses, like total, fuzzy, not translated...
1150 $translation_status_arr = wpbc_get_po_transaltion_statuses_of_files_arr( wp_parse_args(
1151 array(
1152 'po_files_full_path_arr' => $po_files_full_path_arr
1153 )
1154 , $params
1155 )
1156 );
1157 /**
1158 array ( array ( filename = "booking-ro_RO.po", total = {int} 1906
1159 error = false
1160 percent = {float} 98.11
1161 done = {int} 1870
1162 untranslated = {int} 16
1163 fuzzy = {int} 20
1164 english_name = "ro_RO"
1165 locale = "ro_RO"
1166 )
1167 , ...
1168 )
1169 */
1170
1171 if ( $is_echo ) {
1172 //////////////////////////////////////////////////////////////////////////////////
1173 $translation_message = '';
1174 foreach ( $translation_status_arr as $translation_status ) {
1175
1176 $translation_message .= ( empty( $translation_status['english_name'] ) ? $translation_status['locale'] : $translation_status['english_name'] )
1177 . " <strong>{$translation_status['percent']}%</strong> [ {$translation_status['done']} / {$translation_status['total']} ]"
1178 . ", fuzzy <strong>{$translation_status['fuzzy']}</strong>"
1179 . ", not translated <strong>{$translation_status['untranslated']}</strong>" . '<br/>';
1180
1181 }
1182
1183 //////////////////////////////////////////////////////////////////////////////////
1184
1185 wpbc_show_message_in_settings( $translation_message, 'info' );
1186
1187 echo '<a class="button button-secondary" style="margin:10px 0;" href="' . esc_url( wpbc_get_settings_url() ) . '" >' . esc_html__( 'Go to Settings', 'booking' ) . '</a>';
1188 }
1189
1190 return $translation_status_arr;
1191 }
1192
1193
1194 /**
1195 * Get Language names for all Locales from WordPress.org API
1196 *
1197 * @return array|array[]
1198 Array( ["nl_NL"] => array ( language = "nl_NL"
1199 version = "5.9"
1200 updated = "2022-02-10 16:24:09"
1201 english_name = "Dutch"
1202 native_name = "Nederlands"
1203 package = "https://downloads.wordpress.org/translation/core/5.9/nl_NL.zip"
1204 iso = array( "nl", "nld" )
1205 strings = array( continue = "Doorgaan" )
1206 ), ...
1207
1208 */
1209 function wpbc_get_available_language_locales_from_wp_org_api(){
1210
1211 // Get Language names for all Locales
1212 require_once ABSPATH . 'wp-admin/includes/translation-install.php';
1213 /**
1214 * Array( ["nl_NL"] => array ( language = "nl_NL"
1215 version = "5.9"
1216 updated = "2022-02-10 16:24:09"
1217 english_name = "Dutch"
1218 native_name = "Nederlands"
1219 package = "https://downloads.wordpress.org/translation/core/5.9/nl_NL.zip"
1220 iso = array( "nl", "nld" )
1221 strings = array( continue = "Doorgaan" )
1222 * ), ...
1223 */
1224 if (function_exists('wp_get_available_translations')){
1225 $wp_api_available_languages = wp_get_available_translations(); // Get available translations from the WordPress.org API.
1226 } else {
1227 $wp_api_available_languages = array();
1228 }
1229
1230 return $wp_api_available_languages;
1231 }
1232
1233
1234 /**
1235 * Get array of translation statuses (like total, fuzzy, not translated) of each PO files
1236 *
1237 * @param $params (array) array(
1238 'po_files_full_path_arr' => array()
1239 , 'wp_available_languages' => array() - result of this function: wp_get_available_translations()
1240 , 'sort_field_name' => 'percent' - it can be any field from the returned array, like 'total'
1241 , 'sort_order' => SORT_DESC
1242 , 'sort_type' => SORT_NUMERIC
1243 )
1244 * 'po_files_full_path_arr' => array (
1245 0 = "W:\w3\beta\www\wp-content\plugins\booking/languages/booking-ar.po"
1246 1 = "W:\w3\beta\www\wp-content\plugins\booking/languages/booking-bel.po"
1247 * ...
1248 * )
1249 *
1250 * @return array array (
1251 0 = array (
1252 filename = "booking-ro_RO.po"
1253 locale = "ro_RO"
1254 total = {int} 1906
1255 error = false
1256 percent = {float} 98.11
1257 done = {int} 1870
1258 untranslated = {int} 16
1259 fuzzy = {int} 20
1260 english_name = "ro_RO"
1261 )
1262 , ...
1263 )
1264 */
1265 function wpbc_get_po_transaltion_statuses_of_files_arr( $params ){
1266
1267 $defaults = array(
1268 'po_files_full_path_arr' => array()
1269 , 'wp_available_languages' => array()
1270 , 'sort_field_name' => 'percent'
1271 , 'sort_order' => SORT_DESC
1272 , 'sort_type' => SORT_NUMERIC
1273 );
1274 $params = wp_parse_args( $params, $defaults );
1275
1276
1277 $translation_status_arr = array();
1278
1279 foreach ( $params['po_files_full_path_arr'] as $po_file_index => $pot_file_path ) {
1280
1281
1282 $translation_status = wpbc_get_po_translation_statuses($pot_file_path);
1283 /**
1284 * array( filename = "booking-ar.po", locale = "ar", total = {int} 1906, percent = {float} 97.74
1285 done = {int} 1863
1286 untranslated = {int} 17
1287 fuzzy = {int} 26
1288 error = false
1289 * )
1290 */
1291
1292 if ( ! empty( $params['wp_available_languages'][ $translation_status['locale'] ] ) ) {
1293 $translation_status['english_name'] = $params['wp_available_languages'][ $translation_status['locale'] ]['english_name'];
1294 } else {
1295 $translation_status['english_name'] = $translation_status['locale'];
1296 }
1297
1298 $translation_status_arr[] = $translation_status;
1299 }
1300
1301 //////////////////////////////////////////////////////////////////////////////////
1302 // Sort translation array
1303 //////////////////////////////////////////////////////////////////////////////////
1304 $volume = array_column( $translation_status_arr, $params['sort_field_name'] ); // default $params['sort_field_name'] = 'percent'
1305 array_multisort( $volume, $params['sort_order'], $params['sort_type'], $translation_status_arr );
1306
1307 return $translation_status_arr;
1308 }
1309
1310
1311 /**
1312 * Scan directory for PO files
1313 *
1314 * @param $dir_to_scan path to directory with PO files
1315 *
1316 * @return array array with names of PO files in this dir
1317 */
1318 function wpbc_scan_dir_for_po_files( $dir_to_scan ){
1319
1320 $found_files = array();
1321
1322 $files = scandir( $dir_to_scan );
1323 if ( ! $files ) {
1324 $found_files = array();
1325 }
1326
1327 foreach ( $files as $file ) {
1328 if ( '.' === $file[0] || is_dir( $dir_to_scan . "/$file" ) ) {
1329 continue;
1330 }
1331 if ( substr( $file, - 3 ) !== '.po' ) {
1332 continue;
1333 }
1334 $match_result = preg_match( '/(?:(.+)-)?([a-z]{2,3}(?:_[A-Z]{2})?(?:_[a-z0-9]+)?).po/', $file, $match );
1335 if ( ! $match_result ) {
1336 continue;
1337 }
1338 if ( ! in_array( substr( $file, 0, - 3 ) . '.mo', $files, true ) ) {
1339 continue;
1340 }
1341
1342 $found_files[] = $file;
1343 }
1344
1345 return $found_files;
1346 }
1347
1348
1349 /**
1350 * Get translation data statuses from PO file
1351 *
1352 * @param $pot_file_path string - full path to PO translation file
1353 *
1354 * @return array array of PO statuses
1355 */
1356 function wpbc_get_po_translation_statuses( $pot_file_path ){
1357
1358 $translation_status = array(
1359 'filename' => basename( $pot_file_path )
1360 , 'locale' => substr( $pot_file_path, ( strrpos( $pot_file_path, '-' ) + 1 ), - 3 )
1361 , 'total' => 0
1362 , 'error' => false
1363 );
1364
1365 if ( is_readable( $pot_file_path ) ) {
1366
1367 if ( ! class_exists( 'PO' ) ) {
1368 require_once ABSPATH . WPINC . '/pomo/po.php';
1369 }
1370
1371 if ( class_exists( 'PO' ) ) {
1372
1373 $po = new PO();
1374 $is_good = $po->import_from_file( $pot_file_path );
1375
1376 if ( $is_good ) {
1377
1378 $transaltion_total = count( $po->entries );
1379 $transaltion_no = 0;
1380 $transaltion_fuzzy = 0;
1381
1382 foreach ( $po->entries as $po_index => $po_item ) {
1383
1384 $translation = $po_item;
1385
1386 if ( 0 == count( $translation->translations ) ) {
1387 $transaltion_no++;
1388 } elseif ( true === in_array( 'fuzzy', $translation->flags ) ) {
1389 $transaltion_fuzzy++;
1390 }
1391 }
1392
1393 $transaltion_done = $transaltion_total - $transaltion_no - $transaltion_fuzzy;
1394 $transaltion_percent = round( ( $transaltion_done * 100 ) / $transaltion_total, 2 );
1395
1396 $translation_status = wp_parse_args(
1397 array(
1398 'percent' => $transaltion_percent
1399 , 'done' => $transaltion_done
1400 , 'total' => $transaltion_total
1401 , 'untranslated' => $transaltion_no
1402 , 'fuzzy' => $transaltion_fuzzy
1403 )
1404 , $translation_status );
1405
1406 } else {
1407 $translation_status['error'] = 'Import translation from PO file failed';
1408 }
1409 } else {
1410 $translation_status['error'] = 'Can not access to PO class';
1411 }
1412
1413 } else {
1414 $translation_status['error'] = 'File not readable';
1415 }
1416 return $translation_status;
1417 }
1418
1419
1420
1421 /**
1422 * Load translation POT file, and generate PHP file with all translations relative to plugin.
1423 * Link: http://server.com/wp-admin/admin.php?page=wpbc-settings&system_info=show&pot=1#wpbc_general_settings_system_info_metabox
1424 */
1425 function wpbc_pot_to_php() {
1426
1427 /*
1428 * $shortcode = 'wpml';
1429
1430 // Find anything between [wpml] and [/wpml] shortcodes. Magic here: [\s\S]*? - fit to any text
1431 preg_match_all( '/\[' . $shortcode . '\]([\s\S]*?)\[\/' . $shortcode . '\]/i', $text, $wpml_translations, PREG_SET_ORDER );
1432 //debuge( $wpml_translations );
1433
1434 foreach ( $wpml_translations as $translation ) {
1435
1436 */
1437
1438 $pot_file = WP_PLUGIN_DIR . '/' . trim( WPBC_PLUGIN_DIRNAME . '/languages/booking.pot' , '/' );
1439
1440 if ( !is_readable( $pot_file ) ) {
1441 wpbc_show_message_in_settings( 'POT file not found: ' . $pot_file , 'error' );
1442 return false;
1443 } else
1444 wpbc_show_message_in_settings( 'POT file found: ' . $pot_file , 'info' );
1445
1446
1447 if ( ! class_exists( 'PO' ) )
1448 require_once ABSPATH . WPINC . '/pomo/po.php';
1449
1450 if ( class_exists( 'PO' ) ) {
1451
1452 $po = new PO();
1453 $po->import_from_file( $pot_file );
1454
1455 wpbc_show_message_in_settings( 'Found <strong>' . count($po->entries) . '</strong> translations' , 'info' );
1456
1457 // FixIn: 8.7.3.6.
1458 $translation_files = array();
1459
1460
1461 // Generate content of the file
1462 //$all_translations = '<?php function wpbc_all_translations() { $wpbc_all_translations = array(); ';
1463
1464 $lines_number = 1;
1465 $all_translations = '';
1466 foreach ( $po->entries as $transaltion => $transaltion_obj ) {
1467
1468 $transaltion = str_replace( "'", "\'", $transaltion );
1469 $all_translations .= ' $wpbc_all_translations[] = __(\''. $transaltion .'\', \'booking\'); /* translators: 1: ... */ ' . "\n";
1470 $lines_number++;
1471
1472 // Maximum number of lines in such files
1473 if ( $lines_number >= 998 ) {
1474 $file_number = count( $translation_files ) + 1;
1475 $translation_files[] = '<?php function wpbc_all_translations' . $file_number . '() { $wpbc_all_translations = array(); ' . "\n" . $all_translations . " } ";
1476 $all_translations = '';
1477 $lines_number = 1;
1478 }
1479
1480 }
1481
1482 if ( ! empty( $all_translations ) ) {
1483 $file_number = count( $translation_files ) + 1;
1484 $translation_files[] = '<?php function wpbc_all_translations' . $file_number . '() { $wpbc_all_translations = array(); ' . "\n" . $all_translations . " } ";
1485 }
1486
1487
1488 //$all_translations .= ' } ';
1489
1490 foreach ( $translation_files as $file_number => $file_content ) {
1491
1492 // Path to new PHP file with all
1493 $new_php_file = WP_PLUGIN_DIR . '/' . trim( WPBC_PLUGIN_DIRNAME . '/core/lang/wpbc_all_translations' . ( ( ! empty( $file_number ) ) ? $file_number : '' ) . '.php', '/' ); // FixIn: 8.9.4.12.
1494 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
1495 $fh = fopen( $new_php_file, 'w' );
1496 if ( false === $fh ) {
1497 wpbc_show_message_in_settings( 'Can not create or edit PHP file: ' . $new_php_file, 'error' );
1498
1499 return false;
1500 }
1501 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fwrite
1502 $res = fwrite( $fh, $file_content );
1503 if ( false === $res ) {
1504 wpbc_show_message_in_settings( 'Some error during saving data into file ' . $new_php_file, 'error' );
1505
1506 return false;
1507 }
1508 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
1509 $res = fclose( $fh );
1510
1511 wpbc_show_message_in_settings( 'Completed! [ ' . htmlentities( $new_php_file ) . ' ]', 'info' );
1512 }
1513
1514 echo '<a class="button button-secondary" style="margin:10px 0;" href="' . esc_url( wpbc_get_settings_url() ) . '" >' . esc_html__( 'Go to Settings', 'booking' ) . '</a>';
1515
1516 return $res;
1517
1518 } else {
1519 wpbc_show_message_in_settings( 'PO class does not exist or do not loaded' , 'error' );
1520 }
1521
1522
1523
1524 // $filename = $pot_file;
1525 // $reader = new POMO_FileReader( $filename );
1526 ////debuge($reader);
1527 // if ( ! $reader->is_resource() ) {
1528 // return false;
1529 // }
1530 //
1531 // $file_data = $reader->read_all();
1532 //
1533 // $mo = new PO();
1534 // $pomo_reader = new POMO_StringReader($file_data);
1535 // $mo->import_from_reader( $pomo_reader );
1536 //debuge($mo) ;
1537 // if ( isset( $l10n[$domain] ) )
1538 // $mo->merge_with( $l10n[$domain] );
1539
1540
1541
1542 }
1543
1544
1545 /**
1546 * Delete PHP translation files, before updating POT file in plugin, manually.
1547 * @return void
1548 */
1549 function wpbc_delete_translation_php_files(){
1550
1551 $path_arr = array(
1552 WPBC_PLUGIN_DIR . '/core/lang/wpbc_all_translations.php',
1553 WPBC_PLUGIN_DIR . '/core/lang/wpbc_all_translations1.php',
1554 WPBC_PLUGIN_DIR . '/core/lang/wpbc_all_translations2.php',
1555 WPBC_PLUGIN_DIR . '/core/lang/wpbc_all_translations3.php',
1556 WPBC_PLUGIN_DIR . '/core/lang/wpbc_all_translations4.php',
1557 WPBC_PLUGIN_DIR . '/core/lang/wpbc_all_translations5.php'
1558 );
1559
1560
1561 foreach ( $path_arr as $path ) {
1562
1563 if ( file_exists( $path ) ) {
1564 if ( is_file( $path ) ) {
1565 if ( ! wp_delete_file( $path ) ) {
1566 throw new \RuntimeException( 'Failed to unlink ' . esc_html( $path ) . ': ' . var_export( error_get_last(), true ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped, WordPress.PHP.DevelopmentFunctions.error_log_var_export
1567 } else {
1568 echo '<p style="color:red;">Deleted: ' . esc_html( $path ) . '</p>';
1569 }
1570 }
1571 }
1572 }
1573 }
1574
1575
1576 // $translation = apply_filters( "gettext_{$domain}", $translation, $text, $domain );
1577
1578 // FixIn: 9.1.3.2.
1579 /**
1580 * Check consistency of translations. For situations, when translators made mistakes with missed symbols like %s or additional items
1581 *
1582 * @param $translation
1583 * @param $text
1584 * @param $domain
1585 *
1586 * @return string
1587 */
1588 function wpbc_check_translations( $translation, $text, $domain ){
1589
1590 $check_symbols = array( 's', 'd', 'f', 'b', 'c', 'e', 'E', 'F', 'g', 'G', 'h', 'H', 'o', 'u', 'x', 'X' );
1591 foreach ( $check_symbols as $check_symbol ) {
1592 $text_count = substr_count( $text, '%' . $check_symbol );
1593 $translation_count = substr_count( $translation, '%' . $check_symbol );
1594
1595 if ( $text_count != $translation_count ) { // Number of %s in translation != number of %s in original text -- ERROR in translation
1596
1597 /*
1598 $booking_translation_errors = new WP_Error( 'booking_translation_consistency', 'Translation consistency error', array(
1599 'text' => $text,
1600 'translation' => $translation,
1601 'symbol_error' => '%' . $check_symbol
1602 ) );
1603 */
1604 return $text;
1605 }
1606
1607 }
1608
1609 $text_count = substr_count( $text, '%' );
1610 $translation_count = substr_count( $translation, '%' );
1611 if ( $text_count != $translation_count ) {
1612 return $text;
1613 }
1614
1615 return $translation;
1616 }
1617 add_filter( 'gettext_booking', 'wpbc_check_translations', 1000, 3 ); // check Booking Calendar translation terms
1618 add_filter( 'gettext_booking-manager', 'wpbc_check_translations', 1000, 3 ); // check Booking Manager translation terms
1619
1620 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1621 // Deprecated
1622 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1623
1624 /**
1625 * Deprecated
1626 */
1627 function wpbc_get_booking_locale() {
1628 return wpbc_get_maybe_reloaded_booking_locale();
1629 }
1630
1631
1632