PluginProbe
Polylang / 2.9
Polylang v2.9
3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 3.0.3 All 233 releases
polylang / include / olt-manager.php

olt-manager.php in Polylang 2.9, at include/olt-manager.php

250 lines 8.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package Polylang
4 */
5
6 /**
7 * It is best practice that plugins do nothing before plugins_loaded is fired
8 * so it is what Polylang intends to do
9 * but some plugins load their text domain as soon as loaded, thus before plugins_loaded is fired
10 * this class differs text domain loading until the language is defined
11 * either in a plugins_loaded action or in a wp action ( when the language is set from content on frontend )
12 *
13 * @since 1.2
14 */
15 class PLL_OLT_Manager {
16 protected static $instance; // For singleton
17 protected $default_locale;
18 protected $list_textdomains = array(); // All text domains
19 public $labels = array(); // Post types and taxonomies labels to translate
20
21 /**
22 * Constructor: setups relevant filters
23 *
24 * @since 1.2
25 */
26 public function __construct() {
27 // Allows Polylang to be the first plugin loaded ;-)
28 add_filter( 'pre_update_option_active_plugins', array( $this, 'make_polylang_first' ) );
29 add_filter( 'pre_update_option_active_sitewide_plugins', array( $this, 'make_polylang_first' ) );
30
31 // Overriding load text domain only on front since WP 4.7
32 // FIXME test get_user_locale for backward compatibility with WP < 4.7
33 if ( is_admin() && ! Polylang::is_ajax_on_front() && function_exists( 'get_user_locale' ) ) {
34 return;
35 }
36
37 // Saves the default locale before we start any language manipulation
38 $this->default_locale = get_locale();
39
40 // Filters for text domain management
41 add_filter( 'load_textdomain_mofile', array( $this, 'load_textdomain_mofile' ), 10, 2 );
42 add_filter( 'gettext', array( $this, 'gettext' ), 10, 3 );
43 add_filter( 'gettext_with_context', array( $this, 'gettext_with_context' ), 10, 4 );
44
45 // Loads text domains
46 add_action( 'pll_language_defined', array( $this, 'load_textdomains' ), 2 ); // After PLL_Frontend::pll_language_defined
47 add_action( 'pll_no_language_defined', array( $this, 'load_textdomains' ) );
48 }
49
50 /**
51 * Access to the single instance of the class
52 *
53 * @since 1.7
54 *
55 * @return object
56 */
57 public static function instance() {
58 if ( empty( self::$instance ) ) {
59 self::$instance = new self();
60 }
61
62 return self::$instance;
63 }
64
65 /**
66 * Loads text domains
67 *
68 * @since 0.1
69 */
70 public function load_textdomains() {
71 // Our load_textdomain_mofile filter has done its job. let's remove it before calling load_textdomain
72 remove_filter( 'load_textdomain_mofile', array( $this, 'load_textdomain_mofile' ), 10, 2 );
73 remove_filter( 'gettext', array( $this, 'gettext' ), 10, 3 );
74 remove_filter( 'gettext_with_context', array( $this, 'gettext_with_context' ), 10, 4 );
75 $new_locale = get_locale();
76
77 // Don't try to save time for en_US as some users have theme written in another language
78 // Now we can load all overridden text domains with the right language
79 if ( ! empty( $this->list_textdomains ) ) {
80 /*
81 * FIXME: Backward compatibility with WP < 5.6
82 * From WP 4.7 to 5.5, we need to reset the internal cache of _get_path_to_translation when switching from any locale to en_US.
83 * See WP_Locale_Switcher::change_locale()
84 */
85 if ( ! class_exists( 'WP_Textdomain_Registry' ) && function_exists( '_get_path_to_translation' ) ) {
86 _get_path_to_translation( null, true );
87 }
88
89 foreach ( $this->list_textdomains as $textdomain ) {
90 // Since WP 4.6, plugins translations are first loaded from wp-content/languages
91 if ( ! load_textdomain( $textdomain['domain'], str_replace( "{$this->default_locale}.mo", "$new_locale.mo", $textdomain['mo'] ) ) ) {
92 // Since WP 3.5 themes may store languages files in /wp-content/languages/themes
93 if ( ! load_textdomain( $textdomain['domain'], WP_LANG_DIR . "/themes/{$textdomain['domain']}-$new_locale.mo" ) ) {
94 // Since WP 3.7 plugins may store languages files in /wp-content/languages/plugins
95 load_textdomain( $textdomain['domain'], WP_LANG_DIR . "/plugins/{$textdomain['domain']}-$new_locale.mo" );
96 }
97 }
98 }
99 }
100
101 // First remove taxonomies and post_types labels that we don't need to translate
102 $taxonomies = get_taxonomies( array( '_pll' => true ) );
103 $post_types = get_post_types( array( '_pll' => true ) );
104
105 // We don't need to translate core taxonomies and post types labels when setting the language from the url
106 // As they will be translated when registered the second time
107 if ( ! did_action( 'setup_theme' ) ) {
108 $taxonomies = array_merge( get_taxonomies( array( '_builtin' => true ) ), $taxonomies );
109 $post_types = array_merge( get_post_types( array( '_builtin' => true ) ), $post_types );
110 }
111
112 // Translate labels of post types and taxonomies
113 foreach ( array_diff_key( $GLOBALS['wp_taxonomies'], array_flip( $taxonomies ) ) as $tax ) {
114 $this->translate_labels( $tax );
115 }
116 foreach ( array_diff_key( $GLOBALS['wp_post_types'], array_flip( $post_types ) ) as $pt ) {
117 $this->translate_labels( $pt );
118 }
119
120 // Act only if the language has not been set early ( before default textdomain loading and $wp_locale creation )
121 if ( did_action( 'after_setup_theme' ) ) {
122 // Reinitializes wp_locale for weekdays and months
123 unset( $GLOBALS['wp_locale'] );
124 $GLOBALS['wp_locale'] = new WP_Locale();
125 }
126
127 /**
128 * Fires after the post types and taxonomies labels have been translated
129 * This allows plugins to translate text the same way we do for post types and taxonomies labels
130 *
131 * @since 1.2
132 *
133 * @param array $labels list of strings to trnaslate
134 */
135 do_action_ref_array( 'pll_translate_labels', array( &$this->labels ) );
136
137 // Free memory
138 unset( $this->default_locale, $this->list_textdomains, $this->labels );
139 }
140
141 /**
142 * FIXME: Backward compatibility with Polylang for WooCommerce < 0.3.4
143 * Was formerly hooked to the filter 'override_load_textdomain'
144 *
145 * @since 0.1
146 *
147 * @param bool $bool Whether to override the .mo file loading.
148 * @return bool
149 */
150 public function mofile( $bool ) {
151 return $bool;
152 }
153
154 /**
155 * Saves all text domains in a table for later usage
156 * It replaces the 'override_load_textdomain' filter used since 0.1
157 *
158 * @since 2.0.4
159 *
160 * @param string $mofile translation file name
161 * @param string $domain text domain name
162 * @return bool
163 */
164 public function load_textdomain_mofile( $mofile, $domain ) {
165 // On multisite, 2 files are sharing the same domain so we need to distinguish them
166 if ( 'default' === $domain && false !== strpos( $mofile, '/ms-' ) ) {
167 $this->list_textdomains['ms-default'] = array( 'mo' => $mofile, 'domain' => $domain );
168 } else {
169 $this->list_textdomains[ $domain ] = array( 'mo' => $mofile, 'domain' => $domain );
170 }
171 return ''; // Hack to prevent WP loading text domains as we will load them all later
172 }
173
174 /**
175 * Saves post types and taxonomies labels for a later usage
176 *
177 * @since 0.9
178 *
179 * @param string $translation not used
180 * @param string $text string to translate
181 * @param string $domain text domain
182 * @return string unmodified $translation
183 */
184 public function gettext( $translation, $text, $domain ) {
185 if ( is_string( $text ) ) { // Avoid a warning with some buggy plugins which pass an array
186 $this->labels[ $text ] = array( 'domain' => $domain );
187 }
188 return $translation;
189 }
190
191 /**
192 * Saves post types and taxonomies labels for a later usage
193 *
194 * @since 0.9
195 *
196 * @param string $translation not used
197 * @param string $text string to translate
198 * @param string $context some comment to describe the context of string to translate
199 * @param string $domain text domain
200 * @return string unmodified $translation
201 */
202 public function gettext_with_context( $translation, $text, $context, $domain ) {
203 $this->labels[ $text ] = array( 'domain' => $domain, 'context' => $context );
204 return $translation;
205 }
206
207 /**
208 * Translates post types and taxonomies labels once the language is known
209 *
210 * @since 0.9
211 *
212 * @param object $type either a post type or a taxonomy
213 */
214 public function translate_labels( $type ) {
215 // Use static array to avoid translating several times the same ( default ) labels
216 static $translated = array();
217
218 foreach ( $type->labels as $key => $label ) {
219 if ( is_string( $label ) && isset( $this->labels[ $label ] ) ) {
220 if ( empty( $translated[ $label ] ) ) {
221 // PHPCS:disable WordPress.WP.I18n
222 $type->labels->$key = $translated[ $label ] = isset( $this->labels[ $label ]['context'] ) ?
223 _x( $label, $this->labels[ $label ]['context'], $this->labels[ $label ]['domain'] ) :
224 __( $label, $this->labels[ $label ]['domain'] );
225 // PHPCS:enable
226 }
227 else {
228 $type->labels->$key = $translated[ $label ];
229 }
230 }
231 }
232 }
233
234 /**
235 * Allows Polylang to be the first plugin loaded ;- )
236 *
237 * @since 1.2
238 *
239 * @param array $plugins list of active plugins
240 * @return array list of active plugins
241 */
242 public function make_polylang_first( $plugins ) {
243 if ( $key = array_search( POLYLANG_BASENAME, $plugins ) ) {
244 unset( $plugins[ $key ] );
245 array_unshift( $plugins, POLYLANG_BASENAME );
246 }
247 return $plugins;
248 }
249 }
250