PluginProbe ʕ •ᴥ•ʔ
Advanced Custom Fields: Extended / 0.8.9.5
Advanced Custom Fields: Extended v0.8.9.5
0.9.2.6 0.9.2.5 0.8.6 0.8.6.1 0.8.6.3 0.8.6.5 0.8.6.6 0.8.6.7 0.8.6.8 0.8.6.9 0.8.7 0.8.7.1 0.8.7.2 0.8.7.3 0.8.7.4 0.8.7.5 0.8.7.6 0.8.8 0.8.8.1 0.8.8.10 0.8.8.11 0.8.8.2 0.8.8.3 0.8.8.4 0.8.8.5 0.8.8.6 0.8.8.7 0.8.8.8 0.8.8.9 0.8.9 0.8.9.1 0.8.9.2 0.8.9.3 0.8.9.4 0.8.9.5 0.9 0.9.0.1 0.9.0.2 0.9.0.3 0.9.0.4 0.9.0.5 0.9.0.6 0.9.0.7 0.9.0.8 0.9.0.9 0.9.1 0.9.1.1 0.9.2 0.9.2.1 0.9.2.2 0.9.2.3 0.9.2.4 trunk 0.5 0.5.1 0.5.2 0.5.2.1 0.5.2.3 0.5.5 0.5.5.1 0.5.8 0.5.8.1 0.6 0.6.0.1 0.6.0.2 0.6.1 0.6.3 0.6.5 0.6.7 0.6.7.2 0.7 0.7.0.3 0.7.5 0.7.5.5 0.7.8 0.7.9 0.7.9.3 0.7.9.4 0.7.9.9.8 0.7.9.9.9 0.8 0.8.1 0.8.2 0.8.3 0.8.3.1 0.8.4 0.8.4.1 0.8.4.5 0.8.4.6 0.8.5 0.8.5.5
acf-extended / includes / multilang.php
acf-extended / includes Last commit date
admin 3 years ago field-groups 3 years ago fields 3 years ago fields-settings 3 years ago locations 3 years ago modules 2 years ago screens 3 years ago acfe-deprecated-functions.php 2 years ago acfe-field-functions.php 3 years ago acfe-field-group-functions.php 3 years ago acfe-file-functions.php 3 years ago acfe-form-functions.php 3 years ago acfe-helper-functions.php 3 years ago acfe-meta-functions.php 3 years ago acfe-post-functions.php 3 years ago acfe-screen-functions.php 3 years ago acfe-template-functions.php 3 years ago acfe-term-functions.php 3 years ago acfe-user-functions.php 3 years ago acfe-wp-functions.php 3 years ago assets.php 3 years ago compatibility-6.0.php 2 years ago compatibility.php 3 years ago field-extend.php 3 years ago field.php 3 years ago hooks.php 3 years ago init.php 3 years ago local-meta.php 3 years ago module-acf.php 3 years ago module-db.php 3 years ago module-l10n.php 3 years ago module-legacy.php 3 years ago module-manager.php 3 years ago module-post.php 2 years ago module-posts.php 3 years ago module-upgrades.php 3 years ago module.php 3 years ago multilang.php 3 years ago settings.php 3 years ago third-party.php 3 years ago upgrades.php 3 years ago
multilang.php
930 lines
1 <?php
2
3 if(!defined('ABSPATH')){
4 exit;
5 }
6
7 if(!class_exists('acfe_multilang')):
8
9 class acfe_multilang{
10
11 // vars
12 var $is_wpml = false;
13 var $is_polylang = false;
14 var $is_multilang = false;
15 var $options_pages = array();
16
17 /**
18 * construct
19 */
20 function __construct(){
21
22 // wpml
23 if(defined('ICL_SITEPRESS_VERSION')){
24
25 $this->is_wpml = true;
26 $this->is_multilang = true;
27
28 }
29
30 // polyLang
31 if(defined('POLYLANG_VERSION') && function_exists('pll_default_language')){
32
33 $this->is_polylang = true;
34 $this->is_multilang = true;
35
36 }
37
38 if($this->is_multilang){
39 add_action('acf/init', array($this, 'init'), 99);
40 }
41
42 }
43
44
45 /**
46 * init
47 */
48 function init(){
49
50 // check setting
51 if(!acf_get_setting('acfe/modules/multilang')){
52 return;
53 }
54
55 // polylang specific
56 if($this->is_polylang){
57
58 // default/Current Language
59 $dl = pll_default_language('locale');
60 $cl = pll_current_language('locale');
61
62 // update settings
63 acf_update_setting('default_language', $dl);
64 acf_update_setting('current_language', $cl);
65
66 add_filter('acf/pre_load_reference', array($this, 'polylang_preload_reference'), 10, 3);
67 add_filter('acf/pre_load_value', array($this, 'polylang_preload_value'), 10, 3);
68
69 }
70
71 // options page Message
72 add_action('acf/options_page/submitbox_before_major_actions', array($this, 'options_page_message'));
73
74 // acf options post id
75 add_filter('acf/validate_post_id', array($this, 'set_options_post_id'), 99, 2);
76
77 }
78
79
80 /**
81 * polylang_preload_reference
82 *
83 * @param $null
84 * @param $field_name
85 * @param $post_id
86 *
87 * @return mixed|null
88 */
89 function polylang_preload_reference($null, $field_name, $post_id){
90
91 // validate post id
92 $original_post_id = $this->polylang_validate_preload_post_id($post_id);
93
94 if(!$original_post_id){
95 return $null;
96 }
97
98 $reference = acf_get_metadata($post_id, $field_name, true);
99
100 if($reference !== null){
101 return $null;
102 }
103
104 return acf_get_metadata($original_post_id, $field_name, true);
105
106 }
107
108
109 /**
110 * polylang_preload_value
111 *
112 * @param $null
113 * @param $post_id
114 * @param $field
115 *
116 * @return mixed
117 */
118 function polylang_preload_value($null, $post_id, $field){
119
120 // validate post id
121 $original_post_id = $this->polylang_validate_preload_post_id($post_id);
122
123 if(!$original_post_id){
124 return $null;
125 }
126
127 // get field name
128 $field_name = $field['name'];
129
130 // check store
131 $store = acf_get_store('values');
132
133 if($store->has("$post_id:$field_name")){
134 return $null;
135 }
136
137 // load value from database
138 $value = acf_get_metadata($post_id, $field_name);
139
140 // use field's default_value if no meta was found
141 if($value !== null){
142 return $null;
143 }
144
145 return acf_get_value($original_post_id, $field);
146
147 }
148
149
150 /**
151 * polylang_validate_preload_post_id
152 *
153 * @param $post_id
154 *
155 * @return array|false|string|string[]|null
156 */
157 function polylang_validate_preload_post_id($post_id){
158
159 // bail early if admin screen
160 if(is_admin() || !is_string($post_id)){
161 return false;
162 }
163
164 // get post id info
165 $data = acf_get_post_id_info($post_id);
166
167 // bail early if post id isn't an option type
168 if($data['type'] !== 'option'){
169 return false;
170 }
171
172 // bail early if not localized
173 if(!$this->is_localized($post_id)){
174 return false;
175 }
176
177 $original_post_id = preg_replace( '/([_\-][A-Za-z]{2}_[A-Za-z]{2})$/', '', $post_id);
178
179 // check the regex
180 if($original_post_id === $post_id){
181 return false;
182 }
183
184 // bail early if no Options Page found with that post id
185 if(!$this->is_options_page($original_post_id)){
186 return false;
187 }
188
189 return $original_post_id;
190
191 }
192
193
194 /**
195 * wpml_get_languages
196 *
197 * https://wpml.org/documentation/support/wpml-coding-api/wpml-hooks-reference/
198 *
199 * @param $pluck
200 * @param $type
201 *
202 * @return array|int[]|mixed|string[]|null
203 */
204 function wpml_get_languages($pluck = '', $type = 'all'){
205
206 // vars
207 $languages = array();
208 $pluck = $pluck === 'locale' ? 'default_locale' : $pluck;
209
210 switch($type){
211
212 // active
213 case 'active': {
214
215 // https://wpml.org/wpml-hook/wpml_active_languages/
216 $languages = apply_filters('wpml_active_languages', null, array('skip_missing' => 0));
217
218 // Set locale as key
219 $_languages = $languages;
220 $languages = array();
221
222 foreach($_languages as $lang){
223 $languages[ $lang['default_locale'] ] = $lang;
224 }
225
226 if($pluck){
227 $languages = wp_list_pluck($languages, $pluck, true);
228 }
229
230 return $languages;
231
232 }
233
234 // all
235 case '':
236 case 'all': {
237
238 // https://wpml.org/wpml-hook/wpml_active_languages/
239 $languages = apply_filters('wpml_active_languages', null, array('skip_missing' => 0));
240 $languages = wp_list_pluck($languages, 'code', 'default_locale');
241
242 // Default Languages
243 $_languages = icl_get_languages_locales();
244 $_languages = array_flip($_languages);
245
246 if(!empty($_languages)){
247
248 $languages = array_merge($languages, $_languages);
249 $languages = array_unique($languages);
250
251 }
252
253 if($pluck){
254 $languages = $pluck === 'code' ? array_values($_languages) : array_keys($_languages);
255 }
256
257 return $languages;
258
259 }
260
261 }
262
263 return $languages;
264
265 }
266
267
268 /**
269 * polylang_get_languages
270 *
271 * https://polylang.pro/doc/filter-reference/
272 * https://polylang.pro/doc/developpers-how-to/
273 * https://polylang.pro/doc-category/developers/
274 * https://polylang.wordpress.com/documentation/documentation-for-developers/general/
275 * https://polylang.wordpress.com/documentation/documentation-for-developers/functions-reference/
276 *
277 * @param $pluck
278 * @param $type
279 *
280 * @return array|string[]
281 */
282 function polylang_get_languages($pluck = '', $type = 'all'){
283
284 // vars
285 $languages = array();
286
287 switch($type){
288
289 // active
290 case 'active': {
291
292 // convert pluck
293 $pluck = $pluck === 'code' ? 'slug' : $pluck;
294
295 // https://polylang.wordpress.com/documentation/documentation-for-developers/functions-reference/
296 $languages = pll_languages_list(array(
297 'hide_empty' => false,
298 'fields' => $pluck
299 ));
300
301 return $languages;
302
303 }
304
305 // all
306 case '':
307 case 'all': {
308
309 $languages = PLL_Settings::get_predefined_languages();
310
311 if($pluck){
312 $languages = wp_list_pluck($languages, $pluck, true);
313 }
314
315 return $languages;
316
317 }
318
319 }
320
321 return $languages;
322
323 }
324
325
326 /**
327 * set_options_post_id
328 *
329 * @param $post_id
330 * @param $original_post_id
331 *
332 * @return mixed|string
333 */
334 function set_options_post_id($post_id, $original_post_id){
335
336 // bail early if original post id is 'options' ||'option'
337 if(!is_string($post_id)){
338 return $post_id;
339 }
340
341 $data = acf_get_post_id_info($post_id);
342
343 // bail early if post id isn't an option type
344 if($data['type'] !== 'option'){
345 return $post_id;
346 }
347
348 // options Exception
349 // $post_id already translated during the native acf/validate_post_id
350 if(in_array($original_post_id, array('options', 'option'))){
351
352 // exclude filter
353 $exclude = apply_filters('acfe/modules/multilang/exclude_options', array());
354
355 if(in_array('options', $exclude)){
356 return 'options';
357 }
358
359 return $post_id;
360
361 }
362
363 // bail early if no Options Page found with that post id
364 if(!$this->is_options_page($post_id)){
365 return $post_id;
366 }
367
368 // bail early if already localized: 'my-options_en_US'
369 if($this->is_localized($post_id)){
370 return $post_id;
371 }
372
373 // append current language to post id
374 $dl = acf_get_setting('default_language');
375 $cl = acf_get_setting('current_language');
376
377 // add Language
378 if($cl && $cl !== $dl){
379 $post_id .= '_' . $cl;
380 }
381
382 return $post_id;
383
384 }
385
386
387 /**
388 * is_localized
389 *
390 * @param $post_id
391 *
392 * @return bool
393 */
394 function is_localized($post_id){
395
396 // check if post id ends with '-en_US' || '_en_US' || '-en' || '_en'
397 // https://regex101.com/r/oMsyeL/4
398 preg_match('/(?P<locale>[_\-][A-Za-z]{2}_[A-Za-z]{2})$|(?P<code>[_\-][A-Za-z]{2})$/', $post_id, $matches);
399
400 if(empty($matches)){
401 return false;
402 }
403
404 // cleanup matches
405 $lang = array();
406
407 foreach($matches as $key => $val){
408
409 if(is_int($key) || empty($val)){
410 continue;
411 }
412
413 $lang = array(
414 'type' => $key,
415 'lang' => strtolower(substr($val, 1)), // Lowercase + Remove the first '_'
416 );
417
418 }
419
420 if(empty($lang)){
421 return false;
422 }
423
424 // get wpml/polylang languages list
425 $languages = $this->get_languages($lang['type']);
426 $languages = array_map('strtolower', $languages);
427
428 // compare matches vs wpml/polylang languages list
429 return in_array($lang['lang'], $languages);
430
431 }
432
433
434 /**
435 * is_options_page
436 *
437 * @param $post_id
438 *
439 * @return bool
440 */
441 function is_options_page($post_id){
442
443 // check if post id already in options pages
444 if(in_array($post_id, $this->options_pages)){
445 return true;
446 }
447
448 // get acf options pages
449 $options_pages = acf_get_array(acf_get_options_pages());
450 $list = wp_list_pluck($options_pages, 'post_id', true);
451
452 // add 'post type list' location
453 $post_types = acf_get_post_types(array(
454 'show_ui' => 1,
455 'exclude' => array('attachment')
456 ));
457
458 foreach($post_types as $post_type){
459 $list[] = "{$post_type}_options";
460 }
461
462 // add 'taxonomy list' location
463 $taxonomies = acf_get_taxonomies();
464
465 foreach($taxonomies as $taxonomy){
466 $list[] = "tax_{$taxonomy}_options";
467 }
468
469 // deprecated filter
470 $list = apply_filters_deprecated('acfe/modules/multilang/options', array($list), '0.8.8.2', 'acfe/modules/multilang/exclude_options');
471
472 // include filter
473 $list = apply_filters('acfe/modules/multilang/include_options', $list);
474
475 // exclude filter
476 $exclude = apply_filters('acfe/modules/multilang/exclude_options', array());
477
478 if(is_array($exclude) && !empty($exclude)){
479
480 foreach($list as $i => $option){
481 if(in_array($option, $exclude)){
482 unset($list[ $i ]);
483 }
484 }
485
486 $list = array_values($list);
487
488 }
489
490 $this->options_pages = $list;
491
492 return in_array($post_id, $this->options_pages);
493
494 }
495
496
497 /**
498 * get_languages
499 *
500 * @param $pluck
501 * @param $type
502 * @param $plugin
503 *
504 * @return array|int[]|mixed|string[]|null
505 */
506 function get_languages($pluck = '', $type = '', $plugin = ''){
507
508 // polylang
509 if($this->is_polylang || $plugin === 'polylang'){
510 return $this->polylang_get_languages($pluck, $type);
511
512 // wpml
513 }elseif($this->is_wpml || $plugin === 'wpml'){
514 return $this->wpml_get_languages($pluck, $type);
515 }
516
517 return array();
518
519 }
520
521
522 /**
523 * options_page_message
524 */
525 function options_page_message(){
526
527 $default_language = acf_get_setting('default_language');
528 $current_language = acf_get_setting('current_language');
529
530 $message = false;
531
532 // polylang
533 if($this->is_polylang){
534
535 if(!$current_language){
536 $current_language = $default_language;
537 }
538
539 $message = "Language: {$current_language}";
540
541 $nice_language = false;
542 $nice_flag = false;
543
544 $languages = pll_languages_list(array(
545 'hide_empty' => false,
546 'fields' => false
547 ));
548
549 if($languages){
550
551 foreach($languages as $language){
552
553 if($language->locale !== $current_language){
554 continue;
555 }
556
557 $nice_language = $language->name;
558 $nice_flag = $language->flag_url;
559 break;
560
561 }
562
563 }
564
565 if($nice_language){
566 $message = "<img src='{$nice_flag}' style='margin-right:5px;vertical-align:-1px;' /> Language: {$nice_language}";
567 }
568
569 if($default_language === $current_language){
570 $message .= ' (Default)';
571 }
572
573 }
574
575 // wpml
576 elseif($this->is_wpml){
577
578 if($current_language === 'all'){
579 $current_language = 'All';
580 }
581
582 $message = "Language: {$current_language}";
583
584 if($current_language !== 'All'){
585
586 $nice_language = false;
587 $nice_flag = false;
588
589 $languages = apply_filters('wpml_active_languages', null, array('skip_missing' => 0));
590
591 if($languages){
592
593 foreach($languages as $language){
594
595 if($language['language_code'] !== $current_language){
596 continue;
597 }
598
599 $nice_language = $language['native_name'];
600 $nice_flag = $language['country_flag_url'];
601 break;
602
603 }
604
605 }
606
607 if($nice_language){
608
609 $message = "<img src='{$nice_flag}' style='margin-right:5px;vertical-align:-1px; width:16px; height:11px;' /> Language: {$nice_language}";
610
611 }
612
613 }
614
615 }
616
617 if(empty($message)){
618 return;
619 }
620
621 echo "<div class='misc-pub-section' style='padding-top:15px; padding-bottom:15px;'>{$message}</div>";
622
623
624 }
625
626 }
627
628 acf_new_instance('acfe_multilang');
629
630 endif;
631
632
633 /**
634 * acfe_is_multilang
635 *
636 * @return mixed
637 */
638 function acfe_is_multilang(){
639 return acf_get_instance('acfe_multilang')->is_multilang;
640 }
641
642
643 /**
644 * acfe_get_multilang
645 *
646 * @return array
647 */
648 function acfe_get_multilang(){
649
650 $wpml = acf_get_instance('acfe_multilang')->is_wpml;
651 $polylang = acf_get_instance('acfe_multilang')->is_polylang;
652
653 $data = array(
654 'dl' => acf_get_setting('default_language'),
655 'cl' => acf_get_setting('current_language'),
656 'wpml' => $wpml,
657 'polylang' => $polylang,
658 );
659
660 return $data;
661
662 }
663
664
665 /**
666 * acfe_get_multilang_languages
667 *
668 * @param $pluck
669 * @param $type
670 * @param $plugin
671 *
672 * @return mixed
673 */
674 function acfe_get_multilang_languages($pluck = '', $type = '', $plugin = ''){
675 return acf_get_instance('acfe_multilang')->get_languages($pluck, $type, $plugin);
676 }
677
678
679 /**
680 * acfe_is_polylang
681 *
682 * @return mixed
683 */
684 function acfe_is_polylang(){
685 return acf_get_instance('acfe_multilang')->is_polylang;
686 }
687
688
689 /**
690 * acfe_is_wpml
691 *
692 * @return mixed
693 */
694 function acfe_is_wpml(){
695 return acf_get_instance('acfe_multilang')->is_wpml;
696 }
697
698
699 /**
700 * acfe_get_post_lang
701 *
702 * @param $post_id
703 * @param $field
704 *
705 * @return false|mixed|string
706 */
707 function acfe_get_post_lang($post_id, $field = false){
708
709 // bail early if not multilang
710 if(!acfe_is_multilang()){
711 return false;
712 }
713
714 // polylang
715 if(acfe_is_polylang()){
716
717 // default field
718 if(!$field){
719 $field = 'locale';
720 }
721
722 return pll_get_post_language($post_id, $field);
723
724 // wpml
725 }elseif(acfe_is_wpml()){
726
727 $post_lang = apply_filters('wpml_post_language_details', NULL, $post_id);
728
729 // default field
730 if(!$field){
731 $field = 'slug';
732 }
733
734 if($field === 'locale'){
735 return $post_lang['locale'];
736
737 }elseif($field === 'slug'){
738 return $post_lang['language_code'];
739
740 }elseif($field === 'name'){
741 return $post_lang['display_name'];
742 }
743
744 return false;
745
746 }
747
748 return false;
749
750 }
751
752
753 /**
754 * acfe_get_post_translated
755 *
756 * @param $post_id
757 * @param $lang
758 *
759 * @return false|int|mixed|null
760 */
761 function acfe_get_post_translated($post_id, $lang = false){
762
763 // bail early if not multilang
764 if(!acfe_is_multilang()){
765 return $post_id;
766 }
767
768 // default
769 $translated_post_id = $post_id;
770
771 // polylang
772 if(acfe_is_polylang()){
773 $translated_post_id = pll_get_post($post_id, $lang);
774
775 // wpml
776 }elseif(acfe_is_wpml()){
777 $translated_post_id = apply_filters('wpml_object_id', $post_id, 'post', false, $lang);
778 }
779
780 /*
781 if(empty($translated_post_id))
782 return $post_id;
783 */
784
785 return $translated_post_id;
786
787 }
788
789
790 /**
791 * acfe_get_post_translated_default
792 *
793 * @param $post_id
794 *
795 * @return int|mixed
796 */
797 function acfe_get_post_translated_default($post_id){
798
799 // get translated post id
800 $translated_post_id = acfe_get_post_translated($post_id, acf_get_setting('default_language'));
801
802 // fallback to current
803 if(empty($translated_post_id)){
804 return $post_id;
805 }
806
807 return $translated_post_id;
808
809 }
810
811
812 /**
813 * acfe_translate
814 *
815 * @param $string
816 * @param $name
817 * @param $textdomain
818 *
819 * @return mixed|string|null
820 */
821 function acfe_translate($string, $name = '', $textdomain = ''){
822
823 // no polylang/wpml
824 if(!acfe_is_multilang()){
825 return acf_translate($string);
826 }
827
828 // acf translate
829 if(empty($name) && empty($textdomain)){
830 return acf_translate($string);
831 }
832
833 // is array
834 if(is_array($string)){
835
836 foreach($string as $k => $v){
837 $name = !is_numeric($k) ? ucfirst($k) : $name;
838 $string[ $k ] = acfe_translate($v, $name, $textdomain);
839 }
840
841 }
842
843 // bail early if not string
844 if(!is_string($string)){
845 return $string;
846 }
847
848 // bail early if empty
849 if($string === ''){
850 return $string;
851 }
852
853 // wpml
854 if(acfe_is_wpml()){
855 return apply_filters('wpml_translate_single_string', $string, $textdomain, $name);
856 }
857
858 // polylang
859 if(acfe_is_polylang()){
860
861 pll_register_string($name, $string, $textdomain);
862 return pll__($string);
863
864 }
865
866 // default translate
867 return acf_translate($string);
868
869 }
870
871
872 /**
873 * acfe_register_translate
874 *
875 * @param $string
876 * @param $name
877 * @param $textdomain
878 */
879 function acfe_register_translate($string, $name = '', $textdomain = ''){
880
881 // wpml only
882 if(acfe_is_wpml()){
883
884 // is array
885 if(is_array($string)){
886
887 foreach($string as $k => $v){
888 $name = !is_numeric($k) ? ucfirst($k) : $name;
889 acfe_register_translate($v, $name, $textdomain);
890 }
891
892 // string
893 }else{
894 do_action('wpml_register_single_string', $textdomain, $name, $string);
895 }
896
897 }
898
899
900 }
901
902
903 /**
904 * acfe__
905 *
906 * @param $string
907 * @param $name
908 * @param $textdomain
909 *
910 * @deprecated
911 *
912 * @return mixed|string|null
913 */
914 function acfe__($string, $name = false, $textdomain = 'acfe'){
915 return acfe_translate($string, $name, $textdomain);
916 }
917
918
919 /**
920 * acfe__e
921 *
922 * @param $string
923 * @param $name
924 * @param $textdomain
925 *
926 * @deprecated
927 */
928 function acfe__e($string, $name = false, $textdomain = 'acfe'){
929 echo acfe_translate($string, $name, $textdomain);
930 }