PluginProbe
Booking Calendar / 10.1.3
Booking Calendar v10.1.3
11.8.3 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 All 203 releases
booking / core / wpbc-translation.php

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

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