Overview

Classes

  • CMLLanguage
  • CMLPost
  • CMLTranslations
  • CMLUtils

Functions

  • cml_dropdown_langs
  • cml_get_browser_lang
  • cml_get_menu
  • cml_get_notice
  • cml_get_the_link
  • cml_is_homepage
  • cml_show_flags
  • Overview
  • Function
  • Tree
  1: <?php
  2: 
  3: /**
  4:  * Check if current url ( or $url ) is the homepage
  5:  *
  6:  * If is set a static page as homepage, the plugin check if
  7:  * current page is front page or its translation
  8:  *
  9:  * @param string $url - ( optional ) url to check
 10:  * 
 11:  */
 12: function cml_is_homepage( $url = null ) {
 13:   global $wpdb;
 14: 
 15:   if( ! empty( $wpdb ) && method_exists( $wpdb, 'is_category' ) ) {
 16:     if( is_category() || is_archive() ) return false;
 17:   }
 18: 
 19:   //Controllo se è stata impostata una pagina "statica" se l'id di questa è = a quello della statica
 20:   if( cml_use_static_page() ) {
 21:     global $wp_query;
 22:     $static_id = array( get_option( "page_for_posts" ), get_option( "page_on_front" ) );
 23: 
 24:     $lang_id = CMLLanguage::get_current_id();
 25: 
 26:     /*
 27:      * on some site get_queried_object_id isn't available on start
 28:      * and I get:
 29:      * Fatal error: Call to a member function get_queried_object_id() on a non-object
 30:      *
 31:      * So ensure that method exists, otherwise I use get_the_ID() method
 32:      */
 33:     /*
 34:      * If I call get_queried_object_id in the footer can happens that
 35:      * queried_object_id is different from "real" queried_object,
 36:      * so I store that info in $GLOBALS to avoid this problem :)
 37:      */
 38:     if( ! isset( $GLOBALS[ '_cml_get_queried_object_id' ] ) ) {
 39:       if( ! empty( $wpdb ) && method_exists( $wpdb, 'get_queried_object' ) ) {
 40:         $GLOBALS[ '_cml_get_queried_object_id' ] = get_queried_object()->ID;
 41:         $GLOBALS[ '_cml_get_queried_object' ] = get_queried_object();
 42: 
 43:         $the_id = & $GLOBALS[ '_cml_get_queried_object_id' ];
 44:       } else {
 45:         if( is_object( get_post() ) ) {
 46:           $the_id = get_the_ID();
 47:           
 48:           $GLOBALS[ '_cml_get_queried_object_id' ] = $the_id;
 49:         }
 50:       }
 51:     } else {
 52:       $the_id = $GLOBALS[ '_cml_get_queried_object_id' ];
 53:     }
 54: 
 55:     if( ! empty( $the_id ) ) {
 56:       if( in_array( $the_id, $static_id ) ) return true;    //Yes, it is :)
 57: 
 58:       //Is a translation of front page?
 59:       $linked = CMLPost::get_translation( CMLLanguage::get_current_id(), $the_id  );
 60:       if( ! empty( $linked ) ) {
 61:         return in_array( $linked, $static_id );
 62:       }
 63:     }
 64:   }
 65: 
 66:   //I can't use is_home(), because it return empty value, so I have to check
 67:   //it manually
 68:   if( ! empty( $wpdb ) && method_exists( $wpdb, 'is_home' ) ) {
 69:     return is_home();
 70:   }
 71: 
 72:   //Remove language information by url
 73:   CMLUtils::clear_url();
 74: 
 75:   return trailingslashit( CMLUtils::get_clean_url() ) == trailingslashit( CMLUtils::home_url() );
 76: }
 77: 
 78: /**
 79:  * @ignore
 80:  * @internal
 81:  *
 82:  * get page by path
 83:  *
 84:  * On some site I can't use url_to_postid() because
 85:  * $wp_reqruite is empty...
 86:  * 
 87:  */
 88: function cml_get_page_id_by_path($url, $types = null) {
 89:   $url = untrailingslashit( $url );
 90:   $plinks = explode( "/", $url );
 91: 
 92:   if( $types == null ) {
 93:     $types = array_keys( get_post_types() );
 94:   }
 95: 
 96:   $p = cml_get_page_by_path( $url, OBJECT, $types );
 97:   $the_id = is_object( $p ) ? $p->ID : 0;
 98: 
 99:   return $the_id;
100: }
101: 
102: /**
103:  * @ignore
104:  * @internal
105:  *
106:  * This is modified version of wordpress function get_page_by_path,
107:  * because original one doesn't works correctly for me
108:  *
109:  * @since 2.1.0
110:  * @uses $wpdb
111:  *
112:  * @param string $page_path Page path
113:  * @param string $output Optional. Output type. OBJECT, ARRAY_N, or ARRAY_A. Default OBJECT.
114:  * @param array $post_type Optional. Post type. Default page.
115:  * @return WP_Post|null WP_Post on success or null on failure
116:  */
117: function cml_get_page_by_path($page_path, $output = OBJECT, $post_type = array('page')) {
118:     global $wpdb;
119: 
120:     $page_path = rawurlencode(urldecode($page_path));
121:     $page_path = str_replace('%2F', '/', $page_path);
122:     $page_path = str_replace('%20', ' ', $page_path);
123:     $parts = explode( '/', trim( $page_path, '/' ) );
124:     $parts = array_map( 'esc_sql', $parts );
125:     $parts = array_map( 'sanitize_title_for_query', $parts );
126: 
127:     $in_string = "'". implode( "','", $parts ) . "'";
128:     $post_type_sql = implode( "','", $post_type );
129: //     $wpdb->escape_by_ref( $post_type_sql );
130: 
131:     if( empty( $in_string ) ) {
132:       return;
133:     }
134: 
135:     $query = "SELECT ID, post_name, post_parent, post_type FROM $wpdb->posts WHERE post_name IN ($in_string) AND (post_type IN ( '$post_type_sql' ) ) AND post_status = 'publish'";
136:     $pages = $wpdb->get_results( $query, OBJECT_K );
137:     $revparts = array_reverse( $parts );
138: 
139:     $foundid = 0;
140:     foreach ( (array) $pages as $page ) {
141:         if ( $page->post_name == $revparts[0] ) {
142:             $count = 0;
143:             $p = $page;
144: 
145:             while ( $p->post_parent != 0 && isset( $pages[ $p->post_parent ] ) ) {
146:                 $count++;
147:                 $parent = $pages[ $p->post_parent ];
148:                 if ( ! isset( $revparts[ $count ] ) || $parent->post_name != $revparts[ $count ] )
149:                     break;
150:                 $p = $parent;
151:             }
152: 
153:             //if ( $p->post_parent == 0 && $count + 1 == count( $revparts ) && $p->post_name == $revparts[ $count ] ) {
154:             if ( $p->post_parent == 0 && $p->post_name == $revparts[ $count ] ) {
155:               $foundid = $page->ID;
156:               if ( $page->post_type == $post_type )
157:                   break;
158:             }
159:         }
160:     }
161: 
162:     if ( $foundid )
163:         return get_post( $foundid, $output );
164: 
165:     return null;
166: }
167: 
168: /**
169:  * return link of current page in according to selected $language, so if $result != current language
170:  * this function will return its translation link.
171:  *
172:  * @param stdObject $result - language object ( i.e. CMLLanguage::get_default() ) used to translate current link
173:  * @param boolean $linked - true, return linked translation, false return homepage link
174:  * @param boolean $only_existings - return linked post only if it exists, otherwise return blank link
175:  * @param boolean $queried - use get_queried_object_id instead of get_the_ID
176:  *
177:  * return string
178:  */
179: function cml_get_the_link( $result, $linked = true, $only_existings = false, $queried = false ) {
180:   global $wpCeceppaML, $_cml_settings;
181: 
182:   if( $queried && ( cml_is_homepage() || is_search() ) ) { //&& cml_use_static_page() ) {
183:     //current page is homepage?
184:     $link = CMLUtils::get_home_url( $result->cml_language_slug );
185: 
186:     if( is_search() ) {
187:       if( isset( $_GET[ 's' ] ) ) {
188:         $args[ 's' ] = esc_attr( $_GET[ 's' ] );
189:       }
190: 
191:       if( CMLUtils::get_url_mode() <= PRE_LANG ) {
192:         $args[ 'lang' ] = $result->cml_language_slug;
193:       }
194: 
195:       $link = add_query_arg( $args, trailingslashit( $link ) );
196:     }
197:   } else {
198:     $GLOBALS[ '_cml_force_home_slug' ] = $result->cml_language_slug;
199:     
200:     //I have to force language to $result one
201:     $wpCeceppaML->force_category_lang( $result->id );
202: 
203:     if( $queried ) {
204:       if( empty( $GLOBALS[ '_cml_get_queried_object' ] ) ) {
205:         $GLOBALS[ '_cml_get_queried_object' ] = get_queried_object();
206:       }
207:       $q = & $GLOBALS[ '_cml_get_queried_object' ];
208:       
209:       $is_category = isset( $q->taxonomy ) && "category" == $q->taxonomy;
210:       $is_single = isset( $q->ID );
211:       $is_page = $is_single;
212:       $the_id = ( $is_single ) ? $q->ID : 0;
213:       $is_tag = isset( $q->taxonomy ) && "post_tag" == $q->taxonomy;
214: 
215:       if( empty( $q ) ) {
216:         $is_404 = is_404();
217:       }
218:     } else {
219:       $is_category = is_category();
220:       $is_single = is_single();
221:       $is_page = is_page();
222:       $the_id = get_the_ID();
223:       $is_404 = is_404();
224:       $is_tag = is_tag();
225:     }
226: 
227:     /* Collego la categoria della lingua attuale con quella della linga della bandierina */
228:     $link = "";
229: 
230:     if( ! in_the_loop() ) {
231:       $lang_id = CMLLanguage::get_current_id();
232:     } else
233:       $lang_id = CMLLanguage::get_id_by_post_id( $the_id );
234: 
235:     /*
236:      * I must check that is_category is false, or wp will display 404
237:      * is_single is true also for category and in this case
238:      * the plugin will return wrong link
239:      */
240:     if( ( ( $is_single || $is_page ) ||  $linked ) && ! $is_category ) {
241:       $linked_id = CMLPost::get_translation( $result->id, $the_id );
242: 
243:       if( ! empty( $linked_id ) ) {
244:         $link = get_permalink( $linked_id );
245:         $link = CMLPost::remove_extra_number( $link, get_post( $linked_id ) );
246: 
247:         if( CMLUtils::_get( '_real_language' ) != CMLLanguage::get_current_id()
248:             && $linked_id == $the_id ) {
249: 
250:           if( CMLUtils::get_url_mode() == PRE_PATH ) {
251:             $link = $wpCeceppaML->convert_url( $link, $result->cml_language_slug );
252:           }
253:         }
254:       }
255:     }
256: 
257:     if( is_archive() && ! $is_category && ! is_post_type_archive() ) {
258:       global $wp;
259: 
260:       $link = trailingslashit( home_url( $wp->request ) );
261: 
262:       if( CMLUtils::get_url_mode() == PRE_NONE ||
263:           CMLUtils::get_url_mode() == PRE_LANG ) {
264:         $link = add_query_arg( array( "lang" => $result->cml_language_slug ), $link );
265:       }
266:     }
267: 
268:     //Collego le categorie delle varie lingue
269:     if( $is_category ) {
270:       if( $queried && isset( $q->term_id ) ) {
271:         $cat = array( "term_id" => $q->term_id );
272:       } else {
273:         $cat = get_the_category();
274:       }
275: 
276:       if( is_array( $cat ) ) {
277:         $cat_id = ( isset( $cat[ 'term_id' ] ) ) ? $cat[ 'term_id' ] : ( $cat[ count($cat) - 1 ]->term_id );
278: 
279:         //Mi recupererà il link tradotto dal mio plugin ;)
280:         CMLUtils::_set( '_force_category_lang', $result->id );
281:         $link = get_category_link( $cat_id );
282:         
283:         CMLUtils::_del( '_force_category_lang' );
284:       } //endif;
285:     }
286:     
287:     if( $queried && $is_tag ) { //&& false !== strpos( CMLUtils::get_clean_url(), "/tag/" ) ) ) {
288:       if( ! empty( $q ) ) {
289:         $term_id = $q->term_id;
290:       } else {
291:         $term_id = CMLUtils::_get( "_reverted" );
292:       }
293: 
294:       if( ! empty( $term_id ) ) {
295:         CMLUtils::_set( '_force_category_lang', $result->id );
296: 
297:         $link = get_tag_link( $term_id );
298: 
299:         CMLUtils::_del( '_force_category_lang' );
300:       }
301:     }
302: 
303:     if( is_paged() ) {
304:       $link = add_query_arg( array( "lang" => $result->cml_language_slug ) );
305:     }
306: 
307:     unset( $GLOBALS[ '_cml_force_home_slug' ] );
308:     $wpCeceppaML->unset_category_lang();
309: 
310:     /* Controllo se è stata impostata una pagina statica,
311:     perché così invece di restituire il link dell'articolo collegato
312:     aggiungo il più "bello" ?lang=## alla fine della home.
313: 
314:     Se non ho trovato nesuna traduzione per l'articolo, la bandiera punterà alla homepage
315:     */
316:     if( empty( $link ) && ! $only_existings ) {
317:       if( 1 === CMLUtils::_get( "is_crawler" ) ) {
318:         return;
319:       }
320: 
321:       //If post doesn't exists in current language I'll return the link to default language, if exists :)
322:       if( $_cml_settings[ 'cml_force_languge' ] == 1 ) {
323:         /*
324:          * return translation, if exists :)
325:          */
326:         if( is_single() || is_page() ) {
327:           $l = cml_get_linked_post( $the_id, CMLLanguage::get_default_id() );
328:           // if( ! empty( $l ) ) return get_permalink( $l );
329:         }
330: 
331:         /*
332:          * no translation found, and user choosed to force page to flag language,
333:          * I add parameter "lang=##" to url
334:          */
335:         $link = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
336:         if( CMLPost::get_language_by_id( $the_id ) != $result->id ) {
337:           $link = add_query_arg( array( "lang" => $result->cml_language_slug ), $link );
338:         }
339:       } else {
340:         $link = CMLUtils::get_home_url( $result->cml_language_slug );
341:       }
342: 
343:       if( ( $is_tag || ( isset( $is_404 ) && $is_404 ) ) && CMLUtils::get_url_mode() > PRE_LANG ) {
344:         $clean = CMLUtils::get_clean_url();
345:         $url = CMLUtils::home_url();
346:         
347:         //Change slug in url instead of append ?lang arg
348:         $link = str_replace( $url, "", $clean );
349:         $link = CMLUtils::get_home_url( $result->cml_language_slug ) . $link;
350:       }
351:     }
352:   }
353: 
354:   return $link;
355: }
356: 
357: /**
358:  * @ignore
359:  * @internal
360:  *
361:  * use static page?
362:  */
363: function cml_use_static_page() {
364:   return (get_option("page_for_posts") > 0) ||
365:       (get_option("page_on_front") > 0);
366: }
367: 
368: /**
369:  * grab browser language
370:  *
371:  * @return string
372:  */
373: function cml_get_browser_lang() {
374:   if( isset( $GLOBALS[ '_browser_lang' ] ) ) return $GLOBALS[ '_browser_lang' ];
375: 
376:   global $wpdb;
377: 
378:   $browser_langs = @explode( ";", $_SERVER['HTTP_ACCEPT_LANGUAGE'] );
379:   $lang = null;
380: 
381:   //Se la lingua del browser coincide con una di quella attuale della pagina, ignoro tutto
382:   foreach( $browser_langs as $blang ) {
383:     @list( $code1, $code2 ) = explode( ",", $blang );
384: 
385:     $locale[] = str_replace( "-", "_", $code1 );
386:     $locale[] = str_replace( "-", "_", $code2 );
387: 
388:     //Per ogni codice che trovo verifico se è gestito, appena ne trovo 1 mi fermo
389:     //Perché il mio browser mi restituisce sia it-IT, che en-EN, quindi mi devo fermare appena trovo un riscontro
390:     //Senno mi ritrovo sempre la lingua en-EN come $browser_langs;
391:     $i = 0;
392:     while( empty( $lang ) && $i < count( $locale ) ) {
393:       $l = $locale[$i];
394:     
395:       if( strlen( $l ) > 2 ) {
396:         $lang = CMLLanguage::get_id_by_locale( $l );
397:       } else {
398:         //Se ho solo 2 caratteri, cerco negli "slug"
399:         $lang = CMLLanguage::get_id_by_slug( $l );
400:       }
401:     
402:       $i++;
403:     } //endwhile;
404: 
405:     if( ! empty ($lang ) ) {
406:       break;
407:     }
408:   }  //endforeach;
409: 
410:   $GLOBALS[ '_browser_lang' ] = $lang;
411: 
412:   return $lang;
413: }
414: 
415: /**
416:  * return post/page notice in selected language
417:  *
418:  * @param sting $lang_slug - language slug
419:  * 
420:  * @return string return translated notice
421:  */
422: function cml_get_notice( $lang ) {
423:   global $wpdb, $wpCeceppaML;
424: 
425:   //$type - type of notice ( post or page )
426:   $type = ( is_single() ) ? "post" : "page";
427: 
428:   $r = CMLTranslations::get( $lang,
429:                             "_notice_$type",
430:                             "N", true, true );
431: 
432:   if( ! empty( $r ) )
433:     return $r;
434:   else
435:     CMLLanguage::get_current()->cml_language;
436: }
437: 
438: /**
439:  * Return flag &lt;ul&gt;&lt;li&gt;....&lt;/li&gt;&lt;/ul&gt; list
440:  *
441:  * @param array $args is parameters list:
442:  *              <ul>
443:  *                <li>
444:  *                  show ( string ) - choose what to display:<br />
445:  *                  <i>default: text</i>
446:  *                </li>
447:  *                <ul>
448:  *                   <li>text: show only language name</li>
449:  *                   <li>slug: show language slug</li>
450:  *                   <li>none: show no text</li>
451:  *               </ul>
452:  *               <li>
453:  *                show_flag ( boolean ) - show flag?<br />
454:  *                <i>default: true</i>
455:  *               </li>
456:  *               <li>size ( string ) - flag size<br />
457:  *                you can use constants:<br />
458:  *                  CML_FLAG_TINY ( 16x11 )<br />
459:  *                  CML_FLAG_SMALL ( 32x23 )<br />
460:  *                  <i>default: CML_FLAG_TINY</i>
461:  *                <ul>
462:  *                  <li>tiny</li>
463:  *                  <li>small</li>
464:  *                </ul>
465:  *               <li>
466:  *                class_name ( string ) - secondary classname to assign to the list
467:  *                <i>default: ""</i>
468:  *                generated &gt;ul&lt; list has primary class "cml_flags", with that parameter you
469:  *                can assign a secondary one.
470:  *               </li>
471:  *               <li>
472:  *                echo ( boolean ) - If true print list, otherwise return string containing generated list<br />
473:  *                <i>default: true</i>
474:  *               </li>
475:  *               <li>
476:  *                linked ( boolean ) - If true flags link to current translation, false will link to homepage<br />
477:  *                <i>default: true</i>
478:  *               </li>
479:  *               <li>
480:  *                only_existings ( boolean ) - show only flags in which current page exists.<br />
481:  *                <i>default: false</i>
482:  *               </li>
483:  *               <li>
484:  *                queried ( boolean ) - use queried object instead of get_the_ID() or other methods, so output will be
485:  *                                      generated in according to main query, not current one.
486:  *                <i>default: false</i>
487:  *               <li>
488:  *              </ul>
489:  */
490: function cml_show_flags( $args ) {
491:   global $wpdb;
492: 
493:   $args = extract( shortcode_atts( array(
494:                       "show" => "text",
495:                       "size" => "tiny",
496:                       "class" => "",
497:                       "image_class" => "",
498:                       "echo" => true,
499:                       "linked" => true,
500:                       "only_existings" => false,
501:                       "sort" => false,
502:                       "queried" => false,
503:                       "show_flag" => true,
504:                       ), $args ) );
505: 
506:   $_cml_settings = & $GLOBALS[ '_cml_settings' ];
507:   $redirect = $_cml_settings[ 'cml_option_redirect' ];
508: 
509:   $results = cml_get_languages( true, false );
510:   $width = ( $size == "tiny" ) ? 16 : 32;
511: 
512:   $r = "<ul class=\"cml_flags $class\">";
513:   
514:   //Post language...
515:   $lang_id = ( ! $sort ) ? -1 : CMLPost::get_language_by_id( get_the_ID() );
516:   $items = array();
517: 
518:   foreach($results as $result) {
519:     $lang = ( $show == "text" ) ? $result->cml_language : "";
520:     $lang = ( $show == "slug" ) ? $result->cml_language_slug : $lang;
521: 
522:     $link = cml_get_the_link( $result, $linked, $only_existings, $queried );
523:     if( empty( $link) ) continue;
524: 
525:     if( $show_flag ) {
526:       $img = "<img class=\"$size $image_class\" src='" . cml_get_flag_by_lang_id( $result->id, $size ) . "' title='$result->cml_language' width=\"$width\"/>";
527:     } else {
528:       $img = "";
529:     }
530: 
531:     $class = ( $result->id == CMLLanguage::get_current_id() ) ? "current" : "";
532:     $li = "<li class=\"$class\"><a href=\"$link\">{$img}{$lang}</a></li>";
533:     if( $sort && is_array( $items ) && $result->id == $lang_id ) {
534:       array_unshift( $items, $li );
535:     } else {
536:       $items[] = $li;
537:     }
538: 
539:   } //endforeach;
540: 
541: 
542:   $r .= join( "\n", $items );
543:   $r .= "</ul>";
544: 
545:   if( $echo ) 
546:     echo $r;
547:   else
548:     return $r;
549: }
550: 
551: /**
552:  * @ignore
553:  * 
554:  * Check if current post is a custom post
555:  */
556: function cml_is_custom_post_type() {
557:   $types = get_post_types( array ( '_builtin' => FALSE ), 'names' );
558:   
559:   if( empty( $types) ) return FALSE;
560: 
561:   $name = get_post_type();
562:   return in_array( $name, $types );
563: }
564: 
565: /**
566:  * @ignore
567:  */
568: function removesmartquotes($content) {
569:   $content = str_replace('&#8220;', '&quot;', $content);
570:   $content = str_replace('&#8221;', '&quot;', $content);
571:   $content = str_replace('&#8216;', '&#39;', $content);
572:   $content = str_replace('&#8217;', '&#39;', $content);
573:  
574:   return $content;
575: }
576: 
577: /**
578:  * @ignore
579:  * 
580:  * http://www.cult-f.net/detect-crawlers-with-php/
581:  *
582:  * Questa funzione server per evitare di reindirizzare o nascondere i post nella lingua differente
583:  * da quella del browser se schi stà visitando il sito è un crawler, al fine di permettere l'indicizzazione di tutti
584:  * gli articoli
585:  *
586:  */
587: function isCrawler()
588: {
589:   global $wp_query;
590:   
591:   if( ! empty( $wp_query ) && $wp_query->is_robots() ) {
592:     CMLUtils::_set( "is_crawler", 1 );
593: 
594:     return true;
595:   }
596:   
597:     $USER_AGENT = $_SERVER['HTTP_USER_AGENT'];
598: 
599:     // to get crawlers string used in function uncomment it
600:     // it is better to save it in string than use implode every time
601:     // global $crawlers
602:     // $crawlers_agents = implode('|',$crawlers);
603:     $crawlers_agents = 'Google|msnbot|Rambler|Yahoo|AbachoBOT|accoona|AcioRobot|ASPSeek|CocoCrawler|Dumbot|FAST-WebCrawler|GeonaBot|Gigabot|Lycos|MSRBOT|Scooter|AltaVista|IDBot|eStyle|Scrubby';
604:  
605:     if ( strpos($crawlers_agents , $USER_AGENT) === false )
606:        return false;
607:     // crawler detected
608:     // you can use it to return its name
609:     /*
610:     else {
611:        return array_search($USER_AGENT, $crawlers);
612:     }
613:     */
614:     return true;
615: }
616: 
617: /**
618:  * return the id of menu to use in according to current language
619:  * return value can be used as wp_nav_menu function.
620:  *
621:  * The plugin automatically switch menu in according to current language,
622:  * you can use this function if automatic switch doesn't works with your theme/framework
623:  * or if you to force a theme.
624:  * 
625:  * @example
626:  * <?php;<br />
627:  *  $menu = cml_get_menu();<br />
628:  *  wp_nav_menu(array('theme_location' => $menu));<br />
629:  * ?>
630:  */
631: function cml_get_menu() {
632:   //Restituisco il nome del menù da utilizzare a seconda della lingua
633:   $lang = cml_get_current_language();
634: 
635:   return "cml_menu_" . $lang->cml_language_slug;
636: }
637: ?>
638: 
API documentation generated by ApiGen 2.8.0