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