Add support for Thai language in say.c
[asterisk/asterisk.git] / main / say.c
index 45f67dc..e401689 100644 (file)
  * 
  * \note 12-16-2004 : Support for Greek added by InAccess Networks (work funded by HOL, www.hol.gr) George Konstantoulakis <gkon@inaccessnetworks.com>
  *                                             
+ * \note 2007-02-08 : Support for Georgian added by Alexander Shaduri <ashaduri@gmail.com>,
+ *                                             Next Generation Networks (NGN).
+ * \note 2007-03-20 : Support for Thai added by Dome C. <dome@tel.co.th>,
+ *                                             IP Crossing Co.,Ltd.
  */
 
 #include "asterisk.h"
@@ -65,7 +69,7 @@ static int say_character_str_full(struct ast_channel *chan, const char *str, con
        int num = 0;
        int res = 0;
 
-       while (str[num]) {
+       while (str[num] && !res) {
                fn = NULL;
                switch (str[num]) {
                case ('*'):
@@ -123,8 +127,12 @@ static int say_character_str_full(struct ast_channel *chan, const char *str, con
                        fn = fnbuf;
                }
                res = ast_streamfile(chan, fn, lang);
-               if (!res) 
-                       res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+               if (!res) {
+                       if ((audiofd  > -1) && (ctrlfd > -1))
+                               res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+                       else
+                               res = ast_waitstream(chan, ints);
+               }
                ast_stopstream(chan);
                num++;
        }
@@ -140,7 +148,7 @@ static int say_phonetic_str_full(struct ast_channel *chan, const char *str, cons
        int num = 0;
        int res = 0;
 
-       while (str[num]) {
+       while (str[num] && !res) {
                fn = NULL;
                switch (str[num]) {
                case ('*'):
@@ -197,8 +205,12 @@ static int say_phonetic_str_full(struct ast_channel *chan, const char *str, cons
                        fn = fnbuf;
                }
                res = ast_streamfile(chan, fn, lang);
-               if (!res) 
-                       res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+               if (!res) {
+                       if ((audiofd  > -1) && (ctrlfd > -1))
+                               res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+                       else
+                               res = ast_waitstream(chan, ints);
+               }
                ast_stopstream(chan);
                num++;
        }
@@ -242,8 +254,12 @@ static int say_digit_str_full(struct ast_channel *chan, const char *str, const c
                }
                if (fn) {
                        res = ast_streamfile(chan, fn, lang);
-                       if (!res) 
-                               res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+                       if (!res) {
+                               if ((audiofd  > -1) && (ctrlfd > -1))
+                                        res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+                                else
+                                        res = ast_waitstream(chan, ints);
+                       }
                        ast_stopstream(chan);
                }
                num++;
@@ -270,9 +286,12 @@ static int say_digit_str_full(struct ast_channel *chan, const char *str, const c
       \arg \b no    - Norwegian
       \arg \b pl    - Polish       
       \arg \b pt    - Portuguese
+      \arg \b pt_BR - Portuguese (Brazil)
       \arg \b se    - Swedish
       \arg \b tw    - Taiwanese / Chinese
       \arg \b ru    - Russian
+      \arg \b ge    - Georgian
+      \arg \b hu    - Hungarian
 
  \par Gender:
  For Some languages the numbers differ for gender and plural.
@@ -327,6 +346,9 @@ static int ast_say_number_full_se(struct ast_channel *chan, int num, const char
 static int ast_say_number_full_tw(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
 static int ast_say_number_full_gr(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
 static int ast_say_number_full_ru(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
+static int ast_say_number_full_ge(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
+static int ast_say_number_full_hu(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
+static int ast_say_number_full_th(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
 
 /* Forward declarations of language specific variants of ast_say_enumeration_full */
 static int ast_say_enumeration_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
@@ -341,6 +363,9 @@ static int ast_say_date_fr(struct ast_channel *chan, time_t t, const char *ints,
 static int ast_say_date_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_date_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_date_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_date_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_date_hu(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_date_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 
 static int ast_say_date_with_format_en(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
 static int ast_say_date_with_format_da(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
@@ -354,26 +379,36 @@ static int ast_say_date_with_format_pl(struct ast_channel *chan, time_t time, co
 static int ast_say_date_with_format_pt(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
 static int ast_say_date_with_format_tw(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
 static int ast_say_date_with_format_gr(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
+static int ast_say_date_with_format_th(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
 
 static int ast_say_time_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_time_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_time_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_time_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_time_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_time_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_time_tw(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_time_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_time_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_time_hu(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_time_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 
 static int ast_say_datetime_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_datetime_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_datetime_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_datetime_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_datetime_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_datetime_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_datetime_tw(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_datetime_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_datetime_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_datetime_hu(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_datetime_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 
 static int ast_say_datetime_from_now_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_datetime_from_now_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 static int ast_say_datetime_from_now_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_datetime_from_now_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
 
 static int wait_file(struct ast_channel *chan, const char *ints, const char *file, const char *lang) 
 {
@@ -407,13 +442,15 @@ static int say_number_full(struct ast_channel *chan, int num, const char *ints,
           return(ast_say_number_full_fr(chan, num, ints, language, options, audiofd, ctrlfd));
        } else if (!strcasecmp(language, "he") ) {      /* Hebrew syntax */
           return(ast_say_number_full_he(chan, num, ints, language, options, audiofd, ctrlfd));
+       } else if (!strcasecmp(language, "hu") ) {      /* Hungarian syntax */
+          return(ast_say_number_full_hu(chan, num, ints, language, audiofd, ctrlfd));
        } else if (!strcasecmp(language, "it") ) {      /* Italian syntax */
           return(ast_say_number_full_it(chan, num, ints, language, audiofd, ctrlfd));
        } else if (!strcasecmp(language, "nl") ) {      /* Dutch syntax */
           return(ast_say_number_full_nl(chan, num, ints, language, audiofd, ctrlfd));
        } else if (!strcasecmp(language, "pl") ) {      /* Polish syntax */
           return(ast_say_number_full_pl(chan, num, ints, language, options, audiofd, ctrlfd));
-       } else if (!strcasecmp(language, "pt") ) {      /* Portuguese syntax */
+       } else if (!strcasecmp(language, "pt") || !strcasecmp(language, "pt_BR")) {     /* Portuguese syntax */
           return(ast_say_number_full_pt(chan, num, ints, language, options, audiofd, ctrlfd));
        } else if (!strcasecmp(language, "se") ) {      /* Swedish syntax */
           return(ast_say_number_full_se(chan, num, ints, language, options, audiofd, ctrlfd));
@@ -423,6 +460,10 @@ static int say_number_full(struct ast_channel *chan, int num, const char *ints,
           return(ast_say_number_full_gr(chan, num, ints, language, audiofd, ctrlfd));
        } else if (!strcasecmp(language, "ru") ) {      /* Russian syntax */
           return(ast_say_number_full_ru(chan, num, ints, language, options, audiofd, ctrlfd));
+       } else if (!strcasecmp(language, "th") ) {      /* Thai syntax */
+          return(ast_say_number_full_th(chan, num, ints, language, audiofd, ctrlfd));
+       } else if (!strcasecmp(language, "ge") ) {      /* Georgian syntax */
+          return(ast_say_number_full_ge(chan, num, ints, language, options, audiofd, ctrlfd));
        }
 
        /* Default to english */
@@ -439,7 +480,7 @@ static int ast_say_number_full_en(struct ast_channel *chan, int num, const char
        if (!num) 
                return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
 
-       while(!res && (num || playh)) {
+       while (!res && (num || playh)) {
                if (num < 0) {
                        snprintf(fn, sizeof(fn), "digits/minus");
                        if ( num > INT_MIN ) {
@@ -476,15 +517,14 @@ static int ast_say_number_full_en(struct ast_channel *chan, int num, const char
                                                num = num % 1000000;
                                                snprintf(fn, sizeof(fn), "digits/million");
                                        } else {
-                                               if (option_debug)
-                                                       ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                                               ast_debug(1, "Number '%d' is too big for me\n", num);
                                                res = -1;
                                        }
                                }
                        }
                }
                if (!res) {
-                       if(!ast_streamfile(chan, fn, language)) {
+                       if (!ast_streamfile(chan, fn, language)) {
                                if ((audiofd  > -1) && (ctrlfd > -1))
                                        res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
                                else
@@ -542,7 +582,7 @@ static int ast_say_number_full_cz(struct ast_channel *chan, int num, const char
        if (!num) 
                return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
        
-       while(!res && (num || playh)) {
+       while (!res && (num || playh)) {
                if (num < 0) {
                        snprintf(fn, sizeof(fn), "digits/minus");
                        if ( num > INT_MIN ) {
@@ -606,7 +646,7 @@ static int ast_say_number_full_cz(struct ast_channel *chan, int num, const char
                        num -= left * (exp10_int(length-1));
                }
                if (!res) {
-                       if(!ast_streamfile(chan, fn, language)) {
+                       if (!ast_streamfile(chan, fn, language)) {
                                if ((audiofd > -1) && (ctrlfd > -1)) {
                                        res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
                                } else {
@@ -635,7 +675,7 @@ static int ast_say_number_full_da(struct ast_channel *chan, int num, const char
 
        if (options && !strncasecmp(options, "n",1)) cn = -1;
 
-       while(!res && (num || playh || playa )) {
+       while (!res && (num || playh || playa )) {
                /* The grammar for Danish numbers is the same as for English except
                * for the following:
                * - 1 exists in both commune ("en", file "1N") and neuter ("et", file "1")
@@ -706,8 +746,7 @@ static int ast_say_number_full_da(struct ast_channel *chan, int num, const char
                                                        snprintf(fn, sizeof(fn), "digits/millions");
                                                num = num % 1000000;
                                        } else {
-                                               if (option_debug)
-                                                       ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                                               ast_debug(1, "Number '%d' is too big for me\n", num);
                                                res = -1;
                                        }
                                }
@@ -716,7 +755,7 @@ static int ast_say_number_full_da(struct ast_channel *chan, int num, const char
                        }
                }
                if (!res) {
-                       if(!ast_streamfile(chan, fn, language)) {
+                       if (!ast_streamfile(chan, fn, language)) {
                                if ((audiofd > -1) && (ctrlfd > -1)) 
                                        res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
                                else  
@@ -749,7 +788,7 @@ static int ast_say_number_full_de(struct ast_channel *chan, int num, const char
        if (options && (!strncasecmp(options, "f",1)))
                mf = -1;
 
-       while(!res && num) {
+       while (!res && num) {
                /* The grammar for German numbers is the same as for English except
                * for the following:
                * - numbers 20 through 99 are said in reverse order, i.e. 21 is
@@ -842,12 +881,11 @@ static int ast_say_number_full_de(struct ast_channel *chan, int num, const char
                                snprintf(fn, sizeof(fn), "digits/milliards");
                        }
                } else {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                       ast_debug(1, "Number '%d' is too big for me\n", num);
                        res = -1;
                }
                if (!res) {
-                       if(!ast_streamfile(chan, fn, language)) {
+                       if (!ast_streamfile(chan, fn, language)) {
                                if ((audiofd > -1) && (ctrlfd > -1)) 
                                        res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
                                else  
@@ -882,7 +920,7 @@ static int ast_say_number_full_en_GB(struct ast_channel *chan, int num, const ch
        if (!num) 
                return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
 
-       while(!res && (num || playh || playa )) {
+       while (!res && (num || playh || playa )) {
                if (num < 0) {
                        snprintf(fn, sizeof(fn), "digits/minus");
                        if ( num > INT_MIN ) {
@@ -928,13 +966,12 @@ static int ast_say_number_full_en_GB(struct ast_channel *chan, int num, const ch
                                if (num && num < 100)
                                        playa++;
                } else {
-                               if (option_debug)
-                                       ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                               ast_debug(1, "Number '%d' is too big for me\n", num);
                                res = -1;
                }
                
                if (!res) {
-                       if(!ast_streamfile(chan, fn, language)) {
+                       if (!ast_streamfile(chan, fn, language)) {
                                if ((audiofd > -1) && (ctrlfd > -1)) 
                                        res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
                                else  
@@ -1030,8 +1067,7 @@ static int ast_say_number_full_es(struct ast_channel *chan, int num, const char
                                                }
                                                num = num % 1000000;
                                        } else {
-                                               if (option_debug)
-                                                       ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                                               ast_debug(1, "Number '%d' is too big for me\n", num);
                                                res = -1;
                                        }
                                }
@@ -1039,7 +1075,7 @@ static int ast_say_number_full_es(struct ast_channel *chan, int num, const char
                }
 
                if (!res) {
-                       if(!ast_streamfile(chan, fn, language)) {
+                       if (!ast_streamfile(chan, fn, language)) {
                                if ((audiofd > -1) && (ctrlfd > -1))
                                        res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
                                else
@@ -1070,7 +1106,7 @@ static int ast_say_number_full_fr(struct ast_channel *chan, int num, const char
        if (options && !strncasecmp(options, "f",1))
                mf = -1;
 
-       while(!res && (num || playh || playa)) {
+       while (!res && (num || playh || playa)) {
                if (num < 0) {
                        snprintf(fn, sizeof(fn), "digits/minus");
                        if ( num > INT_MIN ) {
@@ -1100,7 +1136,7 @@ static int ast_say_number_full_fr(struct ast_channel *chan, int num, const char
                } else if (num < 80) {
                        snprintf(fn, sizeof(fn), "digits/60");
                        if ((num % 10) == 1) playa++;
-                       num = num - 60;
+                       num -= 60;
                } else if (num < 100) {
                        snprintf(fn, sizeof(fn), "digits/80");
                        num = num - 80;
@@ -1127,12 +1163,11 @@ static int ast_say_number_full_fr(struct ast_channel *chan, int num, const char
                        snprintf(fn, sizeof(fn), "digits/million");
                        num = num % 1000000;
                } else {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                       ast_debug(1, "Number '%d' is too big for me\n", num);
                        res = -1;
                }
                if (!res) {
-                       if(!ast_streamfile(chan, fn, language)) {
+                       if (!ast_streamfile(chan, fn, language)) {
                                if ((audiofd > -1) && (ctrlfd > -1))
                                        res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
                                else
@@ -1150,7 +1185,8 @@ static int ast_say_number_full_fr(struct ast_channel *chan, int num, const char
 /*     Extra sounds needed:
        1F: feminin 'one'
        ve: 'and'
-       2hundred: 2 hundred
+       1hundred: 1 hundred
+       2hundred: 2 hundreds
        2thousands: 2 thousand 
        thousands: plural of 'thousand'
        3sF 'Smichut forms (female)
@@ -1209,7 +1245,7 @@ static int ast_say_number_full_he(struct ast_channel *chan, int num,
                mf = -1;
 
        /* Do we have work to do? */
-       while(!res && (num || (state>0) ))  {
+       while (!res && (num || (state>0) ))  {
                /* first type of work: play a second sound. In this loop
                 * we can only play one sound file at a time. Thus playing 
                 * a second one requires repeating the loop just for the 
@@ -1241,11 +1277,13 @@ static int ast_say_number_full_he(struct ast_channel *chan, int num,
                        num = num % 10;
                        if (num>0) state=2;
                } else if (num < 200) {
-                       snprintf(fn, sizeof(fn), "digits/hundred");
+                       snprintf(fn, sizeof(fn), "digits/1hundred");
                        num = num - 100;
+                       state=2;
                } else if (num < 300) {
-                       snprintf(fn, sizeof(fn), "digits/hundred");
-                       num = num - 100;
+                       snprintf(fn, sizeof(fn), "digits/2hundred");
+                       num = num - 200;
+                       state=2;
                } else if (num < 1000) {
                        snprintf(fn, sizeof(fn), "digits/%d", (num/100));
                        state=1;
@@ -1274,12 +1312,11 @@ static int ast_say_number_full_he(struct ast_channel *chan, int num,
                        snprintf(fn, sizeof(fn), "digits/million");
                        num = num % 1000000;
                } else {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                       ast_debug(1, "Number '%d' is too big for me\n", num);
                        res = -1;
                }
                if (!res) {
-                       if(!ast_streamfile(chan, fn, language)) {
+                       if (!ast_streamfile(chan, fn, language)) {
                                if ((audiofd > -1) && (ctrlfd > -1))
                                        res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
                                else
@@ -1291,6 +1328,87 @@ static int ast_say_number_full_he(struct ast_channel *chan, int num,
        return res;
 }
 
+/*! \brief  ast_say_number_full_hu: Hungarian syntax */
+/* Extra sounds need:
+       10en: "tizen"
+       20on: "huszon"
+*/
+static int ast_say_number_full_hu(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
+{
+       int res = 0;
+       int playh = 0;
+       char fn[256] = "";
+       if (!num) 
+               return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
+
+       /*
+       Hungarian support
+       like english, except numbers up to 29 are from 2 words.
+       10 and first word of 1[1-9] and 20 and first word of 2[1-9] are different.
+       */
+
+       while(!res && (num || playh)) {
+               if (num < 0) {
+                       snprintf(fn, sizeof(fn), "digits/minus");
+                       if ( num > INT_MIN ) {
+                               num = -num;
+                       } else {
+                               num = 0;
+                       }       
+               } else if (playh) {
+                       snprintf(fn, sizeof(fn), "digits/hundred");
+                       playh = 0;
+               } else if (num < 11 || num == 20) {
+                       snprintf(fn, sizeof(fn), "digits/%d", num);
+                       num = 0;
+               } else if (num < 20) {
+                       snprintf(fn, sizeof(fn), "digits/10en");
+                       num = (num - 10);
+               } else if (num < 30) {
+                       snprintf(fn, sizeof(fn), "digits/20on");
+                       num = (num - 20);
+               } else  if (num < 100) {
+                       snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
+                       num -= ((num / 10) * 10);
+               } else {
+                       if (num < 1000){
+                               snprintf(fn, sizeof(fn), "digits/%d", (num/100));
+                               playh++;
+                               num -= ((num / 100) * 100);
+                       } else {
+                               if (num < 1000000) { /* 1,000,000 */
+                                       res = ast_say_number_full_hu(chan, num / 1000, ints, language, audiofd, ctrlfd);
+                                       if (res)
+                                               return res;
+                                       num = num % 1000;
+                                       snprintf(fn, sizeof(fn), "digits/thousand");
+                               } else {
+                                       if (num < 1000000000) { /* 1,000,000,000 */
+                                               res = ast_say_number_full_hu(chan, num / 1000000, ints, language, audiofd, ctrlfd);
+                                               if (res)
+                                                       return res;
+                                               num = num % 1000000;
+                                               snprintf(fn, sizeof(fn), "digits/million");
+                                       } else {
+                                               ast_debug(1, "Number '%d' is too big for me\n", num);
+                                               res = -1;
+                                       }
+                               }
+                       }
+               }
+               if (!res) {
+                       if(!ast_streamfile(chan, fn, language)) {
+                               if ((audiofd  > -1) && (ctrlfd > -1))
+                                       res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+                               else
+                                       res = ast_waitstream(chan, ints);
+                       }
+                       ast_stopstream(chan);
+               }
+       }
+       return res;
+}
+
 /*! \brief  ast_say_number_full_it:  Italian */
 static int ast_say_number_full_it(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
 {
@@ -1326,7 +1444,7 @@ static int ast_say_number_full_it(struct ast_channel *chan, int num, const char
                So the right file is provided.
                */
 
-               while(!res && (num || playh)) {
+       while (!res && (num || playh)) {
                        if (num < 0) {
                                snprintf(fn, sizeof(fn), "digits/minus");
                                if ( num > INT_MIN ) {
@@ -1425,15 +1543,14 @@ static int ast_say_number_full_it(struct ast_channel *chan, int num, const char
                                                        else
                                                                snprintf(fn, sizeof(fn), "digits/millions");
                                                } else {
-                                                       if (option_debug)
-                                                               ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                                                       ast_debug(1, "Number '%d' is too big for me\n", num);
                                                        res = -1;
                                                }
                                        }
                                }
                        }
                        if (!res) {
-                               if(!ast_streamfile(chan, fn, language)) {
+                               if (!ast_streamfile(chan, fn, language)) {
                                        if ((audiofd > -1) && (ctrlfd > -1))
                                                res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
                                        else
@@ -1502,8 +1619,7 @@ static int ast_say_number_full_nl(struct ast_channel *chan, int num, const char
                                                num = num % 1000000;
                                                snprintf(fn, sizeof(fn), "digits/million");
                                        } else {
-                                               if (option_debug)
-                                                       ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                                               ast_debug(1, "Number '%d' is too big for me\n", num);
                                                res = -1;
                                        }
                                }
@@ -1511,7 +1627,7 @@ static int ast_say_number_full_nl(struct ast_channel *chan, int num, const char
                }
 
                if (!res) {
-                       if(!ast_streamfile(chan, fn, language)) {
+                       if (!ast_streamfile(chan, fn, language)) {
                                if ((audiofd > -1) && (ctrlfd > -1))
                                        res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
                                else
@@ -1540,7 +1656,7 @@ static int ast_say_number_full_no(struct ast_channel *chan, int num, const char
        
        if (options && !strncasecmp(options, "n",1)) cn = -1;
 
-       while(!res && (num || playh || playa )) {
+       while (!res && (num || playh || playa )) {
                /* The grammar for Norwegian numbers is the same as for English except
                * for the following:
                * - 1 exists in both commune ("en", file "1") and neuter ("ett", file "1N")
@@ -1598,13 +1714,12 @@ static int ast_say_number_full_no(struct ast_channel *chan, int num, const char
                                if (num && num < 100)
                                        playa++;
                } else {
-                               if (option_debug)
-                                       ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                               ast_debug(1, "Number '%d' is too big for me\n", num);
                                res = -1;
                }
                
                if (!res) {
-                       if(!ast_streamfile(chan, fn, language)) {
+                       if (!ast_streamfile(chan, fn, language)) {
                                if ((audiofd > -1) && (ctrlfd > -1)) 
                                        res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
                                else  
@@ -1650,8 +1765,7 @@ static void pl_odtworz_plik(struct ast_channel *chan, const char *language, int
 {    
        char file_name[255] = "digits/";
        strcat(file_name, fn);
-       if (option_debug)
-               ast_log(LOG_DEBUG, "Trying to play: %s\n", file_name);
+       ast_debug(1, "Trying to play: %s\n", file_name);
        if (!ast_streamfile(chan, file_name, language)) {
                if ((audiofd > -1) && (ctrlfd > -1))
                        ast_waitstream_full(chan, ints, audiofd, ctrlfd);
@@ -1858,7 +1972,7 @@ and combinations of eg.: 20_1, 30m_3m, etc...
        static odmiana *odmiana_zenska = NULL; 
 
        if (odmiana_nieosobowa == NULL) {
-               odmiana_nieosobowa = (odmiana *) malloc(sizeof(odmiana));
+               odmiana_nieosobowa = ast_malloc(sizeof(*odmiana_nieosobowa));
 
                odmiana_nieosobowa->separator_dziesiatek = " ";
 
@@ -1871,7 +1985,7 @@ and combinations of eg.: 20_1, 30m_3m, etc...
        }
 
        if (odmiana_zenska == NULL) {
-               odmiana_zenska = (odmiana *) malloc(sizeof(odmiana));
+               odmiana_zenska = ast_malloc(sizeof(*odmiana_zenska));
 
                odmiana_zenska->separator_dziesiatek = " ";
 
@@ -1884,7 +1998,7 @@ and combinations of eg.: 20_1, 30m_3m, etc...
        }
 
        if (odmiana_meska == NULL) {
-               odmiana_meska = (odmiana *) malloc(sizeof(odmiana));
+               odmiana_meska = ast_malloc(sizeof(*odmiana_meska));
 
                odmiana_meska->separator_dziesiatek = " ";
 
@@ -1929,7 +2043,7 @@ static int ast_say_number_full_pt(struct ast_channel *chan, int num, const char
        if (options && !strncasecmp(options, "f",1))
                mf = -1;
 
-       while(!res && num ) {
+       while (!res && num ) {
                if (num < 0) {
                        snprintf(fn, sizeof(fn), "digits/minus");
                        if ( num > INT_MIN ) {
@@ -1988,6 +2102,10 @@ static int ast_say_number_full_pt(struct ast_channel *chan, int num, const char
                                (!(num % 1000) && (((num / 1000) % 1000) < 100 || !((num / 1000) % 100))) ) )
                                playh = 1;
                        num = num % 1000000;
+               } else {
+                       /* number is too big */
+                       ast_log(LOG_WARNING, "Number '%d' is too big to say.", num);
+                       res = -1;
                }
                if (!res) {
                        if (!ast_streamfile(chan, fn, language)) {
@@ -2018,7 +2136,7 @@ static int ast_say_number_full_se(struct ast_channel *chan, int num, const char
                return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
        if (options && !strncasecmp(options, "n",1)) cn = -1;
 
-       while(!res && (num || playh)) {
+       while (!res && (num || playh)) {
                if (num < 0) {
                        snprintf(fn, sizeof(fn), "digits/minus");
                        if ( num > INT_MIN ) {
@@ -2060,15 +2178,14 @@ static int ast_say_number_full_se(struct ast_channel *chan, int num, const char
                                                num = num % 1000000;
                                                snprintf(fn, sizeof(fn), "digits/million");
                                        } else {
-                                               if (option_debug)
-                                                       ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                                               ast_debug(1, "Number '%d' is too big for me\n", num);
                                                res = -1;
                                        }
                                }
                        }
                }
                if (!res) {
-                       if(!ast_streamfile(chan, fn, language)) {
+                       if (!ast_streamfile(chan, fn, language)) {
                                if ((audiofd > -1) && (ctrlfd > -1))
                                        res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
                                else
@@ -2089,7 +2206,7 @@ static int ast_say_number_full_tw(struct ast_channel *chan, int num, const char
        if (!num)
                return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
 
-       while(!res && (num || playh)) {
+       while (!res && (num || playh)) {
                        if (num < 0) {
                                snprintf(fn, sizeof(fn), "digits/minus");
                                if ( num > INT_MIN ) {
@@ -2126,15 +2243,14 @@ static int ast_say_number_full_tw(struct ast_channel *chan, int num, const char
                                                        num = num % 1000000;
                                                        snprintf(fn, sizeof(fn), "digits/million");
                                                } else {
-                                                       if (option_debug)
-                                                               ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                                                       ast_debug(1, "Number '%d' is too big for me\n", num);
                                                        res = -1;
                                                }
                                        }
                                }
                        }
                        if (!res) {
-                               if(!ast_streamfile(chan, fn, language)) {
+                               if (!ast_streamfile(chan, fn, language)) {
                                        if ((audiofd > -1) && (ctrlfd > -1))
                                                res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
                                        else
@@ -2182,7 +2298,7 @@ static int ast_say_number_full_ru(struct ast_channel *chan, int num, const char
        if (!num) 
                return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
 
-       while(!res && (num)) {
+       while (!res && (num)) {
                if (num < 0) {
                        snprintf(fn, sizeof(fn), "digits/minus");
                        if ( num > INT_MIN ) {
@@ -2191,7 +2307,7 @@ static int ast_say_number_full_ru(struct ast_channel *chan, int num, const char
                                num = 0;
                        }       
                } else  if (num < 20) {
-                       if(options && strlen(options) == 1 && num < 3) {
+                       if (options && strlen(options) == 1 && num < 3) {
                            snprintf(fn, sizeof(fn), "digits/%d%s", num, options);
                        } else {
                            snprintf(fn, sizeof(fn), "digits/%d", num);
@@ -2236,8 +2352,7 @@ static int ast_say_number_full_ru(struct ast_channel *chan, int num, const char
                        }
                        num %= 1000000;
                } else {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                       ast_debug(1, "Number '%d' is too big for me\n", num);
                        res = -1;
                }
                if (!res) {
@@ -2253,6 +2368,74 @@ static int ast_say_number_full_ru(struct ast_channel *chan, int num, const char
        return res;
 }
 
+static int ast_say_number_full_th(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
+{
+       int res = 0;
+       int playh = 0;
+       char fn[256] = "";
+       if (!num) 
+               return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
+
+       while(!res && (num || playh)) {
+               if (num < 0) {
+                       snprintf(fn, sizeof(fn), "digits/lop");
+                       if ( num > INT_MIN ) {
+                               num = -num;
+                       } else {
+                               num = 0;
+                       }       
+               } else if (playh) {
+                       snprintf(fn, sizeof(fn), "digits/roi");
+                       playh = 0;
+               } else if (num < 100) {
+                       if ((num <= 20) || ((num % 10) == 1)) {
+                               snprintf(fn, sizeof(fn), "digits/%d", num);
+                               num = 0;
+                       } else {
+                               snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
+                               num -= ((num / 10) * 10);
+                       }
+               } else if (num < 1000) {
+                       snprintf(fn, sizeof(fn), "digits/%d", (num/100));
+                       playh++;
+                       num -= ((num / 100) * 100);
+               } else if (num < 10000) { /* 10,000 */
+                       res = ast_say_number_full_th(chan, num / 1000, ints, language, audiofd, ctrlfd);
+                       if (res)
+                               return res;
+                       num = num % 1000;
+                       snprintf(fn, sizeof(fn), "digits/pan");
+               } else if (num < 100000) { /* 100,000 */
+                       res = ast_say_number_full_th(chan, num / 10000, ints, language, audiofd, ctrlfd);
+                       if (res)
+                               return res;
+                       num = num % 10000;
+                       snprintf(fn, sizeof(fn), "digits/muan");
+               } else if (num < 1000000) { /* 1,000,000 */
+                       res = ast_say_number_full_th(chan, num / 100000, ints, language, audiofd, ctrlfd);
+                       if (res)
+                               return res;
+                       num = num % 100000;
+                       snprintf(fn, sizeof(fn), "digits/san");
+               } else {
+                       res = ast_say_number_full_th(chan, num / 1000000, ints, language, audiofd, ctrlfd);
+                       if (res)
+                               return res;
+                       num = num % 1000000;
+                       snprintf(fn, sizeof(fn), "digits/larn");
+               }
+               if (!res) {
+                       if(!ast_streamfile(chan, fn, language)) {
+                               if ((audiofd  > -1) && (ctrlfd > -1))
+                                       res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+                               else
+                                       res = ast_waitstream(chan, ints);
+                       }
+                       ast_stopstream(chan);
+               }
+       }
+       return res;
+}
 
 /*! \brief  ast_say_enumeration_full: call language-specific functions */
 /* Called from AGI */
@@ -2277,7 +2460,7 @@ static int ast_say_enumeration_full_en(struct ast_channel *chan, int num, const
        int res = 0, t = 0;
        char fn[256] = "";
        
-       while(!res && num) {
+       while (!res && num) {
                if (num < 0) {
                        snprintf(fn, sizeof(fn), "digits/minus"); /* kind of senseless for enumerations, but our best effort for error checking */
                        if ( num > INT_MIN ) {
@@ -2351,8 +2534,7 @@ static int ast_say_enumeration_full_en(struct ast_channel *chan, int num, const
                        snprintf(fn, sizeof(fn), "digits/h-last");
                        num = 0;
                } else {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                       ast_debug(1, "Number '%d' is too big for me\n", num);
                        res = -1;
                }
 
@@ -2389,7 +2571,7 @@ static int ast_say_enumeration_full_da(struct ast_channel *chan, int num, const
        if (!num) 
                return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
 
-       while(!res && num) {
+       while (!res && num) {
                if (num < 0) {
                        snprintf(fn, sizeof(fn), "digits/minus"); /* kind of senseless for enumerations, but our best effort for error checking */
                        if ( num > INT_MIN ) {
@@ -2505,8 +2687,7 @@ static int ast_say_enumeration_full_da(struct ast_channel *chan, int num, const
                        snprintf(fn, sizeof(fn), "digits/h-last%s", gender);
                        num = 0;
                } else {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                       ast_debug(1, "Number '%d' is too big for me\n", num);
                        res = -1;
                }
 
@@ -2553,7 +2734,7 @@ static int ast_say_enumeration_full_de(struct ast_channel *chan, int num, const
        if (!num) 
                return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
 
-       while(!res && num) {
+       while (!res && num) {
                if (num < 0) {
                        snprintf(fn, sizeof(fn), "digits/minus"); /* kind of senseless for enumerations, but our best effort for error checking */
                        if ( num > INT_MIN ) {
@@ -2669,8 +2850,7 @@ static int ast_say_enumeration_full_de(struct ast_channel *chan, int num, const
                        snprintf(fn, sizeof(fn), "digits/h-last%s", gender);
                        num = 0;
                } else {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                       ast_debug(1, "Number '%d' is too big for me\n", num);
                        res = -1;
                }
 
@@ -2708,12 +2888,18 @@ static int say_date(struct ast_channel *chan, time_t t, const char *ints, const
                return(ast_say_date_de(chan, t, ints, lang));
        } else if (!strcasecmp(lang, "fr") ) {  /* French syntax */
                return(ast_say_date_fr(chan, t, ints, lang));
+       } else if (!strcasecmp(lang, "hu") ) {  /* Hungarian syntax */
+               return(ast_say_date_hu(chan, t, ints, lang));
        } else if (!strcasecmp(lang, "nl") ) {  /* Dutch syntax */
                return(ast_say_date_nl(chan, t, ints, lang));
-       } else if (!strcasecmp(lang, "pt") ) {  /* Portuguese syntax */
+       } else if (!strcasecmp(lang, "pt") || !strcasecmp(lang, "pt_BR")) {     /* Portuguese syntax */
                return(ast_say_date_pt(chan, t, ints, lang));
        } else if (!strcasecmp(lang, "gr") ) {                          /* Greek syntax */
                return(ast_say_date_gr(chan, t, ints, lang));
+       } else if (!strcasecmp(lang, "th") ) {  /* Thai syntax */
+               return(ast_say_date_th(chan, t, ints, lang));
+       } else if (!strcasecmp(lang, "ge") ) {  /* Georgian syntax */
+               return(ast_say_date_ge(chan, t, ints, lang));
        }
 
        /* Default to English */
@@ -2845,6 +3031,37 @@ int ast_say_date_de(struct ast_channel *chan, time_t t, const char *ints, const
        return res;
 }
 
+/* Hungarian syntax */
+int ast_say_date_hu(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+       struct tm tm;
+       char fn[256];
+       int res = 0;
+       ast_localtime(&t,&tm,NULL);
+
+       if (!res)
+               res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
+       if (!res)
+               res = ast_waitstream(chan, ints);
+       if (!res) {
+               snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
+               res = ast_streamfile(chan, fn, lang);
+               if (!res)
+                       res = ast_waitstream(chan, ints);
+       }       
+       if (!res)
+               ast_say_number(chan, tm.tm_mday , ints, lang, (char *) NULL);
+       if (!res)
+               res = ast_waitstream(chan, ints);
+       if (!res) {
+               snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
+               res = ast_streamfile(chan, fn, lang);
+               if (!res)
+                       res = ast_waitstream(chan, ints);               
+       }
+       return res;
+}
+
 /* French syntax */
 int ast_say_date_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 {
@@ -2901,14 +3118,49 @@ int ast_say_date_nl(struct ast_channel *chan, time_t t, const char *ints, const
        return res;
 }
 
+/* Thai syntax */
+int ast_say_date_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+       struct tm tm;
+       char fn[256];
+       int res = 0;
+       ast_localtime(&t,&tm,NULL);
+       if (!res) {
+               snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
+               res = ast_streamfile(chan, fn, lang);
+               snprintf(fn, sizeof(fn), "digits/tee");
+               res = ast_streamfile(chan, fn, lang);
+               if (!res)
+                       res = ast_waitstream(chan, ints);
+       }
+       if (!res)
+               res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
+       if (!res)
+               res = ast_waitstream(chan, ints);
+       if (!res) {
+               snprintf(fn, sizeof(fn), "digits/duan");
+               res = ast_streamfile(chan, fn, lang);
+               snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
+               res = ast_streamfile(chan, fn, lang);
+               if (!res)
+                       res = ast_waitstream(chan, ints);
+       }
+       if (!res){
+               snprintf(fn, sizeof(fn), "digits/posor");
+               res = ast_streamfile(chan, fn, lang);
+               res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
+       }       
+       return res;
+}
+
 /* Portuguese syntax */
 int ast_say_date_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 {
        struct tm tm;
        char fn[256];
        int res = 0;
-       ast_localtime(&t,&tm,NULL);
-       localtime_r(&t,&tm);
+
+       ast_localtime(&t, &tm, NULL);
        snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
        if (!res)
                res = wait_file(chan, ints, fn, lang);
@@ -2947,10 +3199,12 @@ static int say_date_with_format(struct ast_channel *chan, time_t time, const cha
                return(ast_say_date_with_format_nl(chan, time, ints, lang, format, timezone));
        } else if (!strcasecmp(lang, "pl") ) {  /* Polish syntax */
                return(ast_say_date_with_format_pl(chan, time, ints, lang, format, timezone));
-       } else if (!strcasecmp(lang, "pt") ) {  /* Portuguese syntax */
+       } else if (!strcasecmp(lang, "pt") || !strcasecmp(lang, "pt_BR")) {     /* Portuguese syntax */
                return(ast_say_date_with_format_pt(chan, time, ints, lang, format, timezone));
        } else if (!strcasecmp(lang, "tw") || !strcasecmp(lang, "zh") ) {       /* Taiwanese / Chinese syntax */
                return(ast_say_date_with_format_tw(chan, time, ints, lang, format, timezone));
+       } else if (!strcasecmp(lang, "th") ) {  /* Thai syntax */
+               return(ast_say_date_with_format_th(chan, time, ints, lang, format, timezone));
        } else if (!strcasecmp(lang, "gr") ) {  /* Greek syntax */
                return(ast_say_date_with_format_gr(chan, time, ints, lang, format, timezone));
        }
@@ -2972,8 +3226,7 @@ int ast_say_date_with_format_en(struct ast_channel *chan, time_t time, const cha
        ast_localtime(&time,&tm,timezone);
 
        for (offset=0 ; format[offset] != '\0' ; offset++) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
+               ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
                switch (format[offset]) {
                        /* NOTE:  if you add more options here, please try to be consistent with strftime(3) */
                        case '\'':
@@ -3215,8 +3468,7 @@ int ast_say_date_with_format_da(struct ast_channel *chan, time_t time, const cha
        ast_localtime(&time,&tm,timezone);
 
        for (offset=0 ; format[offset] != '\0' ; offset++) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
+               ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
                switch (format[offset]) {
                        /* NOTE:  if you add more options here, please try to be consistent with strftime(3) */
                        case '\'':
@@ -3421,8 +3673,7 @@ int ast_say_date_with_format_de(struct ast_channel *chan, time_t time, const cha
        ast_localtime(&time,&tm,timezone);
 
        for (offset=0 ; format[offset] != '\0' ; offset++) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
+               ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
                switch (format[offset]) {
                        /* NOTE:  if you add more options here, please try to be consistent with strftime(3) */
                        case '\'':
@@ -3612,48 +3863,20 @@ int ast_say_date_with_format_de(struct ast_channel *chan, time_t time, const cha
        return res;
 }
 
-/* TODO: this probably is not the correct format for doxygen remarks */
-
-/** ast_say_date_with_format_he Say formmated date in Hebrew
- *
- * \ref ast_say_date_with_format_en for the details of the options 
- *
- * Changes from the English version: 
- *
- * * don't replicate in here the logic of ast_say_number_full_he
- *
- * * year is always 4-digit (because it's simpler)
- *
- * * added c, x, and X. Mainly for my tests
- *
- * * The standard "long" format used in Hebrew is AdBY, rather than ABdY
- *
- * TODO: 
- * * A "ha" is missing in the standard date format, before the 'd'.
- * * The numbers of 3000--19000 are not handled well
- **/
-#define IL_DATE_STR "AdBY"
-#define IL_TIME_STR "IMp"
-#define IL_DATE_STR_FULL IL_DATE_STR " 'digits/at' " IL_TIME_STR
-int ast_say_date_with_format_he(struct ast_channel *chan, time_t time, 
-    const char *ints, const char *lang, const char *format, 
-    const char *timezone)
+/* Thai syntax */
+int ast_say_date_with_format_th(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
 {
-       /* TODO: This whole function is cut&paste from 
-        * ast_say_date_with_format_en . Is that considered acceptable?
-        **/
        struct tm tm;
        int res=0, offset, sndoffset;
        char sndfile[256], nextmsg[256];
 
-       if (!format)
-               format = IL_DATE_STR_FULL;
+       if (format == NULL)
+               format = "a 'digits/tee' e 'digits/duan' hY  I 'digits/naliga' M 'digits/natee'";
 
        ast_localtime(&time,&tm,timezone);
 
        for (offset=0 ; format[offset] != '\0' ; offset++) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
+               ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
                switch (format[offset]) {
                        /* NOTE:  if you add more options here, please try to be consistent with strftime(3) */
                        case '\'':
@@ -3677,8 +3900,206 @@ int ast_say_date_with_format_he(struct ast_channel *chan, time_t time,
                                snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
                                res = wait_file(chan,ints,nextmsg,lang);
                                break;
+                       case 'm':
+                               /* Month enumerated */
+                               res = ast_say_number(chan, (tm.tm_mon + 1), ints, lang, (char *) NULL); 
+                               break;
                        case 'd':
-                       case 'e': /* Day of the month */
+                       case 'e':
+                               /* First - Thirtyfirst */
+                               res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);      
+                               break;
+                       case 'Y':
+                               /* Year */
+                               res = ast_say_number(chan, tm.tm_year + 1900 + 543, ints, lang, (char *) NULL);
+                               break;
+                       case 'I':
+                       case 'l':
+                               /* 12-Hour */
+                               if (tm.tm_hour == 0)
+                                       snprintf(nextmsg,sizeof(nextmsg), "digits/24");
+                               snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
+                               res = wait_file(chan,ints,nextmsg,lang);
+                               break;
+                       case 'H':
+                       case 'k':
+                               /* 24-Hour */
+                               if (tm.tm_hour == 0)
+                                       snprintf(nextmsg,sizeof(nextmsg), "digits/24");
+                               snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
+                               res = wait_file(chan,ints,nextmsg,lang);
+                               break;
+                       case 'M':
+                       case 'N':
+                               res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
+                               break;
+                       case 'P':
+                       case 'p':
+                               break;
+                       case 'Q':
+                               /* Shorthand for "Today", "Yesterday", or ABdY */
+                               /* XXX As emphasized elsewhere, this should the native way in your
+                                * language to say the date, with changes in what you say, depending
+                                * upon how recent the date is. XXX */
+                               {
+                                       struct timeval now;
+                                       struct tm tmnow;
+                                       time_t beg_today, tt;
+
+                                       gettimeofday(&now,NULL);
+                                       tt = now.tv_sec;
+                                       ast_localtime(&tt,&tmnow,timezone);
+                                       /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
+                                       /* In any case, it saves not having to do ast_mktime() */
+                                       beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
+                                       if (beg_today < time) {
+                                               /* Today */
+                                               res = wait_file(chan,ints, "digits/today",lang);
+                                       } else if (beg_today - 86400 < time) {
+                                               /* Yesterday */
+                                               res = wait_file(chan,ints, "digits/yesterday",lang);
+                                       } else if (beg_today - 86400 * 6 < time) {
+                                               /* Within the last week */
+                                               res = ast_say_date_with_format_en(chan, time, ints, lang, "A", timezone);
+                                       } else if (beg_today - 2628000 < time) {
+                                               /* Less than a month ago - "Sunday, October third" */
+                                               res = ast_say_date_with_format_en(chan, time, ints, lang, "ABd", timezone);
+                                       } else if (beg_today - 15768000 < time) {
+                                               /* Less than 6 months ago - "August seventh" */
+                                               res = ast_say_date_with_format_en(chan, time, ints, lang, "Bd", timezone);
+                                       } else {
+                                               /* More than 6 months ago - "April nineteenth two thousand three" */
+                                               res = ast_say_date_with_format_en(chan, time, ints, lang, "BdY", timezone);
+                                       }
+                               }
+                               break;
+                       case 'q':
+                               /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
+                               /* XXX As emphasized elsewhere, this should the native way in your
+                                * language to say the date, with changes in what you say, depending
+                                * upon how recent the date is. XXX */
+                               {
+                                       struct timeval now;
+                                       struct tm tmnow;
+                                       time_t beg_today, tt;
+
+                                       gettimeofday(&now,NULL);
+                                       tt = now.tv_sec;
+                                       ast_localtime(&tt,&tmnow,timezone);
+                                       /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
+                                       /* In any case, it saves not having to do ast_mktime() */
+                                       beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
+                                       if (beg_today < time) {
+                                               /* Today */
+                                       } else if ((beg_today - 86400) < time) {
+                                               /* Yesterday */
+                                               res = wait_file(chan,ints, "digits/yesterday",lang);
+                                       } else if (beg_today - 86400 * 6 < time) {
+                                               /* Within the last week */
+                                               res = ast_say_date_with_format_en(chan, time, ints, lang, "A", timezone);
+                                       } else if (beg_today - 2628000 < time) {
+                                               /* Less than a month ago - "Sunday, October third" */
+                                               res = ast_say_date_with_format_en(chan, time, ints, lang, "ABd", timezone);
+                                       } else if (beg_today - 15768000 < time) {
+                                               /* Less than 6 months ago - "August seventh" */
+                                               res = ast_say_date_with_format_en(chan, time, ints, lang, "Bd", timezone);
+                                       } else {
+                                               /* More than 6 months ago - "April nineteenth two thousand three" */
+                                               res = ast_say_date_with_format_en(chan, time, ints, lang, "BdY", timezone);
+                                       }
+                               }
+                               break;
+                       case 'R':
+                               res = ast_say_date_with_format_en(chan, time, ints, lang, "HM", timezone);
+                               break;
+                       case 'S':
+                               res = ast_say_number(chan, tm.tm_sec, ints, lang, (char *) NULL);
+                               break;
+                       case 'T':
+                               res = ast_say_date_with_format_en(chan, time, ints, lang, "HMS", timezone);
+                               break;
+                       case ' ':
+                       case '  ':
+                               /* Just ignore spaces and tabs */
+                               break;
+                       default:
+                               /* Unknown character */
+                               ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
+               }
+               /* Jump out on DTMF */
+               if (res) {
+                       break;
+               }
+       }
+       return res;
+}
+
+/* TODO: this probably is not the correct format for doxygen remarks */
+
+/** ast_say_date_with_format_he Say formatted date in Hebrew
+ *
+ * \ref ast_say_date_with_format_en for the details of the options 
+ *
+ * Changes from the English version: 
+ *
+ * * don't replicate in here the logic of ast_say_number_full_he
+ *
+ * * year is always 4-digit (because it's simpler)
+ *
+ * * added c, x, and X. Mainly for my tests
+ *
+ * * The standard "long" format used in Hebrew is AdBY, rather than ABdY
+ *
+ * TODO: 
+ * * A "ha" is missing in the standard date format, before the 'd'.
+ * * The numbers of 3000--19000 are not handled well
+ **/
+#define IL_DATE_STR "AdBY"
+#define IL_TIME_STR "IMp"
+#define IL_DATE_STR_FULL IL_DATE_STR " 'digits/at' " IL_TIME_STR
+int ast_say_date_with_format_he(struct ast_channel *chan, time_t time, 
+    const char *ints, const char *lang, const char *format, 
+    const char *timezone)
+{
+       /* TODO: This whole function is cut&paste from 
+        * ast_say_date_with_format_en . Is that considered acceptable?
+        **/
+       struct tm tm;
+       int res=0, offset, sndoffset;
+       char sndfile[256], nextmsg[256];
+
+       if (!format)
+               format = IL_DATE_STR_FULL;
+
+       ast_localtime(&time,&tm,timezone);
+
+       for (offset=0 ; format[offset] != '\0' ; offset++) {
+               ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
+               switch (format[offset]) {
+                       /* NOTE:  if you add more options here, please try to be consistent with strftime(3) */
+                       case '\'':
+                               /* Literal name of a sound file */
+                               sndoffset=0;
+                               for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
+                                       sndfile[sndoffset] = format[offset];
+                               sndfile[sndoffset] = '\0';
+                               res = wait_file(chan,ints,sndfile,lang);
+                               break;
+                       case 'A':
+                       case 'a':
+                               /* Sunday - Saturday */
+                               snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
+                               res = wait_file(chan,ints,nextmsg,lang);
+                               break;
+                       case 'B':
+                       case 'b':
+                       case 'h':
+                               /* January - December */
+                               snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
+                               res = wait_file(chan,ints,nextmsg,lang);
+                               break;
+                       case 'd':
+                       case 'e': /* Day of the month */
                                 /* I'm not sure exactly what the parameters 
                                  * audiofd and ctrlfd to 
                                  * ast_say_number_full_he mean, but it seems
@@ -3835,8 +4256,7 @@ int ast_say_date_with_format_es(struct ast_channel *chan, time_t time, const cha
        ast_localtime(&time,&tm,timezone);
 
        for (offset=0 ; format[offset] != '\0' ; offset++) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
+               ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
                switch (format[offset]) {
                        /* NOTE:  if you add more options here, please try to be consistent with strftime(3) */
                        case '\'':
@@ -4028,8 +4448,7 @@ int ast_say_date_with_format_fr(struct ast_channel *chan, time_t time, const cha
        ast_localtime(&time,&tm,timezone);
 
        for (offset=0 ; format[offset] != '\0' ; offset++) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
+               ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
                switch (format[offset]) {
                        /* NOTE:  if you add more options here, please try to be consistent with strftime(3) */
                        case '\'':
@@ -4227,8 +4646,7 @@ int ast_say_date_with_format_it(struct ast_channel *chan, time_t time, const cha
        ast_localtime(&time,&tm,timezone);
 
        for (offset=0 ; format[offset] != '\0' ; offset++) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
+               ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
                switch (format[offset]) {
                        /* NOTE:  if you add more options here, please try to be consistent with strftime(3) */
                        case '\'':
@@ -4461,8 +4879,7 @@ int ast_say_date_with_format_nl(struct ast_channel *chan, time_t time, const cha
        ast_localtime(&time,&tm,timezone);
 
        for (offset=0 ; format[offset] != '\0' ; offset++) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
+               ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
                switch (format[offset]) {
                        /* NOTE:  if you add more options here, please try to be consistent with strftime(3) */
                        case '\'':
@@ -4636,32 +5053,7 @@ int ast_say_date_with_format_nl(struct ast_channel *chan, time_t time, const cha
                                break;
                        case 'S':
                                /* Seconds */
-                               if (tm.tm_sec == 0) {
-                                       snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
-                                       res = wait_file(chan,ints,nextmsg,lang);
-                               } else if (tm.tm_sec < 10) {
-                                       res = wait_file(chan,ints, "digits/oh",lang);
-                                       if (!res) {
-                                               snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
-                                               res = wait_file(chan,ints,nextmsg,lang);
-                                       }
-                               } else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
-                                       snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
-                                       res = wait_file(chan,ints,nextmsg,lang);
-                               } else {
-                                       int ten, one;
-                                       ten = (tm.tm_sec / 10) * 10;
-                                       one = (tm.tm_sec % 10);
-                                       snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten);
-                                       res = wait_file(chan,ints,nextmsg,lang);
-                                       if (!res) {
-                                               /* Fifty, not fifty-zero */
-                                               if (one != 0) {
-                                                       snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
-                                                       res = wait_file(chan,ints,nextmsg,lang);
-                                               }
-                                       }
-                               }
+                               res = ast_say_number(chan, tm.tm_sec, ints, lang, (char *) NULL);
                                break;
                        case 'T':
                                res = ast_say_date_with_format_nl(chan, time, ints, lang, "HMS", timezone);
@@ -4693,8 +5085,7 @@ int ast_say_date_with_format_pl(struct ast_channel *chan, time_t thetime, const
 
        for (offset = 0 ; format[offset] != '\0' ; offset++) {
                int remainder;
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
+               ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
                switch (format[offset]) {
                        /* NOTE:  if you add more options here, please try to be consistent with strftime(3) */
                        case '\'':
@@ -4912,8 +5303,7 @@ int ast_say_date_with_format_pt(struct ast_channel *chan, time_t time, const cha
        ast_localtime(&time,&tm,timezone);
 
        for (offset=0 ; format[offset] != '\0' ; offset++) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
+               ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
                switch (format[offset]) {
                        /* NOTE:  if you add more options here, please try to be consistent with strftime(3) */
                        case '\'':
@@ -4940,8 +5330,12 @@ int ast_say_date_with_format_pt(struct ast_channel *chan, time_t time, const cha
                                break;
                        case 'm':
                                /* First - Twelfth */
-                               snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
-                               res = wait_file(chan,ints,nextmsg,lang);
+                               if (!strcasecmp(lang, "pt_BR")) {
+                                       res = ast_say_number(chan, tm.tm_mon+1, ints, lang, (char *) NULL);
+                               } else {
+                                       snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
+                                       res = wait_file(chan,ints,nextmsg,lang);
+                               }
                                break;
                        case 'd':
                        case 'e':
@@ -4955,66 +5349,126 @@ int ast_say_date_with_format_pt(struct ast_channel *chan, time_t time, const cha
                        case 'I':
                        case 'l':
                                /* 12-Hour */
-                               if (tm.tm_hour == 0) {
-                                       if (format[offset] == 'I')
-                                               res = wait_file(chan, ints, "digits/pt-ah", lang);
-                                       if (!res)
-                                               res = wait_file(chan, ints, "digits/pt-meianoite", lang);
-                               }
-                               else if (tm.tm_hour == 12) {
-                                       if (format[offset] == 'I')
-                                               res = wait_file(chan, ints, "digits/pt-ao", lang);
-                                       if (!res)
-                                               res = wait_file(chan, ints, "digits/pt-meiodia", lang);
-                               }
-                               else {
-                                       if (format[offset] == 'I') {
-                                               res = wait_file(chan, ints, "digits/pt-ah", lang);
-                                               if ((tm.tm_hour % 12) != 1)
-                                                       if (!res)
-                                                               res = wait_file(chan, ints, "digits/pt-sss", lang);
+                               if (!strcasecmp(lang, "pt_BR")) {
+                                       if (tm.tm_hour == 0) {
+                                               if (format[offset] == 'I')
+                                                       res = wait_file(chan, ints, "digits/pt-a", lang);
+                                               if (!res)
+                                                       res = wait_file(chan, ints, "digits/pt-meianoite", lang);
+                                       } else if (tm.tm_hour == 12) {
+                                               if (format[offset] == 'I')
+                                                       res = wait_file(chan, ints, "digits/pt-ao", lang);
+                                               if (!res)
+                                                       res = wait_file(chan, ints, "digits/pt-meiodia", lang);
+                                               } else {
+                                               if (format[offset] == 'I') {
+                                                       if ((tm.tm_hour % 12) != 1)
+                                                               res = wait_file(chan, ints, "digits/pt-as", lang);
+                                                       else
+                                                               res = wait_file(chan, ints, "digits/pt-a", lang);
+                                               }
+                                               if (!res)
+                                                       res = ast_say_number(chan, (tm.tm_hour % 12), ints, lang, "f");
+                                               if ((!res) && (format[offset] == 'I'))
+                                               res = ast_say_date_with_format(chan, time, ints, lang, "P", timezone);
+                                       }
+                               } else {
+                                       if (tm.tm_hour == 0) {
+                                               if (format[offset] == 'I')
+                                                       res = wait_file(chan, ints, "digits/pt-ah", lang);
+                                               if (!res)
+                                                       res = wait_file(chan, ints, "digits/pt-meianoite", lang);
+                                               }
+                                       else if (tm.tm_hour == 12) {
+                                               if (format[offset] == 'I')
+                                                       res = wait_file(chan, ints, "digits/pt-ao", lang);
+                                               if (!res)
+                                                       res = wait_file(chan, ints, "digits/pt-meiodia", lang);
+                                       }
+                                       else {
+                                               if (format[offset] == 'I') {
+                                                       res = wait_file(chan, ints, "digits/pt-ah", lang);
+                                                       if ((tm.tm_hour % 12) != 1)
+                                                               if (!res)
+                                                                       res = wait_file(chan, ints, "digits/pt-sss", lang);
+                                               }
+                                               if (!res)
+                                                       res = ast_say_number(chan, (tm.tm_hour % 12), ints, lang, "f");
                                        }
-                                       if (!res)
-                                               res = ast_say_number(chan, (tm.tm_hour % 12), ints, lang, "f");
                                }
                                break;
                        case 'H':
                        case 'k':
                                /* 24-Hour */
-                               res = ast_say_number(chan, -tm.tm_hour, ints, lang, NULL);
-                               if (!res) {
-                                       if (tm.tm_hour != 0) {
-                                               int remainder = tm.tm_hour;
-                                               if (tm.tm_hour > 20) {
-                                                       res = wait_file(chan,ints, "digits/20",lang);
-                                                       remainder -= 20;
-                                               }
-                                               if (!res) {
-                                                       snprintf(nextmsg,sizeof(nextmsg), "digits/%d", remainder);
-                                                       res = wait_file(chan,ints,nextmsg,lang);
+                               if (!strcasecmp(lang, "pt_BR")) {
+                                       res = ast_say_number(chan, tm.tm_hour, ints, lang, "f");
+                                       if ((!res) && (format[offset] == 'H')) {
+                                               if (tm.tm_hour > 1) {
+                                                       res = wait_file(chan,ints,"digits/hours",lang);
+                                               } else {
+                                                       res = wait_file(chan,ints,"digits/hour",lang);
                                                }
                                        }
-                               }
-                               break;
-                       case 'M':
-                               /* Minute */
-                               if (tm.tm_min == 0) {
-                                       res = wait_file(chan, ints, "digits/pt-hora", lang);
-                                       if (tm.tm_hour != 1)
+                               } else {
+                                       res = ast_say_number(chan, -tm.tm_hour, ints, lang, NULL);
+                                       if (!res) {
+                                               if (tm.tm_hour != 0) {
+                                                       int remainder = tm.tm_hour;
+                                                       if (tm.tm_hour > 20) {
+                                                               res = wait_file(chan,ints, "digits/20",lang);
+                                                               remainder -= 20;
+                                                       }
+                                                       if (!res) {
+                                                               snprintf(nextmsg,sizeof(nextmsg), "digits/%d", remainder);
+                                                               res = wait_file(chan,ints,nextmsg,lang);
+                                                       }
+                                               }
+                                       }
+                               }
+                               break;
+                       case 'M':
+                               /* Minute */
+                               if (!strcasecmp(lang, "pt_BR")) {
+                                       res = ast_say_number(chan, tm.tm_min, ints, lang, NULL);
+                                       if (!res) {
+                                               if (tm.tm_min > 1) {
+                                                       res = wait_file(chan,ints,"digits/minutes",lang);
+                                               } else {
+                                                       res = wait_file(chan,ints,"digits/minute",lang);
+                                               }
+                                       }
+                               } else {
+                                       if (tm.tm_min == 0) {
+                                               res = wait_file(chan, ints, "digits/pt-hora", lang);
+                                               if (tm.tm_hour != 1)
+                                                       if (!res)
+                                                               res = wait_file(chan, ints, "digits/pt-sss", lang);                     } else {
+                                               res = wait_file(chan,ints,"digits/pt-e",lang);
                                                if (!res)
-                                                       res = wait_file(chan, ints, "digits/pt-sss", lang);                     } else {
-                                       res = wait_file(chan,ints,"digits/pt-e",lang);
-                                       if (!res)
-                                               res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);       
+                                                       res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);       
+                                       }
                                }
                                break;
                        case 'P':
                        case 'p':
                                /* AM/PM */
-                               if (tm.tm_hour > 12)
-                                       res = wait_file(chan, ints, "digits/p-m", lang);
-                               else if (tm.tm_hour  && tm.tm_hour < 12)
-                                       res = wait_file(chan, ints, "digits/a-m", lang);
+                               if (!strcasecmp(lang, "pt_BR")) {
+                                       if ((tm.tm_hour != 0) && (tm.tm_hour != 12)) {
+                                               res = wait_file(chan, ints, "digits/pt-da", lang);
+                                               if (!res) {
+                                                       if ((tm.tm_hour >= 0) && (tm.tm_hour < 12))
+                                                               res = wait_file(chan, ints, "digits/morning", lang);
+                                                       else if ((tm.tm_hour >= 12) && (tm.tm_hour < 18))
+                                                               res = wait_file(chan, ints, "digits/afternoon", lang);
+                                                       else res = wait_file(chan, ints, "digits/night", lang);
+                                               }
+                                       }
+                               } else {
+                                       if (tm.tm_hour > 12)
+                                               res = wait_file(chan, ints, "digits/p-m", lang);
+                                       else if (tm.tm_hour  && tm.tm_hour < 12)
+                                               res = wait_file(chan, ints, "digits/a-m", lang);
+                               }
                                break;
                        case 'Q':
                                /* Shorthand for "Today", "Yesterday", or ABdY */
@@ -5077,30 +5531,41 @@ int ast_say_date_with_format_pt(struct ast_channel *chan, time_t time, const cha
                                break;
                        case 'S':
                                /* Seconds */
-                               if (tm.tm_sec == 0) {
-                                       snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
-                                       res = wait_file(chan,ints,nextmsg,lang);
-                               } else if (tm.tm_sec < 10) {
-                                       res = wait_file(chan,ints, "digits/oh",lang);
+                               if (!strcasecmp(lang, "pt_BR")) {
+                                       res = ast_say_number(chan, tm.tm_sec, ints, lang, NULL);
                                        if (!res) {
-                                               snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
-                                               res = wait_file(chan,ints,nextmsg,lang);
+                                               if (tm.tm_sec > 1) {
+                                                       res = wait_file(chan,ints,"digits/seconds",lang);
+                                               } else {
+                                                       res = wait_file(chan,ints,"digits/second",lang);
+                                               }
                                        }
-                               } else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
-                                       snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
-                                       res = wait_file(chan,ints,nextmsg,lang);
                                } else {
-                                       int ten, one;
-                                       ten = (tm.tm_sec / 10) * 10;
-                                       one = (tm.tm_sec % 10);
-                                       snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten);
-                                       res = wait_file(chan,ints,nextmsg,lang);
-                                       if (!res) {
-                                               /* Fifty, not fifty-zero */
-                                               if (one != 0) {
-                                                       snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
+                                       if (tm.tm_sec == 0) {
+                                               snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
+                                               res = wait_file(chan,ints,nextmsg,lang);
+                                       } else if (tm.tm_sec < 10) {
+                                               res = wait_file(chan,ints, "digits/oh",lang);
+                                               if (!res) {
+                                                       snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
                                                        res = wait_file(chan,ints,nextmsg,lang);
                                                }
+                                       } else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
+                                               snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
+                                               res = wait_file(chan,ints,nextmsg,lang);
+                                       } else {
+                                               int ten, one;
+                                               ten = (tm.tm_sec / 10) * 10;
+                                               one = (tm.tm_sec % 10);
+                                               snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten);
+                                               res = wait_file(chan,ints,nextmsg,lang);
+                                               if (!res) {
+                                                       /* Fifty, not fifty-zero */
+                                                       if (one != 0) {
+                                                               snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
+                                                               res = wait_file(chan,ints,nextmsg,lang);
+                                                       }
+                                               }
                                        }
                                }
                                break;
@@ -5131,13 +5596,12 @@ int ast_say_date_with_format_tw(struct ast_channel *chan, time_t time, const cha
        char sndfile[256], nextmsg[256];
 
        if (format == NULL)
-               format = "YBdA 'digits/at' HM";
+               format = "YBdAkM";
 
        ast_localtime(&time,&tm,timezone);
 
        for (offset=0 ; format[offset] != '\0' ; offset++) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
+               ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
                switch (format[offset]) {
                        /* NOTE:  if you add more options here, please try to be consistent with strftime(3) */
                        case '\'':
@@ -5170,16 +5634,17 @@ int ast_say_date_with_format_tw(struct ast_channel *chan, time_t time, const cha
                        case 'e':
                                /* First - Thirtyfirst */
                                if (!(tm.tm_mday % 10) || (tm.tm_mday < 10)) {
-                                       snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mday);
+                                       snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_mday);
                                        res = wait_file(chan,ints,nextmsg,lang);
                                } else {
-                                       snprintf(nextmsg,sizeof(nextmsg), "digits/h-%dh", tm.tm_mday - (tm.tm_mday % 10));
+                                       snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_mday - (tm.tm_mday % 10));
                                        res = wait_file(chan,ints,nextmsg,lang);
-                                       if(!res) {
-                                               snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mday % 10);
+                                       if (!res) {
+                                               snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_mday % 10);
                                                res = wait_file(chan,ints,nextmsg,lang);
                                        }
                                }
+                if(!res) res = wait_file(chan,ints,"ri",lang);
                                break;
                        case 'Y':
                                /* Year */
@@ -5249,12 +5714,12 @@ int ast_say_date_with_format_tw(struct ast_channel *chan, time_t time, const cha
                                }
                                break;
                        case 'H':
+                if (tm.tm_hour < 10) {
+                    res = wait_file(chan, ints, "digits/0", lang);
+                }
                        case 'k':
                                /* 24-Hour */
                                if (!(tm.tm_hour % 10) || tm.tm_hour < 10) {
-                                       if (tm.tm_hour < 10) {
-                                               res = wait_file(chan, ints, "digits/0", lang);
-                                       }
                                        snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
                                        res = wait_file(chan,ints,nextmsg,lang);
                                } else {
@@ -5355,7 +5820,7 @@ int ast_say_date_with_format_tw(struct ast_channel *chan, time_t time, const cha
                                }
                                break;
                        case 'R':
-                               res = ast_say_date_with_format_tw(chan, time, ints, lang, "HM", timezone);
+                               res = ast_say_date_with_format_tw(chan, time, ints, lang, "kM", timezone);
                                break;
                        case 'S':
                                /* Seconds */
@@ -5404,14 +5869,23 @@ static int say_time(struct ast_channel *chan, time_t t, const char *ints, const
                return(ast_say_time_de(chan, t, ints, lang));
        } else if (!strcasecmp(lang, "fr") ) {  /* French syntax */
                return(ast_say_time_fr(chan, t, ints, lang));
+       } else if (!strcasecmp(lang, "hu") ) {  /* Hungarian syntax */
+               return(ast_say_time_hu(chan, t, ints, lang));
        } else if (!strcasecmp(lang, "nl") ) {  /* Dutch syntax */
                return(ast_say_time_nl(chan, t, ints, lang));
        } else if (!strcasecmp(lang, "pt") ) {  /* Portuguese syntax */
                return(ast_say_time_pt(chan, t, ints, lang));
+       } else if (!strcasecmp(lang, "pt_BR") ) {       /* Brazilian Portuguese syntax */
+               return(ast_say_time_pt_BR(chan, t, ints, lang));
+       } else if (!strcasecmp(lang, "tw") ) {  /* Taiwanese syntax */
        } else if (!strcasecmp(lang, "tw") || !strcasecmp(lang, "zh") ) {       /* Taiwanese / Chinese syntax */
                return(ast_say_time_tw(chan, t, ints, lang));
        } else if (!strcasecmp(lang, "gr") ) {                          /* Greek syntax */
                return(ast_say_time_gr(chan, t, ints, lang));
+       } else if (!strcasecmp(lang, "th") ) {
+               return(ast_say_time_th(chan, t, ints, lang));
+       } else if (!strcasecmp(lang, "ge") ) {  /* Georgian syntax */
+               return(ast_say_time_ge(chan, t, ints, lang));
        }
 
        /* Default to English */
@@ -5424,7 +5898,8 @@ int ast_say_time_en(struct ast_channel *chan, time_t t, const char *ints, const
        struct tm tm;
        int res = 0;
        int hour, pm=0;
-       localtime_r(&t,&tm);
+
+       ast_localtime(&t, &tm, NULL);
        hour = tm.tm_hour;
        if (!hour)
                hour = 12;
@@ -5470,7 +5945,8 @@ int ast_say_time_de(struct ast_channel *chan, time_t t, const char *ints, const
 {
        struct tm tm;
        int res = 0;
-       localtime_r(&t,&tm);
+
+       ast_localtime(&t, &tm, NULL);
        if (!res)
                res = ast_say_number(chan, tm.tm_hour, ints, lang, "n");
        if (!res)
@@ -5483,12 +5959,35 @@ int ast_say_time_de(struct ast_channel *chan, time_t t, const char *ints, const
        return res;
 }
 
+/* Hungarian syntax */
+int ast_say_time_hu(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+       struct tm tm;
+       int res = 0;
+
+       ast_localtime(&t, &tm, NULL);
+       if (!res)
+               res = ast_say_number(chan, tm.tm_hour, ints, lang, "n");
+       if (!res)
+               res = ast_streamfile(chan, "digits/oclock", lang);
+       if (!res)
+               res = ast_waitstream(chan, ints);
+       if (!res)
+           if (tm.tm_min > 0) { 
+                       res = ast_say_number(chan, tm.tm_min, ints, lang, "f");
+                       if (!res)
+                               res = ast_streamfile(chan, "digits/minute", lang);
+               }
+       return res;
+}
+
 /* French syntax */
 int ast_say_time_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 {
        struct tm tm;
        int res = 0;
-       localtime_r(&t,&tm);
+
+       ast_localtime(&t, &tm, NULL);
 
        res = ast_say_number(chan, tm.tm_hour, ints, lang, "f");
        if (!res)
@@ -5505,7 +6004,8 @@ int ast_say_time_nl(struct ast_channel *chan, time_t t, const char *ints, const
 {
        struct tm tm;
        int res = 0;
-       localtime_r(&t,&tm);
+
+       ast_localtime(&t, &tm, NULL);
        if (!res)
                res = ast_say_number(chan, tm.tm_hour, ints, lang, (char *) NULL);
        if (!res)
@@ -5524,7 +6024,8 @@ int ast_say_time_pt(struct ast_channel *chan, time_t t, const char *ints, const
        struct tm tm;
        int res = 0;
        int hour;
-       localtime_r(&t,&tm);
+
+       ast_localtime(&t, &tm, NULL);
        hour = tm.tm_hour;
        if (!res)
                res = ast_say_number(chan, hour, ints, lang, "f");
@@ -5545,13 +6046,60 @@ int ast_say_time_pt(struct ast_channel *chan, time_t t, const char *ints, const
        return res;
 }
 
+/* Brazilian Portuguese syntax */
+int ast_say_time_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+       struct tm tm;
+       int res = 0;
+
+       ast_localtime(&t, &tm, NULL);
+
+       res = ast_say_number(chan, tm.tm_hour, ints, lang, "f");
+       if (!res) {
+               if (tm.tm_hour > 1)
+                       res = wait_file(chan, ints, "digits/hours", lang);
+               else
+                       res = wait_file(chan, ints, "digits/hour", lang);
+       }
+       if ((!res) && (tm.tm_min)) {
+               res = wait_file(chan, ints, "digits/pt-e", lang);
+               if (!res)
+                       res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
+               if (!res) {
+                       if (tm.tm_min > 1)
+                               res = wait_file(chan, ints, "digits/minutes", lang);
+                       else
+                               res = wait_file(chan, ints, "digits/minute", lang);
+               }
+       }
+       return res;
+}
+
+/* Thai  syntax */
+int ast_say_time_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+       struct tm tm;
+       int res = 0;
+       int hour;
+       ast_localtime(&t, &tm, NULL);
+       hour = tm.tm_hour;
+       if (!hour)
+               hour = 24;
+       if (!res)
+               res = ast_say_number(chan, hour, ints, lang, (char *) NULL);
+       if (!res)
+               res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
+       return res;
+}
+
 /* Taiwanese / Chinese  syntax */
 int ast_say_time_tw(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 {
        struct tm tm;
        int res = 0;
        int hour, pm=0;
-       localtime_r(&t,&tm);
+
+       ast_localtime(&t, &tm, NULL);
        hour = tm.tm_hour;
        if (!hour)
                hour = 12;
@@ -5595,12 +6143,20 @@ static int say_datetime(struct ast_channel *chan, time_t t, const char *ints, co
                return(ast_say_datetime_fr(chan, t, ints, lang));
        } else if (!strcasecmp(lang, "nl") ) {  /* Dutch syntax */
                return(ast_say_datetime_nl(chan, t, ints, lang));
+       } else if (!strcasecmp(lang, "hu") ) {  /* Hungarian syntax */
+               return(ast_say_datetime_hu(chan, t, ints, lang));
        } else if (!strcasecmp(lang, "pt") ) {  /* Portuguese syntax */
                return(ast_say_datetime_pt(chan, t, ints, lang));
+       } else if (!strcasecmp(lang, "pt_BR") ) {       /* Brazilian Portuguese syntax */
+               return(ast_say_datetime_pt_BR(chan, t, ints, lang));
        } else if (!strcasecmp(lang, "tw") || !strcasecmp(lang, "zh") ) {       /* Taiwanese / Chinese syntax */
                return(ast_say_datetime_tw(chan, t, ints, lang));
        } else if (!strcasecmp(lang, "gr") ) {                          /* Greek syntax */
                return(ast_say_datetime_gr(chan, t, ints, lang));
+       } else if (!strcasecmp(lang, "th") ) {  /* Thai syntax */
+               return(ast_say_datetime_th(chan, t, ints, lang));
+       } else if (!strcasecmp(lang, "ge") ) {  /* Georgian syntax */
+               return(ast_say_datetime_ge(chan, t, ints, lang));
        }
 
        /* Default to English */
@@ -5614,7 +6170,8 @@ int ast_say_datetime_en(struct ast_channel *chan, time_t t, const char *ints, co
        char fn[256];
        int res = 0;
        int hour, pm=0;
-       localtime_r(&t,&tm);
+
+       ast_localtime(&t, &tm, NULL);
        if (!res) {
                snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
                res = ast_streamfile(chan, fn, lang);
@@ -5677,7 +6234,8 @@ int ast_say_datetime_de(struct ast_channel *chan, time_t t, const char *ints, co
 {
        struct tm tm;
        int res = 0;
-       localtime_r(&t,&tm);
+
+       ast_localtime(&t, &tm, NULL);
        res = ast_say_date(chan, t, ints, lang);
        if (!res) 
                ast_say_time(chan, t, ints, lang);
@@ -5685,13 +6243,27 @@ int ast_say_datetime_de(struct ast_channel *chan, time_t t, const char *ints, co
 
 }
 
+/* Hungarian syntax */
+int ast_say_datetime_hu(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+       struct tm tm;
+       int res = 0;
+
+       ast_localtime(&t, &tm, NULL);
+       res = ast_say_date(chan, t, ints, lang);
+       if (!res) 
+               ast_say_time(chan, t, ints, lang);
+       return res;
+}
+
 /* French syntax */
 int ast_say_datetime_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 {
        struct tm tm;
        char fn[256];
        int res = 0;
-       localtime_r(&t,&tm);
+
+       ast_localtime(&t, &tm, NULL);
 
        if (!res)
                res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
@@ -5729,7 +6301,8 @@ int ast_say_datetime_nl(struct ast_channel *chan, time_t t, const char *ints, co
 {
        struct tm tm;
        int res = 0;
-       localtime_r(&t,&tm);
+
+       ast_localtime(&t, &tm, NULL);
        res = ast_say_date(chan, t, ints, lang);
        if (!res) {
                res = ast_streamfile(chan, "digits/nl-om", lang);
@@ -5748,7 +6321,8 @@ int ast_say_datetime_pt(struct ast_channel *chan, time_t t, const char *ints, co
        char fn[256];
        int res = 0;
        int hour, pm=0;
-       localtime_r(&t,&tm);
+
+       ast_localtime(&t, &tm, NULL);
        if (!res) {
                snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
                res = ast_streamfile(chan, fn, lang);
@@ -5806,6 +6380,61 @@ int ast_say_datetime_pt(struct ast_channel *chan, time_t t, const char *ints, co
        return res;
 }
 
+/* Brazilian Portuguese syntax */
+int ast_say_datetime_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+       struct tm tm;
+       int res = 0;
+
+       ast_localtime(&t, &tm, NULL);
+       res = ast_say_date(chan, t, ints, lang);
+       if (!res)
+               res = ast_say_time(chan, t, ints, lang);
+       return res;
+}
+
+/* Thai syntax */
+int ast_say_datetime_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+       struct tm tm;
+       char fn[256];
+       int res = 0;
+       int hour;
+       ast_localtime(&t, &tm, NULL);
+       if (!res) {
+               snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
+               res = ast_streamfile(chan, fn, lang);
+               if (!res)
+                       res = ast_waitstream(chan, ints);
+       }
+       if (!res) {
+               snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
+               res = ast_streamfile(chan, fn, lang);
+               if (!res)
+                       res = ast_waitstream(chan, ints);
+       }
+       if (!res){
+               snprintf(fn, sizeof(fn), "digits/posor");
+               res = ast_streamfile(chan, fn, lang);
+               res = ast_say_number(chan, tm.tm_year + 1900 + 543, ints, lang, (char *) NULL);
+       }       
+       if (!res)
+               res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
+
+       hour = tm.tm_hour;
+       if (!hour)
+               hour = 24;
+       if (!res){
+               snprintf(fn, sizeof(fn), "digits/wela");
+               res = ast_streamfile(chan, fn, lang);
+       }       
+       if (!res)
+               res = ast_say_number(chan, hour, ints, lang, (char *) NULL);
+       if (!res)
+               res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
+       return res;
+}
+
 /* Taiwanese / Chinese syntax */
 int ast_say_datetime_tw(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 {
@@ -5813,7 +6442,8 @@ int ast_say_datetime_tw(struct ast_channel *chan, time_t t, const char *ints, co
        char fn[256];
        int res = 0;
        int hour, pm=0;
-       localtime_r(&t,&tm);
+
+       ast_localtime(&t, &tm, NULL);
        if (!res)
                res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
        if (!res) {
@@ -5870,8 +6500,10 @@ static int say_datetime_from_now(struct ast_channel *chan, time_t t, const char
                return(ast_say_datetime_from_now_en(chan, t, ints, lang));
        } else if (!strcasecmp(lang, "fr") ) {  /* French syntax */
                return(ast_say_datetime_from_now_fr(chan, t, ints, lang));
-       } else if (!strcasecmp(lang, "pt") ) {  /* Portuguese syntax */
+       } else if (!strcasecmp(lang, "pt") || !strcasecmp(lang, "pt_BR")) {     /* Portuguese syntax */
                return(ast_say_datetime_from_now_pt(chan, t, ints, lang));
+       } else if (!strcasecmp(lang, "ge") ) {  /* Georgian syntax */
+               return(ast_say_datetime_from_now_ge(chan, t, ints, lang));
        }
 
        /* Default to English */
@@ -5890,8 +6522,8 @@ int ast_say_datetime_from_now_en(struct ast_channel *chan, time_t t, const char
 
        time(&nowt);
 
-       localtime_r(&t,&tm);
-       localtime_r(&nowt,&now);
+       ast_localtime(&t, &tm, NULL);
+       ast_localtime(&nowt,&now, NULL);
        daydiff = now.tm_yday - tm.tm_yday;
        if ((daydiff < 0) || (daydiff > 6)) {
                /* Day of month and month */
@@ -5930,8 +6562,8 @@ int ast_say_datetime_from_now_fr(struct ast_channel *chan, time_t t, const char
 
        time(&nowt);
 
-       localtime_r(&t,&tm);
-       localtime_r(&nowt,&now);
+       ast_localtime(&t, &tm, NULL);
+       ast_localtime(&nowt, &now, NULL);
        daydiff = now.tm_yday - tm.tm_yday;
        if ((daydiff < 0) || (daydiff > 6)) {
                /* Day of month and month */
@@ -5970,8 +6602,8 @@ int ast_say_datetime_from_now_pt(struct ast_channel *chan, time_t t, const char
 
        time(&nowt);
 
-       localtime_r(&t,&tm);
-       localtime_r(&nowt,&now);
+       ast_localtime(&t, &tm, NULL);
+       ast_localtime(&nowt, &now, NULL);
        daydiff = now.tm_yday - tm.tm_yday;
        if ((daydiff < 0) || (daydiff > 6)) {
                /* Day of month and month */
@@ -5989,14 +6621,24 @@ int ast_say_datetime_from_now_pt(struct ast_channel *chan, time_t t, const char
                if (!res)
                        res = wait_file(chan, ints, fn, lang);
        }       /* Otherwise, it was today */
-       snprintf(fn, sizeof(fn), "digits/pt-ah");
-       if (!res)
-               res = wait_file(chan, ints, fn, lang);
-       if (tm.tm_hour != 1)
-       if (!res)
-               res = wait_file(chan, ints, "digits/pt-sss", lang);
-       if (!res)
-               res = ast_say_time(chan, t, ints, lang);
+       if (!strcasecmp(lang, "pt_BR")) {
+               if (tm.tm_hour > 1) {
+                       snprintf(fn, sizeof(fn), "digits/pt-as");
+               } else {
+                       snprintf(fn, sizeof(fn), "digits/pt-a");
+               }
+               if (!res)
+                       res = wait_file(chan, ints, fn, lang);
+       } else {
+               snprintf(fn, sizeof(fn), "digits/pt-ah");
+               if (!res)
+                       res = wait_file(chan, ints, fn, lang);
+               if (tm.tm_hour != 1)
+               if (!res)
+                       res = wait_file(chan, ints, "digits/pt-sss", lang);
+               if (!res)
+                       res = ast_say_time(chan, t, ints, lang);
+       }
        return res;
 }
 
@@ -6013,7 +6655,7 @@ static int gr_say_number_female(int num, struct ast_channel *chan, const char *i
        int res;
        char fn[256] = "";
 
-       /* ast_log(LOG_DEBUG, "\n\n Saying number female %s %d \n\n",lang, num); */
+       /* ast_debug(1, "\n\n Saying number female %s %d \n\n",lang, num); */
        if (num < 5) {
                snprintf(fn, sizeof(fn), "digits/female-%d", num);
                res = wait_file(chan, ints, fn, lang);
@@ -6067,7 +6709,7 @@ static int ast_say_number_full_gr(struct ast_channel *chan, int num, const char
                        return  ast_waitstream(chan, ints);
        }
 
-       while(!res && num ) {
+       while (!res && num ) {
                i++;
                if (num < 13) {
                        snprintf(fn, sizeof(fn), "digits/%d", num);
@@ -6104,14 +6746,13 @@ static int ast_say_number_full_gr(struct ast_channel *chan, int num, const char
                                        num = num % 1000000;
                                        snprintf(fn, sizeof(fn), "digits/millions");
                                } else {
-                                       if (option_debug)
-                                               ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
+                                       ast_debug(1, "Number '%d' is too big for me\n", num);
                                        res = -1;
                                }
                        }
                } 
                if (!res) {
-                       if(!ast_streamfile(chan, fn, language)) {
+                       if (!ast_streamfile(chan, fn, language)) {
                                if ((audiofd > -1) && (ctrlfd > -1))
                                        res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
                                else
@@ -6185,7 +6826,7 @@ static int ast_say_time_gr(struct ast_channel *chan, time_t t, const char *ints,
        int res = 0;
        int hour, pm=0;
 
-       localtime_r(&t,&tm);
+       ast_localtime(&t, &tm, NULL);
        hour = tm.tm_hour;
 
        if (!hour)
@@ -6230,7 +6871,8 @@ static int ast_say_datetime_gr(struct ast_channel *chan, time_t t, const char *i
        struct tm tm;
        char fn[256];
        int res = 0;
-       localtime_r(&t,&tm);
+
+       ast_localtime(&t, &tm, NULL);
 
        
        /* W E E K - D A Y */
@@ -6269,8 +6911,7 @@ static int ast_say_date_with_format_gr(struct ast_channel *chan, time_t time, co
        ast_localtime(&time,&tm,timezone);
        
        for (offset=0 ; format[offset] != '\0' ; offset++) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
+               ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
                switch (format[offset]) {
                        /* NOTE:  if you add more options here, please try to be consistent with strftime(3) */
                case '\'':
@@ -6432,6 +7073,380 @@ static int ast_say_date_with_format_gr(struct ast_channel *chan, time_t time, co
        return res;
 }
 
+
+
+
+/*********************************** Georgian Support ***************************************/
+
+
+/*
+       Convert a number into a semi-localized string. Only for Georgian.
+       res must be of at least 256 bytes, preallocated.
+       The output corresponds to Georgian spoken numbers, so
+       it may be either converted to real words by applying a direct conversion
+       table, or played just by substituting the entities with played files.
+
+       Output may consist of the following tokens (separated by spaces):
+       0, minus.
+       1-9, 1_-9_. (erti, ori, sami, otxi, ... . erti, or, sam, otx, ...).
+       10-19.
+       20, 40, 60, 80, 20_, 40_, 60_, 80_. (oci, ormoci, ..., ocda, ormocda, ...).
+       100, 100_, 200, 200_, ..., 900, 900_. (asi, as, orasi, oras, ...).
+       1000, 1000_. (atasi, atas).
+       1000000, 1000000_. (milioni, milion).
+       1000000000, 1000000000_. (miliardi, miliard).
+
+       To be able to play the sounds, each of the above tokens needs
+       a corresponding sound file. (e.g. 200_.gsm).
+*/
+static char* ast_translate_number_ge(int num, char* res, int res_len)
+{
+       char buf[256];
+       int digit = 0;
+       int remainder = 0;
+
+
+       if (num < 0) {
+               strncat(res, "minus ", res_len - strlen(res) - 1);
+               if ( num > INT_MIN ) {
+                       num = -num;
+               } else {
+                       num = 0;
+               }
+       }
+
+
+       /* directly read the numbers */
+       if (num <= 20 || num == 40 || num == 60 || num == 80 || num == 100) {
+               snprintf(buf, sizeof(buf), "%d", num);
+               strncat(res, buf, res_len - strlen(res) - 1);
+               return res;
+       }
+
+
+       if (num < 40) {  /* ocda... */
+               strncat(res, "20_ ", res_len - strlen(res) - 1);
+               return ast_translate_number_ge(num - 20, res, res_len);
+       }
+
+       if (num < 60) {  /* ormocda... */
+               strncat(res, "40_ ", res_len - strlen(res) - 1);
+               return ast_translate_number_ge(num - 40, res, res_len);
+       }
+
+       if (num < 80) {  /* samocda... */
+               strncat(res, "60_ ", res_len - strlen(res) - 1);
+               return ast_translate_number_ge(num - 60, res, res_len);
+       }
+
+       if (num < 100) {  /* otxmocda... */
+               strncat(res, "80_ ", res_len - strlen(res) - 1);
+               return ast_translate_number_ge(num - 80, res, res_len);
+       }
+
+
+       if (num < 1000) {  /*  as, oras, samas, ..., cxraas. asi, orasi, ..., cxraasi. */
+               remainder = num % 100;
+               digit = (num - remainder) / 100;
+
+               if (remainder == 0) {
+                       snprintf(buf, sizeof(buf), "%d", num);
+                       strncat(res, buf, res_len - strlen(res) - 1);
+                       return res;
+               } else {
+                       snprintf(buf, sizeof(buf), "%d_ ", digit*100);
+                       strncat(res, buf, res_len - strlen(res) - 1);
+                       return ast_translate_number_ge(remainder, res, res_len);
+               }
+       }
+
+
+       if (num == 1000) {
+               strncat(res, "1000", res_len - strlen(res) - 1);
+               return res;
+       }
+
+
+       if (num < 1000000) {
+               remainder = num % 1000;
+               digit = (num - remainder) / 1000;
+
+               if (remainder == 0) {
+                       ast_translate_number_ge(digit, res, res_len);
+                       strncat(res, " 1000", res_len - strlen(res) - 1);
+                       return res;
+               }
+
+               if (digit == 1) {
+                       strncat(res, "1000_ ", res_len - strlen(res) - 1);
+                       return ast_translate_number_ge(remainder, res, res_len);
+               }
+
+               ast_translate_number_ge(digit, res, res_len);
+               strncat(res, " 1000_ ", res_len - strlen(res) - 1);
+               return ast_translate_number_ge(remainder, res, res_len);
+
+       }
+
+
+       if (num == 1000000) {
+               strncat(res, "1 1000000", res_len - strlen(res) - 1);
+               return res;
+       }
+
+
+       if (num < 1000000000) {
+               remainder = num % 1000000;
+               digit = (num - remainder) / 1000000;
+
+               if (remainder == 0) {
+                       ast_translate_number_ge(digit, res, res_len);
+                       strncat(res, " 1000000", res_len - strlen(res) - 1);
+                       return res;
+               }
+
+               ast_translate_number_ge(digit, res, res_len);
+               strncat(res, " 1000000_ ", res_len - strlen(res) - 1);
+               return ast_translate_number_ge(remainder, res, res_len);
+
+       }
+
+
+       if (num == 1000000000) {
+               strncat(res, "1 1000000000", res_len - strlen(res) - 1);
+               return res;
+       }
+
+
+       if (num > 1000000000) {
+               remainder = num % 1000000000;
+               digit = (num - remainder) / 1000000000;
+
+               if (remainder == 0) {
+                       ast_translate_number_ge(digit, res, res_len);
+                       strncat(res, " 1000000000", res_len - strlen(res) - 1);
+                       return res;
+               }
+
+               ast_translate_number_ge(digit, res, res_len);
+               strncat(res, " 1000000000_ ", res_len - strlen(res) - 1);
+               return ast_translate_number_ge(remainder, res, res_len);
+
+       }
+
+       return res;
+
+}
+
+
+
+/*! \brief  ast_say_number_full_ge: Georgian syntax */
+static int ast_say_number_full_ge(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
+{
+       int res = 0;
+       char fn[512] = "";
+       char* s = 0;
+       const char* remainder = fn;
+
+       if (!num)
+               return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
+
+
+       ast_translate_number_ge(num, fn, 512);
+
+
+
+       while (res == 0 && (s = strstr(remainder, " "))) {
+               size_t len = s - remainder;
+               char* new_string = ast_malloc(len + 1 + strlen("digits/"));
+
+               sprintf(new_string, "digits/");
+               strncat(new_string, remainder, len);  /* we can't sprintf() it, it's not null-terminated. */
+/*             new_string[len + strlen("digits/")] = '\0'; */
+
+               if (!ast_streamfile(chan, new_string, language)) {
+                       if ((audiofd  > -1) && (ctrlfd > -1))
+                               res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+                       else
+                               res = ast_waitstream(chan, ints);
+               }
+               ast_stopstream(chan);
+
+               ast_free(new_string);
+
+               remainder = s + 1;  /* position just after the found space char. */
+               while(*remainder == ' ')  /* skip multiple spaces */
+                       remainder++;
+       }
+
+
+       /* the last chunk. */
+       if (res == 0 && *remainder) {
+
+               char* new_string = ast_malloc(strlen(remainder) + 1 + strlen("digits/"));
+               sprintf(new_string, "digits/%s", remainder);
+
+               if (!ast_streamfile(chan, new_string, language)) {
+                       if ((audiofd  > -1) && (ctrlfd > -1))
+                               res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+                       else
+                               res = ast_waitstream(chan, ints);
+               }
+               ast_stopstream(chan);
+
+               ast_free(new_string);
+
+       }
+
+
+       return res;
+
+}
+
+
+
+/*
+Georgian support for date/time requires the following files (*.gsm):
+
+mon-1, mon-2, ... (ianvari, tebervali, ...)
+day-1, day-2, ... (orshabati, samshabati, ...)
+saati_da
+tsuti
+tslis
+*/
+
+
+
+/* Georgian syntax. e.g. "oriatas xuti tslis 5 noemberi". */
+static int ast_say_date_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+       struct tm tm;
+       char fn[256];
+       int res = 0;
+       ast_localtime(&t,&tm,NULL);
+
+       if (!res)
+               res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
+
+       if (!res) {
+               snprintf(fn, sizeof(fn), "digits/tslis %d", tm.tm_wday);
+               res = ast_streamfile(chan, fn, lang);
+               if (!res)
+                       res = ast_waitstream(chan, ints);
+       }
+
+       if (!res) {
+               res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
+/*             if (!res)
+                       res = ast_waitstream(chan, ints);
+*/
+       }
+
+       if (!res) {
+               snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
+               res = ast_streamfile(chan, fn, lang);
+               if (!res)
+                       res = ast_waitstream(chan, ints);
+       }
+       return res;
+
+}
+
+
+
+
+
+/* Georgian syntax. e.g. "otxi saati da eqvsi tsuti" */
+static int ast_say_time_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+       struct tm tm;
+       int res = 0;
+
+       ast_localtime(&t, &tm, NULL);
+
+       res = ast_say_number(chan, tm.tm_hour, ints, lang, (char*)NULL);
+       if (!res) {
+               res = ast_streamfile(chan, "digits/saati_da", lang);
+               if (!res)
+                       res = ast_waitstream(chan, ints);
+       }
+
+       if (tm.tm_min) {
+               if (!res) {
+                       res = ast_say_number(chan, tm.tm_min, ints, lang, (char*)NULL);
+
+                       if (!res) {
+                               res = ast_streamfile(chan, "digits/tsuti", lang);
+                               if (!res)
+                                       res = ast_waitstream(chan, ints);
+                       }
+               }
+       }
+       return res;
+}
+
+
+
+/* Georgian syntax. Say date, then say time. */
+static int ast_say_datetime_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+       struct tm tm;
+       int res = 0;
+
+       ast_localtime(&t, &tm, NULL);
+       res = ast_say_date(chan, t, ints, lang);
+       if (!res)
+               ast_say_time(chan, t, ints, lang);
+       return res;
+
+}
+
+
+
+
+/* Georgian syntax */
+static int ast_say_datetime_from_now_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+       int res=0;
+       time_t nowt;
+       int daydiff;
+       struct tm tm;
+       struct tm now;
+       char fn[256];
+
+       time(&nowt);
+
+       ast_localtime(&t, &tm, NULL);
+       ast_localtime(&nowt, &now, NULL);
+       daydiff = now.tm_yday - tm.tm_yday;
+       if ((daydiff < 0) || (daydiff > 6)) {
+               /* Day of month and month */
+               if (!res)
+                       res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
+               if (!res) {
+                       snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
+                       res = ast_streamfile(chan, fn, lang);
+                       if (!res)
+                               res = ast_waitstream(chan, ints);
+               }
+
+       } else if (daydiff) {
+               /* Just what day of the week */
+               if (!res) {
+                       snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
+                       res = ast_streamfile(chan, fn, lang);
+                       if (!res)
+                               res = ast_waitstream(chan, ints);
+               }
+       } /* Otherwise, it was today */
+       if (!res)
+               res = ast_say_time(chan, t, ints, lang);
+
+       return res;
+}
+
+
+
 /*
  * remap the 'say' functions to use those in this file
  */