Safari, AJAX and "broken" encodings
Some lessons are learned the hard way.
I was doing another AJAX based system today, and faced a problem where the Ajax.Updater updated text was shown correctly in every single browser except for Safari.
Like I wrote in one of my previous posts, one should check if the output to browser from a script is sent in UTF-8, because this is the encoding AJAX supports. So, in my case with Japanese-language web-sites, I have ordinary pages encodings set to ShiftJIS. So, when I output text which is supposed to be used to replace web-page contents using Prorotype's Ajax.Update call, I convert it from ShiftJIS to UTF-8 before outputting as the result of AJAX call.
And the code might look like that:
ob_start(); //starting output buffer
print_eventsList("month", $_REQUEST["y"], $_REQUEST["m"]); //outputting everything to output buffer
print "some additional output functions might be here";
$out = ob_get_clean(); //getting results of the output buffer
print mb_convert_encoding($out, "UTF-8", "SJIS"); //converting output from server's default encoding to UTF-8 and outputting it as the result of AJAX call
So, the problem was that the code above worked in Firefox, Camino, IE 6.0 on Windows, but was rendered incorrectly on Safari. The encoding was kind of "broken". Tried lots of thing before finally found the solution (and it works on every browser!). It looks like all browsers except for Safari have the XMLHTTPRequest encoding set to UTF-8 by default. And Safari.. I don't know if it has any defaults at all. So I decided to set the encoding of the AJAX output result in the header of the output - AND IT WORKED!
Just one line of code has to be added:
header("Content-type:text/html; charset=utf-8");
and the final code:
ob_start();
print_eventsList("month", $_REQUEST["y"], $_REQUEST["m"]);
print "some additional output functions might be here";
$out = ob_get_clean();
header("Content-type:text/html; charset=utf-8");
print mb_convert_encoding($out, "UTF-8", "SJIS");
So.. good luck in making AJAX calls and happy coding ;)
UPDATE!
Actually, all you need is to send header with your server's default encoding. So if all pages on your server are generated in ShiftJIS encoding, just add the following header
header("Content-type:text/html; charset=shift_jis");
July 26th, 2006 at 8:48 pm
great. thanks.
still i got a problem: all my ajax-loaded pages are displayed correctly by Safari now. But sending them doesn't work: One page contains a form which i sent to the server by XMLHTTPRequest: the values of that form though do not seem to arrive in UTF-8. It works with all known Browsers but with Safari. Do you know a workaround?
July 26th, 2006 at 9:57 pm
i didn't try to send much stuff using AJAX in Safari, but my first guess would be to check what kind of data Safari sends to the script. It could be that it sends data in page's default encoding which might not be UTF-8 for example. If you have a link to a test page it would be interesting to look at it and may be I can help.
One more thing - it looks like Safari conforms to standards to a better degree than other browsers, so it might be that the code misses some required part which other browsers just forgive. But.. I'm afraid I can't say more that that right now. May be if I have time I'll try the thing myself and see how it works in Safari.
August 1st, 2006 at 11:01 pm
I think I have a simular problem. Within Safari everything looks fine as all dashes are dashes and all pound signs are pound sign. Though within IE dashes and pound signs are shown as hashes. From what I have read above this is because of how the data is encoded when being passed too and from AJAX coding. Can anyone confirm that this could be the case. Thanks.
August 1st, 2006 at 11:04 pm
Sorry I meant "?" not hashes.
October 14th, 2006 at 5:44 am
My turn to add an other trick about SAFARI/HTTPREQUEST and charset.
I learned from you that I need to specify the charset by rewriting the header information. This does the trick until I needed to make synchronous requests.
It appears that using httprequest with the third argument as false (i.e. synchronously) makes UTF-8 unreadable by SAFARI…
I can't understand why ?
This is driving me made…
Paul
November 18th, 2006 at 3:11 am
Wuaaaaaaa. thank youuu. I lovee youuu mikee!! I fixing the AJAX with shift-jis bug 3 hours. And the only mistake i made was i type shift-JIS in the content-type. Ohhhh nooo T_T it should be shift_JIS
ThAnK Y0U!
November 18th, 2006 at 10:07 am
you're welcome Rickyok :)
March 4th, 2007 at 6:35 pm
Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! A million times over!
March 7th, 2007 at 4:27 pm
i am using asp .. i m not sure whether i using the write way to set the charset onot and it doesn't work in Safari .. not sure where is the mistake ..
March 19th, 2007 at 4:32 pm
This is driving me crazy too. I'm not using ASP either. I seem to be sending the correct content-type from my server though:
addResponseHttp( "Content-Type:text/html; charset=shift_jis" )'
but the Japanese that comes back from my AJAX/Prototype calls seem garbled.
doug
June 11th, 2007 at 8:50 pm
Finally solved my problem. Turned out that Safari is not switching to UTF-8 on a text/json response. I have charset set to utf-8 inside the html and in all http response headers (both for html and the json). And now my unicode characters are not displayed properly in Safari. What the heck, it even works in IE6 but not in Safari :)
Turned out that I'm missing the charset attribite in the tag. I'm using ScriptSrcIO as a transport mechanism.
July 19th, 2007 at 8:18 pm
After having pretty much the same problem as you, with a Japanese AJAX call, I Google'd "safari ajax utf8" and your post popped up as the first result - fabulous!! Thanks for your write-up.
November 8th, 2007 at 7:20 pm
I had the same problem.
I had "AddDefaultCharset UTF-8" in my .htaccess file to automatically add a UTF charset header to all server responses.
Safari was working fine with the data when shown using a straightforward PHP/MySQL page. When I showed it using AJAX, the encoding cracked open in only Safari.
It seems Apache's charset header didn't count when it came to Safari. Setting it manually in the back-end PHP script for my AJAX request solved the problem. Just like you said.
Thank you!