Software internationalization is difficult under the best of circumstances, but it always amazed me how often one particular country came up in discussions of internationalization problems: Turkey.
I've been tracking a really funky bug in my West Wind Web Store application that seems to crop up only very infrequently in my error logs. In a previous post I mentioned that I had instituted some additional logging features – specifically making sure that I would also log the locale of the user accessing the application.
Well, three bug reports later I noticed that all errors occurred with a Turkish (tr) browser. So I changed my browser's default language to Turkish and sure enough I could see the error occur.
I had blogged earlier about a bug in dasBlog that affected Turkish users. When a Turkish browser reported an HTTP Accept-Language header indicating Turkish as the preferred language, no blog posts would show up. As fix, I suggested that users change their blog templates, but I knew that wasn't an appropriate fix.
I understand that Turkish prisons are not to be trifled with, but the question remains: why do Turkish people take such cruel and perverse delight in breaking our fine software? What's wrong with Turkey?
As with so many other problems in software development, the question shouldn't be what's wrong with Turkey, but rather, what the hell is wrong with software developers? Some of this is sort of obvious if you have any cultural awareness whatsoever.
In the United States, we would typically format today's date as 3/14/2008. In Turkey, they format it as 14.3.2008.
In the United States, we use commas to group digits, like so: 32,768. In Turkey, they group digits using a period, so the same number would be entered as 32.768.
These minor formatting differences are usually not a big deal for output and display purposes, but it's a whole different ballgame when you're parsing input. You'd naturally expect people to input dates and numbers in the format they're used to. If your code assumes that input will be in typical American English format, there will be.. trouble.
Most languages have this covered; there are functions that allow you to read or write dates and numbers appropriately for various cultures. In .NET, for example, it's the difference between these two calls:
Because no culture is specified, the first call will parse the number according to the rules of the default culture that code is running under. Let's hope it's running under a Turkish version of Windows, so it can parse the number correctly. The second call, however, explicitly specifies a culture. The "invariant" culture is every American programmer's secret dream realized: we merely close our eyes and wish away all those confusing languages and cultures and their crazy, bug-inducing date and number formatting schemes in favor of our own. A nice enough dream while it lasts, but instead of rudely asking your users to "speak American" through the invariant culture, you could politely ask them to enter data in ISO international standard format instead.
Anyway, point being, this kind of culture support is baked into most modern programming languages, so all you need to do is make sure your developers are aware of it-- and more importantly, that they're thinking about situations when they might need to use it.
But all that date and time formatting stuff is easy. Or about as easy as i18n ever gets, anyway. Strings are where it really starts to get hairy. Guess where this code fails?
switch (myType.ToLower())
{
case "integer" : ;
}
If you guessed Turkey, you're wrong! Just kidding. Of course it fails in Turkey. When we convert the string "integer" to upper and lower case in the Turkish locale, we get some strange characters back:
It's sort of hard to see the subtle differences here unless we ratchet up the font size:
I → lowercase → ı
i → uppercase → İ
There's obviously no way these strings are going to match "integer" or "INTEGER" respectively. This is known as the Turkish I problem, and the solution should feel awfully familiar by now:
That will produce the expected output, or at least, the output that matches the comparison in the original code snippet.
This is, of course, only the tip of the iceberg when it comes to internationalization. We haven't even touched on the truly difficult locales like Hebrew and Arabic. But I do agree with Jeff Moser-- if your code can pass the Turkey test, you're doing quite well. Certainly better than most.
If you care a whit about localization or internationalization, force your code to run under the Turkish locale as soon as reasonably possible. It's a strong bellwether for your code running in most-- but by no means all-- cultures and locales.
======================================================================== 같은 소스를 컴파일해도 터키에서는 돌아가지 않는단다. 언어의 문화적 차이 때문이다. 소수점을 마침표(.)와 쉼표(,)로 구분하는 차이, ToLower, ToUpper등 언어의 인식 차이(미쿡에서는 ToUpper를 소문자에서 대문자로 바꾸는 것으로 인식하지만 터키에서는 글자의 크기를 크게 만드는 것으로 인식한다.) 같은 코드를 컴파일하면 에러가 발생하는데 그나마도 브라우저를 터키어로 맞추지 않으면 볼 수 없단다. .NET에서는 그러한 문화적 차이를 표시해주는 코드가 포함되어 있는데 'Invariant'가 그것이란다.
한국도 마찬가지다. 많은 한국인들이 다분히 미쿡을 동경하지만 언어에 있어서는 한국어를 사랑한다. 일상생활에서 영어를 능숙하게 말하고 다니면 '어머 웬 잘난척? 즈질이야~'정도의 말을 듣는다.(나도 그런말 들어보고 싶다.) 한국어를 좋아하고 주로 사용하는 것은 좋은 현상이다. 그런데 상황에 맞게 사용해야 한다. 프로그래밍을 할 때 시간표시나 숫자표시등이 일치되지 않는 부분이 꽤 있다. 시간표현은 표현방식이 아주 다양하다. 24시표현, AM/PM, 오전/오후 시:분, 시/분, 시-분, 시 분 이렇게 다양한 표현을 모두 한국 문화에서 사용한다. 숫자표현은 어떤가? 그냥 숫자를 바로 사용하기도 한다. 그건 세계 공통이다. 하지만 숫자의 자릿수를 좀 더 명확히 하기위해 ,로 세자리 단위씩 끊어서 표현한다. 그리고 읽을 땐 4자리 단위로 읽는다. 한국에서 사용하는 숫자의 단위는 4단위다. 일, 만, 억, 조, 경, 해... 그런데 숫자는 3단위다. 미쿡에서는 숫자의 단위가 3단위다. 어렸을 적 새로운 단위가 제대로 정착되는데 혼란이 없다면 표기단위를 4단위로 하는 것이 좋을 것이라고 생각했었다.
글에서 문화적 차이를 뛰어넘으려면 ISO표준을 따르라고 권하고 있다.
물론 국제표준을 따르는 것이 가장 좋다. 그리고 그렇게 하지 못할 땐 입장을 확실하게 해야 한다. 무슨 말이냐면 한국식으로 하고싶으면 해당 scope내에서는 확실히 한국식으로 하고, 미쿡식으로 하고싶으면 확실히 미쿡식으로 하고 ISO대로 하고싶으면(ISO표준이 미쿡식은 아니다) ISO에 맞추어서 하란 말이다. 가끔 실무에서도 변수 이름으로 한국어발음을 억지로 영어로 적어놓은 경우를 자주 볼 수 있다. (실제 이런 이름을 쓰진 않겠지만 굳이 예를 든다면 show, view, print등의 내용을 bogi(보기)와 같이 억지로 쓰는 경우가 있다.)
상대가 정 모르면 사전을 찾아서라도 알 수 있으면 그건 괜찮다. 자신이 있지도 않은 단어를 만들어버리는 도대체 어떻게 알아보란 거야? 이도 저도 아닌 어중간한 지점에서 타협하지 마라!!