As you can see, i18n seems to try to decode passed unicode strings with the ascii codec, while encoding the returned tring with utf-8. In python 2, apparently if the trying fails, the unicode object gets passed to something expecting bytes, while in python 3, the failing to encode with ascii already produces an Exception.
This way, regardless of python version, passing bytes objects that contain any utf-8 work, while unicode-containing strings that you didn’t manually encode to utf-8 byte strings don’t.
PS: The next best things to a documentation for it is this and of course the code.