PluginProbe ʕ •ᴥ•ʔ
Advanced Custom Fields: Extended / 0.8.8.5
Advanced Custom Fields: Extended v0.8.8.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 4 years ago field-groups 4 years ago fields 4 years ago fields-settings 4 years ago forms 4 years ago locations 4 years ago modules 4 years ago acfe-field-functions.php 4 years ago acfe-field-group-functions.php 4 years ago acfe-file-functions.php 4 years ago acfe-form-functions.php 4 years ago acfe-helper-functions.php 4 years ago acfe-meta-functions.php 4 years ago acfe-post-functions.php 4 years ago acfe-screen-functions.php 4 years ago acfe-template-functions.php 4 years ago acfe-term-functions.php 4 years ago acfe-user-functions.php 4 years ago acfe-wp-functions.php 4 years ago assets.php 4 years ago compatibility.php 4 years ago hooks.php 4 years ago init.php 4 years ago local-meta.php 4 years ago multilang.php 4 years ago settings.php 4 years ago upgrades.php 4 years ago
multilang.php
749 lines
1 <?php
2
3 if(!defined('ABSPATH'))
4 exit;
5
6 if(!class_exists('acfe_multilang')):
7
8 class acfe_multilang{
9
10 var $is_wpml = false;
11 var $is_polylang = false;
12 var $is_multilang = false;
13 var $options_pages = false;
14
15 function __construct(){
16
17 // WPML
18 if(defined('ICL_SITEPRESS_VERSION')){
19
20 $this->is_wpml = true;
21 $this->is_multilang = true;
22
23 }
24
25 // PolyLang
26 if(defined('POLYLANG_VERSION') && function_exists('pll_default_language')){
27
28 $this->is_polylang = true;
29 $this->is_multilang = true;
30
31 }
32
33 if($this->is_multilang){
34
35 add_action('acf/init', array($this, 'init'), 99);
36
37 }
38
39 }
40
41 function init(){
42
43 // Check setting
44 if(!acf_get_setting('acfe/modules/multilang'))
45 return;
46
47 // Polylang specific
48 if($this->is_polylang){
49
50 // Default/Current Language
51 $dl = pll_default_language('locale');
52 $cl = pll_current_language('locale');
53
54 // Update settings
55 acf_update_setting('default_language', $dl);
56 acf_update_setting('current_language', $cl);
57
58 add_filter('acf/pre_load_reference', array($this, 'polylang_preload_reference'), 10, 3);
59 add_filter('acf/pre_load_value', array($this, 'polylang_preload_value'), 10, 3);
60
61 }
62
63 // Options Page Message
64 add_action('acf/options_page/submitbox_before_major_actions', array($this, 'options_page_message'));
65
66 // ACF Options Post ID
67 add_filter('acf/validate_post_id', array($this, 'set_options_post_id'), 99, 2);
68
69 }
70
71 function polylang_preload_reference($null, $field_name, $post_id){
72
73 // Validate post id
74 $original_post_id = $this->polylang_validate_preload_post_id($post_id);
75
76 if(!$original_post_id)
77 return $null;
78
79 $reference = acf_get_metadata($post_id, $field_name, true);
80
81 if($reference !== null)
82 return $null;
83
84 return acf_get_metadata($original_post_id, $field_name, true);
85
86 }
87
88 function polylang_preload_value($null, $post_id, $field){
89
90 // Validate post id
91 $original_post_id = $this->polylang_validate_preload_post_id($post_id);
92
93 if(!$original_post_id)
94 return $null;
95
96 // Get field name.
97 $field_name = $field['name'];
98
99 // Check store.
100 $store = acf_get_store('values');
101
102 if($store->has("$post_id:$field_name"))
103 return $null;
104
105 // Load value from database.
106 $value = acf_get_metadata($post_id, $field_name);
107
108 // Use field's default_value if no meta was found.
109 if($value !== null)
110 return $null;
111
112 return acf_get_value($original_post_id, $field);
113
114 }
115
116 function polylang_validate_preload_post_id($post_id){
117
118 // Bail early if admin screen
119 if(is_admin() || !is_string($post_id))
120 return false;
121
122 // Get post id info
123 $data = acf_get_post_id_info($post_id);
124
125 // Bail early if post id isn't an option type
126 if($data['type'] !== 'option')
127 return false;
128
129 // Bail early if not localized
130 if(!$this->is_localized($post_id))
131 return false;
132
133 $original_post_id = preg_replace( '/([_\-][A-Za-z]{2}_[A-Za-z]{2})$/', '', $post_id);
134
135 // Check the regex
136 if($original_post_id === $post_id)
137 return false;
138
139 // Bail early if no Options Page found with that post id
140 if(!$this->is_options_page($original_post_id))
141 return false;
142
143 return $original_post_id;
144
145 }
146
147 /**
148 * WPML
149 * https://wpml.org/documentation/support/wpml-coding-api/wpml-hooks-reference/
150 */
151 function wpml_get_languages($pluck = '', $type = 'all'){
152
153 // Vars
154 $languages = array();
155 $pluck = $pluck === 'locale' ? 'default_locale' : $pluck;
156
157 switch($type){
158
159 // Active
160 case 'active':
161
162 // https://wpml.org/wpml-hook/wpml_active_languages/
163 $languages = apply_filters('wpml_active_languages', null, array('skip_missing' => 0));
164
165 // Set locale as key
166 $_languages = $languages;
167 $languages = array();
168
169 foreach($_languages as $lang){
170 $languages[ $lang['default_locale'] ] = $lang;
171 }
172
173 if($pluck)
174 $languages = wp_list_pluck($languages, $pluck, true);
175
176 return $languages;
177
178 // All
179 case '':
180 case 'all':
181
182 // https://wpml.org/wpml-hook/wpml_active_languages/
183 $languages = apply_filters('wpml_active_languages', null, array('skip_missing' => 0));
184 $languages = wp_list_pluck($languages, 'code', 'default_locale');
185
186 // Default Languages
187 $_languages = icl_get_languages_locales();
188 $_languages = array_flip($_languages);
189
190 if(!empty($_languages)){
191
192 $languages = array_merge($languages, $_languages);
193 $languages = array_unique($languages);
194
195 }
196
197 if($pluck)
198 $languages = $pluck === 'code' ? array_values($_languages) : array_keys($_languages);
199
200 return $languages;
201
202 }
203
204 return $languages;
205
206 }
207
208 /**
209 * PolyLang
210 * https://polylang.pro/doc/filter-reference/
211 * https://polylang.pro/doc/developpers-how-to/
212 * https://polylang.pro/doc-category/developers/
213 * https://polylang.wordpress.com/documentation/documentation-for-developers/general/
214 * https://polylang.wordpress.com/documentation/documentation-for-developers/functions-reference/
215 */
216 function polylang_get_languages($pluck = '', $type = 'all'){
217
218 // Vars
219 $languages = array();
220
221 switch($type){
222
223 // Active
224 case 'active':
225
226 // Convert pluck
227 $pluck = $pluck === 'code' ? 'slug' : $pluck;
228
229 // https://polylang.wordpress.com/documentation/documentation-for-developers/functions-reference/
230 $languages = pll_languages_list(array(
231 'hide_empty' => false,
232 'fields' => $pluck
233 ));
234
235 return $languages;
236
237 // All
238 case '':
239 case 'all':
240
241 $languages = PLL_Settings::get_predefined_languages();
242
243 if($pluck)
244 $languages = wp_list_pluck($languages, $pluck, true);
245
246 return $languages;
247
248 }
249
250 return $languages;
251
252 }
253
254 /**
255 * ACF Options Post ID
256 */
257 function set_options_post_id($post_id, $original_post_id){
258
259 // Bail early if original post id is 'options' ||'option'
260 if(!is_string($post_id))
261 return $post_id;
262
263 $data = acf_get_post_id_info($post_id);
264
265 // Bail early if post id isn't an option type
266 if($data['type'] !== 'option')
267 return $post_id;
268
269 // Options Exception
270 // $post_id already translated during the native acf/validate_post_id
271 if(in_array($original_post_id, array('options', 'option'))){
272
273 // Exclude filter
274 $exclude = apply_filters('acfe/modules/multilang/exclude_options', array());
275
276 if(in_array('options', $exclude)){
277 return 'options';
278 }
279
280 return $post_id;
281
282 }
283
284 // Bail early if no Options Page found with that post id
285 if(!$this->is_options_page($post_id))
286 return $post_id;
287
288 // Bail early if already localized: 'my-options_en_US'
289 if($this->is_localized($post_id))
290 return $post_id;
291
292 // Append current language to post id
293 $dl = acf_get_setting('default_language');
294 $cl = acf_get_setting('current_language');
295
296 // Add Language
297 if($cl && $cl !== $dl){
298
299 $post_id .= '_' . $cl;
300
301 }
302
303 return $post_id;
304
305 }
306
307 function is_localized($post_id){
308
309 // Check if post id ends with '-en_US' || '_en_US' || '-en' || '_en'
310 // https://regex101.com/r/oMsyeL/4
311 preg_match('/(?P<locale>[_\-][A-Za-z]{2}_[A-Za-z]{2})$|(?P<code>[_\-][A-Za-z]{2})$/', $post_id, $matches);
312
313 if(empty($matches))
314 return false;
315
316 // Cleanup matches
317 $lang = array();
318
319 foreach($matches as $key => $val){
320
321 if(is_int($key) || empty($val))
322 continue;
323
324 $lang = array(
325 'type' => $key,
326 'lang' => strtolower(substr($val, 1)), // Lowercase + Remove the first '_'
327 );
328
329 }
330
331 if(empty($lang))
332 return false;
333
334 // Get WPML/Polylang Languages List
335 $languages = $this->get_languages($lang['type']);
336 $languages = array_map('strtolower', $languages);
337
338 // Compare Matches vs WPML/Polylang Languages List
339 return in_array($lang['lang'], $languages);
340
341 }
342
343 function is_options_page($post_id){
344
345 // Get Options Pages
346 if($this->options_pages === false){
347
348 // Get ACF Options Pages
349 $options_pages = acf_get_array(acf_get_options_pages());
350 $list = wp_list_pluck($options_pages, 'post_id', true);
351
352 // Add 'Post Types List' location
353 $post_types = acf_get_post_types(array(
354 'show_ui' => 1,
355 'exclude' => array('attachment')
356 ));
357
358 if(!empty($post_types)){
359
360 foreach($post_types as $post_type){
361
362 $list[] = $post_type . '_options';
363
364 }
365
366 }
367
368 // Add 'Taxonomy List' location
369 $taxonomies = acf_get_taxonomies();
370
371 if(!empty($taxonomies)){
372
373 foreach($taxonomies as $taxonomy){
374
375 $list[] = 'tax_' . $taxonomy . '_options';
376
377 }
378
379 }
380
381 // Depreacted filter
382 $list = apply_filters_deprecated('acfe/modules/multilang/options', array($list), '0.8.8.2', 'acfe/modules/multilang/exclude_options');
383
384 // Include filter
385 $list = apply_filters('acfe/modules/multilang/include_options', $list);
386
387 // Exclude filter
388 $exclude = apply_filters('acfe/modules/multilang/exclude_options', array());
389
390 if(is_array($exclude) && !empty($exclude)){
391
392 foreach($list as $i => $option){
393
394 if(!in_array($option, $exclude))
395 continue;
396
397 unset($list[$i]);
398
399 }
400
401 $list = array_values($list);
402
403 }
404
405 $this->options_pages = $list;
406
407 }
408
409 if(is_array($this->options_pages) && !empty($this->options_pages)){
410
411 return in_array($post_id, $this->options_pages);
412
413 }
414
415 return false;
416
417 }
418
419 function get_languages($pluck = '', $type = '', $plugin = ''){
420
421 // Polylang
422 if($this->is_polylang || $plugin === 'polylang'){
423
424 return $this->polylang_get_languages($pluck, $type);
425
426 // WPML
427 }elseif($this->is_wpml || $plugin === 'wpml'){
428
429 return $this->wpml_get_languages($pluck, $type);
430
431 }
432
433 return array();
434
435 }
436
437 function options_page_message(){
438
439 $default_language = acf_get_setting('default_language');
440 $current_language = acf_get_setting('current_language');
441
442 $message = false;
443
444 // Polylang
445 if($this->is_polylang){
446
447 if(!$current_language)
448 $current_language = $default_language;
449
450 $message = "Language: {$current_language}";
451
452 $nice_language = false;
453 $nice_flag = false;
454
455 $languages = pll_languages_list(array(
456 'hide_empty' => false,
457 'fields' => false
458 ));
459
460 if($languages){
461
462 foreach($languages as $language){
463
464 if($language->locale !== $current_language)
465 continue;
466
467 $nice_language = $language->name;
468 $nice_flag = $language->flag_url;
469 break;
470
471 }
472
473 }
474
475 if($nice_language){
476
477 $message = "<img src='{$nice_flag}' style='margin-right:5px;vertical-align:-1px;' /> Language: {$nice_language}";
478
479 }
480
481 if($default_language === $current_language){
482
483 $message .= ' (Default)';
484
485 }
486
487 }
488
489 // WPML
490 elseif($this->is_wpml){
491
492 if($current_language === 'all')
493 $current_language = 'All';
494
495 $message = "Language: {$current_language}";
496
497 if($current_language !== 'All'){
498
499 $nice_language = false;
500 $nice_flag = false;
501
502 $languages = apply_filters('wpml_active_languages', null, array('skip_missing' => 0));
503
504 if($languages){
505
506 foreach($languages as $language){
507
508 if($language['language_code'] !== $current_language)
509 continue;
510
511 $nice_language = $language['native_name'];
512 $nice_flag = $language['country_flag_url'];
513 break;
514
515 }
516
517 }
518
519 if($nice_language){
520
521 $message = "<img src='{$nice_flag}' style='margin-right:5px;vertical-align:-1px; width:16px; height:11px;' /> Language: {$nice_language}";
522
523 }
524
525 }
526
527 }
528
529 if(empty($message))
530 return;
531
532 echo "<div class='misc-pub-section' style='padding-top:15px; padding-bottom:15px;'>{$message}</div>";
533
534
535 }
536
537 }
538
539 acf_new_instance('acfe_multilang');
540
541 endif;
542
543 /*
544 * Is Multilang Enabled
545 */
546 function acfe_is_multilang(){
547
548 return acf_get_instance('acfe_multilang')->is_multilang;
549
550 }
551
552 /*
553 * Get Multilang Data
554 */
555 function acfe_get_multilang(){
556
557 $wpml = acf_get_instance('acfe_multilang')->is_wpml;
558 $polylang = acf_get_instance('acfe_multilang')->is_polylang;
559
560 $data = array(
561 'dl' => acf_get_setting('default_language'),
562 'cl' => acf_get_setting('current_language'),
563 'wpml' => $wpml,
564 'polylang' => $polylang,
565 );
566
567 return $data;
568
569 }
570
571 /*
572 * Get Languages
573 */
574 function acfe_get_multilang_languages($pluck = '', $type = '', $plugin = ''){
575
576 return acf_get_instance('acfe_multilang')->get_languages($pluck, $type, $plugin);
577
578 }
579
580 /*
581 * Is Polylang
582 */
583 function acfe_is_polylang(){
584
585 return acf_get_instance('acfe_multilang')->is_polylang;
586
587 }
588
589 /*
590 * Is WPML
591 */
592 function acfe_is_wpml(){
593
594 return acf_get_instance('acfe_multilang')->is_wpml;
595
596 }
597
598 /*
599 * Get Post Language
600 */
601 function acfe_get_post_lang($post_id, $field = false){
602
603 // Bail early if not multilang
604 if(!acfe_is_multilang())
605 return false;
606
607 // Polylang
608 if(acfe_is_polylang()){
609
610 // Default field
611 if(!$field)
612 $field = 'locale';
613
614 return pll_get_post_language($post_id, $field);
615
616 // WPML
617 }elseif(acfe_is_wpml()){
618
619 $post_lang = apply_filters('wpml_post_language_details', NULL, $post_id);
620
621 // Default field
622 if(!$field)
623 $field = 'slug';
624
625 if($field === 'locale'){
626
627 return $post_lang['locale'];
628
629 }elseif($field === 'slug'){
630
631 return $post_lang['language_code'];
632
633 }elseif($field === 'name'){
634
635 return $post_lang['display_name'];
636
637 }
638
639 return false;
640
641 }
642
643 return false;
644
645 }
646
647 /*
648 * Get Post Translated
649 */
650 function acfe_get_post_translated($post_id, $lang = false){
651
652 // Bail early if not multilang
653 if(!acfe_is_multilang())
654 return $post_id;
655
656 // Default
657 $translated_post_id = $post_id;
658
659 // Polylang
660 if(acfe_is_polylang()){
661
662 $translated_post_id = pll_get_post($post_id, $lang);
663
664 // WPML
665 }elseif(acfe_is_wpml()){
666
667 $translated_post_id = apply_filters('wpml_object_id', $post_id, 'post', false, $lang);
668
669 }
670
671 /*
672 if(empty($translated_post_id))
673 return $post_id;
674 */
675
676 return $translated_post_id;
677
678 }
679
680 /*
681 * Get Default Post Translated
682 */
683 function acfe_get_post_translated_default($post_id){
684
685 // Get translated post id
686 $translated_post_id = acfe_get_post_translated($post_id, acf_get_setting('default_language'));
687
688 // Fallback to current
689 if(empty($translated_post_id))
690 return $post_id;
691
692 return $translated_post_id;
693
694 }
695
696 /*
697 * Translate String
698 */
699 function acfe_translate($string, $name = false, $textdomain = 'acfe'){
700
701 // Bail early
702 if(!acfe_is_multilang() || empty($string))
703 return __($string, $textdomain);
704
705 // Name compatibility
706 if(empty($name))
707 $name = $string;
708
709 // WPML
710 if(acfe_is_wpml()){
711
712 // Translate (Register string during save)
713 return apply_filters('wpml_translate_single_string', $string, $textdomain, $name);
714
715 }
716
717 // PolyLang
718 if(acfe_is_polylang()){
719
720 // Register string
721 pll_register_string($name, $string, $textdomain);
722
723 // Translate
724 return pll__($string);
725
726 }
727
728 // Default Translate
729 return __($string, $textdomain);
730
731 }
732
733 /*
734 * Deprecated Translate String
735 */
736 function acfe__($string, $name = false, $textdomain = 'acfe'){
737
738 return acfe_translate($string, $name, $textdomain);
739
740 }
741
742 /*
743 * Deprecated Translate String (echo)
744 */
745 function acfe__e($string, $name = false, $textdomain = 'acfe'){
746
747 echo acfe_translate($string, $name, $textdomain);
748
749 }