PluginProbe
Polylang / 2.3.2
Polylang v2.3.2
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.3.2, at include/olt-manager.php

248 lines 8.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * It is best practice that plugins do nothing before plugins_loaded is fired
5 * so it is what Polylang intends to do
6 * but some plugins load their text domain as soon as loaded, thus before plugins_loaded is fired
7 * this class differs text domain loading until the language is defined
8 * either in a plugins_loaded action or in a wp action ( when the language is set from content on frontend )
9 *
10 * @since 1.2
11 */
12 class PLL_OLT_Manager {
13 static protected $instance; // For singleton
14 protected $default_locale;
15 protected $list_textdomains = array(); // All text domains
16 public $labels = array(); // Post types and taxonomies labels to translate
17
18 /**
19 * Constructor: setups relevant filters
20 *
21 * @since 1.2
22 */
23 public function __construct() {
24 // Allows Polylang to be the first plugin loaded ;-)
25 add_filter( 'pre_update_option_active_plugins', array( $this, 'make_polylang_first' ) );
26 add_filter( 'pre_update_option_active_sitewide_plugins', array( $this, 'make_polylang_first' ) );
27
28 // Overriding load text domain only on front since WP 4.7
29 // FIXME test get_user_locale for backward compatibility with WP < 4.7
30 if ( is_admin() && function_exists( 'get_user_locale' ) ) {
31 return;
32 }
33
34 // Saves the default locale before we start any language manipulation
35 $this->default_locale = get_locale();
36
37 // Filters for text domain management
38 add_filter( 'load_textdomain_mofile', array( $this, 'load_textdomain_mofile' ), 10, 2 );
39 add_filter( 'gettext', array( $this, 'gettext' ), 10, 3 );
40 add_filter( 'gettext_with_context', array( $this, 'gettext_with_context' ), 10, 4 );
41
42 if ( ! Polylang::is_ajax_on_front() ) {
43 // Loads text domains
44 add_action( 'pll_language_defined', array( $this, 'load_textdomains' ), 2 ); // After PLL_Frontend::pll_language_defined
45 add_action( 'pll_no_language_defined', array( $this, 'load_textdomains' ) );
46 }
47 }
48
49 /**
50 * Access to the single instance of the class
51 *
52 * @since 1.7
53 *
54 * @return object
55 */
56 static public function instance() {
57 if ( empty( self::$instance ) ) {
58 self::$instance = new self();
59 }
60
61 return self::$instance;
62 }
63
64 /**
65 * Loads text domains
66 *
67 * @since 0.1
68 */
69 public function load_textdomains() {
70 // Our load_textdomain_mofile filter has done its job. let's remove it before calling load_textdomain
71 remove_filter( 'load_textdomain_mofile', array( $this, 'load_textdomain_mofile' ), 10, 2 );
72 remove_filter( 'gettext', array( $this, 'gettext' ), 10, 3 );
73 remove_filter( 'gettext_with_context', array( $this, 'gettext_with_context' ), 10, 4 );
74 $new_locale = get_locale();
75
76 // Don't try to save time for en_US as some users have theme written in another language
77 // Now we can load all overridden text domains with the right language
78 if ( ! empty( $this->list_textdomains ) ) {
79
80 // Since WP 4.7 we need to reset the internal cache of _get_path_to_translation when switching from any locale to en_US
81 // See WP_Locale_Switcher::change_locale()
82 // FIXME test _get_path_to_translation for backward compatibility with WP < 4.7
83 if ( function_exists( '_get_path_to_translation' ) ) {
84 _get_path_to_translation( null, true );
85 }
86
87 foreach ( $this->list_textdomains as $textdomain ) {
88 // Since WP 4.6, plugins translations are first loaded from wp-content/languages
89 if ( ! load_textdomain( $textdomain['domain'], str_replace( "{$this->default_locale}.mo", "$new_locale.mo", $textdomain['mo'] ) ) ) {
90 // Since WP 3.5 themes may store languages files in /wp-content/languages/themes
91 if ( ! load_textdomain( $textdomain['domain'], WP_LANG_DIR . "/themes/{$textdomain['domain']}-$new_locale.mo" ) ) {
92 // Since WP 3.7 plugins may store languages files in /wp-content/languages/plugins
93 load_textdomain( $textdomain['domain'], WP_LANG_DIR . "/plugins/{$textdomain['domain']}-$new_locale.mo" );
94 }
95 }
96 }
97 }
98
99 // First remove taxonomies and post_types labels that we don't need to translate
100 $taxonomies = get_taxonomies( array( '_pll' => true ) );
101 $post_types = get_post_types( array( '_pll' => true ) );
102
103 // We don't need to translate core taxonomies and post types labels when setting the language from the url
104 // As they will be translated when registered the second time
105 if ( ! did_action( 'setup_theme' ) ) {
106 $taxonomies = array_merge( get_taxonomies( array( '_builtin' => true ) ), $taxonomies );
107 $post_types = array_merge( get_post_types( array( '_builtin' => true ) ), $post_types );
108 }
109
110 // Translate labels of post types and taxonomies
111 foreach ( array_diff_key( $GLOBALS['wp_taxonomies'], array_flip( $taxonomies ) ) as $tax ) {
112 $this->translate_labels( $tax );
113 }
114 foreach ( array_diff_key( $GLOBALS['wp_post_types'], array_flip( $post_types ) ) as $pt ) {
115 $this->translate_labels( $pt );
116 }
117
118 // Act only if the language has not been set early ( before default textdomain loading and $wp_locale creation )
119 if ( did_action( 'after_setup_theme' ) ) {
120 // Reinitializes wp_locale for weekdays and months
121 unset( $GLOBALS['wp_locale'] );
122 $GLOBALS['wp_locale'] = new WP_Locale();
123 }
124
125 /**
126 * Fires after the post types and taxonomies labels have been translated
127 * This allows plugins to translate text the same way we do for post types and taxonomies labels
128 *
129 * @since 1.2
130 *
131 * @param array $labels list of strings to trnaslate
132 */
133 do_action_ref_array( 'pll_translate_labels', array( &$this->labels ) );
134
135 // Free memory
136 unset( $this->default_locale, $this->list_textdomains, $this->labels );
137 }
138
139 /**
140 * FIXME: Backward compatibility with Polylang for WooCommerce < 0.3.4
141 * To remove in Polylang 2.1
142 *
143 * @since 0.1
144 *
145 * @param bool $bool not used
146 * @param string $domain text domain name
147 * @param string $mofile translation file name
148 * @return bool
149 */
150 public function mofile( $bool, $domain, $mofile ) {
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 $type->labels->$key = $translated[ $label ] = isset( $this->labels[ $label ]['context'] ) ?
222 _x( $label, $this->labels[ $label ]['context'], $this->labels[ $label ]['domain'] ) :
223 __( $label, $this->labels[ $label ]['domain'] );
224 }
225 else {
226 $type->labels->$key = $translated[ $label ];
227 }
228 }
229 }
230 }
231
232 /**
233 * Allows Polylang to be the first plugin loaded ;- )
234 *
235 * @since 1.2
236 *
237 * @param array $plugins list of active plugins
238 * @return array list of active plugins
239 */
240 public function make_polylang_first( $plugins ) {
241 if ( $key = array_search( POLYLANG_BASENAME, $plugins ) ) {
242 unset( $plugins[ $key ] );
243 array_unshift( $plugins, POLYLANG_BASENAME );
244 }
245 return $plugins;
246 }
247 }
248