本家 master にログ出力を追加して確認した:
今日の日付 テキスト 11月22日
IO - speech.speak (13:48:54): Speaking [LangChangeCommand ('ja_JP'), u'\u4eca\u65e5\u306e\u65e5\u4ed8 \u30c6\u30ad\u30b9\u30c8 \u200e11\u200e\u6708\u200e22\u200e\u65e5\r\n'] IO - speech.speak (13:48:54): Speaking [LangChangeCommand ('ja_JP'), u'\u4eca\u65e5\u306e\u65e5\u4ed8 \u30c6\u30ad\u30b9\u30c8 11 \u6708 22 \u65e5 ']
speech.py の processText が \u200e を削って空白を入れて、それから音声エンジンに渡されている。
Unicode 制御文字の処理として検討するか、数字と単位のあいだに空白が入る場合の処理として対処するか、 もしかすると後者として考えた方がよいかも知れない。
Windows 8.1 のチャームを読み上げると、音声エンジンにかかわらず 「じゅういち、ひ、にじゅうに、つき」 のように区切られて読み上げられる。
調べてみると「11月22日」のような文字列だが、数字の前後に 0x200e (Unicode left-to-right mark) が入っている。
JTalk は音声エンジンで work around しているはずだが効いていないので、 もしかすると NVDA 側の前処理ですでに区切られているのかも知れない。