PluginProbe
Cooked – Recipe Management / trunk
Cooked – Recipe Management vtrunk
1.16.0 1.15.0 trunk 1.10.0 1.11.0 1.11.1 1.11.2 1.11.3 1.11.4 1.12.0 1.13.0 1.14.0 1.7.10 1.7.11 1.7.12 1.7.13 1.7.15.1 1.7.15.3 1.7.15.4 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 All 36 releases
cooked / includes / class.cooked-multilingual.php

class.cooked-multilingual.php in Cooked – Recipe Management trunk, at includes/class.cooked-multilingual.php

274 lines 8.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Cooked Multilingual Support
4 *
5 * @package Cooked
6 * @subpackage Multilingual Support
7 * @since 1.12.0
8 */
9
10 // Exit if accessed directly
11 if ( ! defined( 'ABSPATH' ) ) exit;
12
13 /**
14 * Cooked_Multilingual Class
15 *
16 * This class handles multilingual plugin support (Polylang, WPML, etc.).
17 *
18 * @since 1.12.0
19 */
20 class Cooked_Multilingual {
21
22 /**
23 * Constructor
24 */
25 public function __construct() {
26 add_action( 'admin_notices', [ $this, 'translation_notice' ] );
27 }
28
29 /**
30 * Check if Polylang is active
31 *
32 * @return bool
33 */
34 public static function is_polylang_active() {
35 return function_exists( 'pll_get_post' );
36 }
37
38 /**
39 * Check if WPML is active
40 *
41 * Note: We check for ICL_SITEPRESS_VERSION constant which is specific to WPML.
42 * We can't just check function_exists('icl_object_id') because Polylang
43 * provides WPML compatibility functions.
44 *
45 * @return bool
46 */
47 public static function is_wpml_active() {
48 return defined( 'ICL_SITEPRESS_VERSION' );
49 }
50
51 /**
52 * Check if any multilingual plugin is active
53 *
54 * @return bool
55 */
56 public static function is_multilingual_active() {
57 return self::is_polylang_active() || self::is_wpml_active();
58 }
59
60 /**
61 * Get the current language code
62 *
63 * @return string|false Language code or false if not available
64 */
65 public static function get_current_language() {
66 // Polylang support
67 if ( self::is_polylang_active() && function_exists( 'pll_current_language' ) ) {
68 return pll_current_language();
69 }
70 // WPML support
71 elseif ( self::is_wpml_active() ) {
72 return apply_filters( 'wpml_current_language', null );
73 }
74 return false;
75 }
76
77 /**
78 * Get the browse page ID for the current language
79 *
80 * This method returns the translated browse page ID when a multilingual plugin is active.
81 * Use this when checking is_page() or generating URLs with get_permalink().
82 *
83 * @param int|bool $browse_page_id Optional. The default browse page ID. If not provided, gets from settings.
84 * @return int|bool The translated page ID or original, false if not set
85 */
86 public static function get_browse_page_id( $browse_page_id = null ) {
87 // If no ID provided, get from settings
88 if ( $browse_page_id === null ) {
89 global $_cooked_settings;
90 $browse_page_id = ! empty( $_cooked_settings['browse_page'] ) ? $_cooked_settings['browse_page'] : false;
91 }
92
93 if ( ! $browse_page_id ) {
94 return false;
95 }
96
97 // Polylang support (check first, as it's more common)
98 if ( self::is_polylang_active() ) {
99 $translated_id = pll_get_post( $browse_page_id );
100 if ( $translated_id ) {
101 return $translated_id;
102 }
103 }
104 // WPML support (only if Polylang is not active)
105 elseif ( self::is_wpml_active() ) {
106 $translated_id = icl_object_id( $browse_page_id, 'page', true );
107 if ( $translated_id ) {
108 return $translated_id;
109 }
110 }
111
112 return $browse_page_id;
113 }
114
115 /**
116 * Get all browse page translations
117 *
118 * Returns an array of all translated browse page IDs and slugs.
119 * Useful for creating rewrite rules for each language.
120 *
121 * @return array Array of ['lang' => ['id' => int, 'slug' => string]]
122 */
123 public static function get_all_browse_pages() {
124 global $_cooked_settings;
125
126 $pages = [];
127 $default_page_id = ! empty( $_cooked_settings['browse_page'] ) ? $_cooked_settings['browse_page'] : false;
128
129 if ( ! $default_page_id ) {
130 return $pages;
131 }
132
133 // Default page (always include)
134 $pages['default'] = [
135 'id' => $default_page_id,
136 'slug' => self::get_page_slug( $default_page_id )
137 ];
138
139 // Polylang translations (check first, as it's more common)
140 if ( self::is_polylang_active() && function_exists( 'pll_get_post_translations' ) ) {
141 $translations = pll_get_post_translations( $default_page_id );
142 foreach ( $translations as $lang => $translated_id ) {
143 if ( $translated_id && $translated_id != $default_page_id ) {
144 $pages[ $lang ] = [
145 'id' => $translated_id,
146 'slug' => self::get_page_slug( $translated_id )
147 ];
148 }
149 }
150 }
151 // WPML translations (only if Polylang is not active)
152 elseif ( self::is_wpml_active() ) {
153 $languages = apply_filters( 'wpml_active_languages', null );
154 if ( is_array( $languages ) ) {
155 foreach ( $languages as $lang_code => $lang_data ) {
156 $translated_id = icl_object_id( $default_page_id, 'page', false, $lang_code );
157 if ( $translated_id && $translated_id != $default_page_id ) {
158 $pages[ $lang_code ] = [
159 'id' => $translated_id,
160 'slug' => self::get_page_slug( $translated_id )
161 ];
162 }
163 }
164 }
165 }
166
167 return $pages;
168 }
169
170 /**
171 * Get page slug from ID
172 *
173 * @param int $page_id The page ID
174 * @return string|null The page slug (empty string for homepage), or null if page doesn't exist
175 */
176 private static function get_page_slug( $page_id ) {
177 if ( ! $page_id ) {
178 return null;
179 }
180
181 $permalink = get_permalink( $page_id );
182 if ( ! $permalink ) {
183 return null;
184 }
185
186 // Returns empty string for homepage, which is valid
187 return ltrim( untrailingslashit( str_replace( home_url(), '', $permalink ) ), '/' );
188 }
189
190 /**
191 * Check if browse page has translations
192 *
193 * @return array Array of missing language codes
194 */
195 public static function get_missing_translations() {
196 global $_cooked_settings;
197
198 $missing = [];
199 $default_page_id = ! empty( $_cooked_settings['browse_page'] ) ? $_cooked_settings['browse_page'] : false;
200
201 if ( ! $default_page_id ) {
202 return $missing;
203 }
204
205 // Check Polylang translations (check first, as it's more common)
206 if ( self::is_polylang_active() && function_exists( 'pll_languages_list' ) && function_exists( 'pll_get_post_translations' ) ) {
207 $languages = pll_languages_list( [ 'fields' => 'slug' ] );
208 $translations = pll_get_post_translations( $default_page_id );
209
210 foreach ( $languages as $lang ) {
211 if ( ! isset( $translations[ $lang ] ) || ! $translations[ $lang ] ) {
212 $missing[] = $lang;
213 }
214 }
215 }
216 // Check WPML translations (only if Polylang is not active)
217 elseif ( self::is_wpml_active() ) {
218 $languages = apply_filters( 'wpml_active_languages', null );
219 if ( is_array( $languages ) ) {
220 foreach ( $languages as $lang_code => $lang_data ) {
221 $translated_id = icl_object_id( $default_page_id, 'page', false, $lang_code );
222 if ( ! $translated_id ) {
223 $missing[] = $lang_code;
224 }
225 }
226 }
227 }
228
229 return $missing;
230 }
231
232 /**
233 * Display admin notice about missing browse page translations
234 */
235 public function translation_notice() {
236 // Only show on Cooked settings page
237 if ( ! isset( $_GET['page'] ) || $_GET['page'] !== 'cooked_settings' ) {
238 return;
239 }
240
241 // Only show if multilingual plugin is active
242 if ( ! self::is_multilingual_active() ) {
243 return;
244 }
245
246 global $_cooked_settings;
247
248 // Only show if browse page is set
249 if ( empty( $_cooked_settings['browse_page'] ) ) {
250 return;
251 }
252
253 $missing = self::get_missing_translations();
254
255 if ( ! empty( $missing ) ) {
256 $plugin_name = self::is_polylang_active() ? 'Polylang' : 'WPML';
257 $class = 'notice notice-warning';
258 $message = sprintf(
259 '<strong>%s</strong> %s <strong>%s</strong>',
260 __( 'Multilingual Setup:', 'cooked' ),
261 __( 'Your Browse/Search Recipes page is missing translations for:', 'cooked' ),
262 strtoupper( implode( ', ', $missing ) )
263 );
264 $message .= '<br><em>' . sprintf(
265 /* translators: %s is the multilingual plugin name (Polylang or WPML) */
266 __( 'Create translations of your browse page in %s for full multilingual support.', 'cooked' ),
267 $plugin_name
268 ) . '</em>';
269
270 printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), $message );
271 }
272 }
273 }
274