say.conf

Захотелось мне чтобы суммы, даты и прочее на рідній мові проговаривались правильно, а то корявое звучание в контакт центрах меня просто убивает. Навести порядок в проговаривании нам поможет новая реализация работы говорилки(правка say.conf).
Для начала определимся с падежами
ССЫЛКА
Собственно то что нам нужно

 
uk	Ukrainian	nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);

Для применения новых правил достаточно подправить say.conf и единожды сделать

say load new

Увидим сообщение что у нас все получилось. ну и теперь наша говорилка работает именно так как мы это зададим в самом файле say.conf
Синтаксис файла достаточно прост:

в секции [general]
mode=new  
new -проговариваем на основании этого файла
old - используя функции playback заложенные разработчиками. 

!!!Для применения изменений в say.conf нужно перезагружать ПЛЕЙБЕК!!!
module reload app_playback.so

Формат говорилки таков: prefix:[format:]data

data, как правило, строка, заданная (либо числом, ASCII строка или дата/время в формате, указанном ниже), data доступна в правой части правила, как переменная ${SAY}.

format дополнительный аргумент и обычно используется только для даты и времени.
prefix используется для выбора стандарта произношения
Префиксы по умолчанию
num для чисел
enum для перечисления
date для даты
time для времени
datetime для даты и времени
char для строки символов
phonetic для фонетических строк
digit для числовых строк

Также можно создавать свои префиксы, что будет показано далее

ВАЖНО!! X Z N спец символ который нужно экранировать! [X] [N] [Z]

Правила обработки:
Если поле format пустое, или формат отсутствует, вся строка сравнивается с шаблоном в левой части
При первом совпадении, компоненты разделенные запятой из правой части произносятся по шаблону:
+ Компоненты с : повторно обрабатываются согласно правил
+ Компоненты без ‘:’ воспроизводятся как обычные файлы

Если поле format не пустое ,format разделяет фразу на части (отдельные символы, или имена файлов в одинарных кавычках), и потом файлы воспроизводятся, в то время как отдельные символы используются для генерации новых строк format:pat:data для обработки.

Даты/и Время подразумеваем что дата доступна в следующем формате YYYMMDDHHmm.ss-dow-doy
4 -год
2 — месяц,
2 — день,
2 — час
2 — минуты,
2 — секунды,
1 — день недели (dow)day-of-week,
3 — день года(doy) day-of-year.
Пример:
datetime::200604172030.00-4-102
datetime::. => date:AdBY ‘digits/at’ IMp:${SAY}
Формат проговора даты по умолчанию

Вот пример того что у меня получилось для Української мови:

[ua-base](!) 
    _[n]um:0 => num:${SAY} 
    _[n]um:0f => digits/${SAY:0:1} 
    _[n]um:0. => num:${SAY:1} 
    _[n]um:X  => digits/${SAY} 
    _[n]um:1f  => digits/odna 
    _[n]um:2f  => digits/dvi 
    _[n]um:Xf  => num:${SAY:0:1}
;     Tens 
    _[n]um:1Xf  => num:${SAY:0:2}
    _[n]um:1X   => digits/${SAY} 
    _[n]um:[2-9]0     => digits/${SAY} 
    _[n]um:[2-9]0f     => digits/${SAY:0:2} 
    _[n]um:[2-9][1-9] => digits/${SAY:0:1}0, num:${SAY:1} 
    _[n]um:[2-9][1-9]f => digits/${SAY:0:1}0, num:${SAY:1}
        ; Hundreds 
    _[n]um:[1-9]00    => digits/${SAY} 
    _[n]um:[1-9]00f    => num:${SAY} 
    _[n]um:XXX        => num:${SAY:0:1}00, num:${SAY:1} 
    _[n]um:XXXf        => num:${SAY:0:1}00, num:${SAY:1}
    ; Thousands 
    _[n]um:1XXX       => num:${SAY:0:1}, digits/thousand, num:${SAY:1} 
    _[n]um:[2-4]XXX   => num:${SAY:0:1}, digits/thousands-i, num:${SAY:1} 
    _[n]um:[5-9]XXX   => num:${SAY:0:1}, digits/thousands, num:${SAY:1} 
    _[n]um:X1XXX      => num:${SAY:0:2}, digits/thousand, num:${SAY:2} 
    _[n]um:X[2-4]XXX  => num:${SAY:0:2}, digits/thousands-i, num:${SAY:2} 
    _[n]um:X[5-9]XXX  => num:${SAY:0:2}, digits/thousands, num:${SAY:2} 
    _[n]um:XX1XXX     => num:${SAY:0:3}, digits/thousand, num:${SAY:3} 
    _[n]um:XX[2-4]XXX => num:${SAY:0:3}, digits/thousands-i, num:${SAY:3} 
    _[n]um:XX[5-9]XXX => num:${SAY:0:3}, digits/thousands, num:${SAY:3} 
    ; Millions 
    _[n]um:1XXXXXX        => num:${SAY:0:1}, digits/million, num:${SAY:1} 
    _[n]um:[2-4]XXXXXX    => num:${SAY:0:1}, digits/millions-i, num:${SAY:1} 
    _[n]um:[5-9]XXXXXX    => num:${SAY:0:1}, digits/millions, num:${SAY:1} 
    _[n]um:X1XXXXXX       => num:${SAY:0:2}, digits/million, num:${SAY:2} 
    _[n]um:X[2-4]XXXXXX   => num:${SAY:0:2}, digits/millions-i, num:${SAY:2} 
    _[n]um:X[5-9]XXXXXX   => num:${SAY:0:2}, digits/millions, num:${SAY:2} 
    _[n]um:XX1XXXXXX      => num:${SAY:0:3}, digits/million, num:${SAY:3} 
    _[n]um:XX[2-4]XXXXXX  => num:${SAY:0:3}, digits/millions-i, num:${SAY:3} 
    _[n]um:XX[5-9]XXXXXX  => num:${SAY:0:3}, digits/millions, num:${SAY:3} 
    ; Billions 
    _[n]um:1XXXXXXXXX     => num:${SAY:0:1}, digits/billion, num:${SAY:1} 
    _[n]um:[2-4]XXXXXXXXX => num:${SAY:0:1}, digits/billions-i, num:${SAY:1} 
    _[n]um:[5-9]XXXXXXXXX => num:${SAY:0:1}, digits/billions, num:${SAY:1} 
    _[n]um:X1XXXXXXXXX    => num:${SAY:0:2}, digits/billion, num:${SAY:2} 
    _[n]um:X[2-4]XXXXXXXXX => num:${SAY:0:2}, digits/billions-i, num:${SAY:2} 
    _[n]um:X[5-9]XXXXXXXXX => num:${SAY:0:2}, digits/billions, num:${SAY:2} 
    _[n]um:XX1XXXXXXXXX    => num:${SAY:0:3}, digits/billion, num:${SAY:3} 
    _[n]um:XX[2-4]XXXXXXXXX => num:${SAY:0:3}, digits/billions-i, num:${SAY:3} 
    _[n]um:XX[5-9]XXXXXXXXX => num:${SAY:0:3}, digits/billions, num:${SAY:3} 

    ; enumeration 
    _e[n]um:X[mfn] => digits/h-${SAY} 
    _e[n]um:1X[mfn] => digits/h-${SAY} 
    _e[n]um:[2-9]0[mfn] => digits/h-${SAY} 
    _e[n]um:[2-9][1-9][mfn] => num:${SAY:0:1}0, digits/h-${SAY:1} 
    _e[n]um:[1-9]XX[mfn] => num:${SAY:0:1}, digits/hundred, enum:${SAY:1} 

[ua](ua-base,digit-base) 

;CHAS
    _godu[n]:0 => num:${SAY}, digits/godun 
    _godu[n]:1 => digits/odna, digits/goduna 
    _godu[n]:2 => digits/dvi, digits/godunu 
    _godu[n]:[3-4] => num:${SAY}, digits/godunu 
    _godu[n]:[5-9] => num:${SAY}, digits/godun 
    _godu[n]:0X => godun:${SAY:1} 
    _godu[n]:1X => num:${SAY}, digits/godun 
    _godu[n]:20 => num:${SAY}, digits/godun 
    _godu[n]:2[1-4] => num:${SAY:0:1}0, godun:${SAY:1} 
    _hvulu[n]:0 => num:${SAY}, digits/hvulun 
    _hvulu[n]:1 => digits/odna, digits/hvuluna 
    _hvulu[n]:2 => digits/dvi, digits/hvulunu
    _hvulu[n]:[3-4] =>  num:${SAY}, digits/hvulunu 
    _hvulu[n]:[5-9] => num:${SAY}, digits/hvulun 
    _hvulu[n]:0X  => hvulun:${SAY:1} 
    _hvulu[n]:1X  => num:${SAY}, digits/hvulun 
    _hvulu[n]:[2-5]0 => num:${SAY}, digits/hvulun 
    _hvulu[n]:[2-5][1-9] => num:${SAY:0:1}0, hvulun:${SAY:1} 
    _seku[n]d:0 =>  num:${SAY}, digits/secund 
    _seku[n]d:1 => digits/odna, digits/secunda 
    _seku[n]d:2 => digits/dvi, digits/secundu
    _seku[n]d:[3-4] => num:${SAY}, digits/secundu 
    _seku[n]d:[5-9] => num:${SAY}, digits/secund 
    _seku[n]d:0X => sekund:${SAY:1} 
    _seku[n]d:1X => num:${SAY}, digits/secund 
    _seku[n]d:[2-5]0 => num:${SAY}, digits/secund 
    _seku[n]d:[2-5][1-9] => num:${SAY:0:1}0, sekund:${SAY:1} 

;zagalnij chas
    _date:[hH]:. => godun:${SAY:8:2}              ; hour 
    _date:[M]:. => hvulun:${SAY:10:2}             ; minute 
    _date:[S]:. => sekund:${SAY:13:2}             ; seconds 
    _datetime::. =>  date:AdBY HMS:${SAY} 

;GROSHI

_gr[n]:. => num:${SAY}f, digits/grn${IF($[$[$[${SAY}%10]=1] & $[$[${SAY}%100]!=11]]?1:${IF($[$[$[$[${SAY}%10]>=2] & $[$[${SAY}%10]<=4]] & $[$[$[${SAY}%100]<10] | $[$[${SAY}%100]>=20]]]?2:5)})} 
_kop:. => num:${SAY}f, digits/kop${IF($[$[$[${SAY}%10]=1] & $[$[${SAY}%100]!=11]]?1:${IF($[$[$[$[${SAY}%10]>=2] & $[$[${SAY}%10]<=4]] & $[$[$[${SAY}%100]<10] | $[$[${SAY}%100]>=20]]]?2:5)})} 

Особенности названия файлов:
grn1 гривня
grn2 гривні
grn5 гривень

kop1 копійка
kop2 копійки
kop5 копійок
Использование:
Playback(grn:21|say) — двадцять однa гривня
Playback(kop:21|say) — двадцять одна копійка

Обратите внимание что файлики вы должны сами наговаривать!
Желаю успешных локализаций)

Заметили ошибку, напишите пожалуйста! Спасибо.

Комментарии: