Russian Plurals
Globalization is hard.
Some tasks — like decimal separators, date and time formats, right to left layouts, and more — are now in 2010 are managed pretty OK by the well-known libraries such as Win32 API, or Windows Forms.
I don’t know what do the open source-inclined individuals use for that purpose — maybe the ICU? Don’t care.
Today I was installing Skype messenger. I did that on my friend’s laptop — he asked me to reinstall Windows and install some software, including Skype.
While installing, it outputs the estimated time. It says “remaining time is about 10 seconds”, then “remaining time is about 8 seconds”, hope you’ve got the point.
My friend asked me to install Russian versions of the software. So I saw Russian text in the Skype installer. It said “осталось примерно 10 секунд” (=remaining time is about 10 seconds), then eventually “осталось примерно 2 секунд” (=remaining time is about 2 seconds).
The problem is, Russian language has three distinct plural forms for the language constructions like “2 seconds”, and Skype installer only uses one of them. For a Russian like me, it sounds as weird as e.g. “3 second” or “1 seconds” for an English speaker.
Here’s the link with more information about that aspect of Russian language.
What’s The Solution?
When I developed the software with Russian UI, I invented my own one.
Here’s the copy-paste of my C# source code that calculates which form to use for an integer:
/// return 0 if Russian plural = single ( numbers ending in 1, but not 11 )
/// return 1 for "-a" or "-i" form ( number ending in 2, 3 or 4 but not 12, 13 or 14 )
/// return 2 for "-ov" or "-ey" form ( numbers ending in 5, 6, 7, 8, 9, 0, or from 11 to 14 )</summary>
/// <param name="i">The number following the plural.</param>
/// <seealso cref="http://www.russianlessons.net/lessons/lesson11_main.php"/>
static int RussianPlural( int i )
{
if( i < 0 ) i = -i;
int d1 = ( i % 10 );
int d2 = ( ( ( i - d1 ) / 10) % 10 );
if( 1 == d1 && d2 != 1 ) return 0;
if( d1 >= 2 && d1 <= 4 && d2 != 1 ) return 1;
return 2;
}
And then in the same class there’re several functions like the following ones:
/// <summary>Get Russian plural for "symbols"</summary>
/// <param name="n">How many of them</param>
public static string rusSymbolsNoun( int n ){ return s_strSymbols[ RussianPlural( n ) ]; }
static readonly string[] s_strMessages = new string[ 3 ] { "сообщение", "сообщения", "сообщений" };
/// <summary>Get Russian plural for "messages"</summary>
/// <param name="n">How many of them</param>
public static string rusMessagesNoun( int n ) { return s_strMessages[ RussianPlural( n ) ]; }
static readonly string[] s_strDollars = new string[ 3 ] { "доллар", "доллара", "долларов" };
/// <summary>Get Russian plural for "dollars"</summary>
/// <param name="n">How many of them</param>
public static string rusDollarsNoun( int n ) { return s_strDollars[ RussianPlural( n ) ]; }
No Silver Bullet
As you probably see, my solution only works for Russian language.
Let me repeat: globalization is hard. Get used to it.
Besides several plural forms, there’re also many other aspects of software globalization, that are not (yet?) covered by Microsoft’s libraries. Here're some of them:
- In English you say “on Sunday, on Monday”, etc. In Russian language, the “on” part is translated as “в” for any day of the week but Tuesday, and on Tuesdays it becomes “во” instead.
- Different units of measure.
- Muslims don’t like icons containing any part of a human body.
- Chinese hieroglyphs contain too many strokes; that’s why the default Windows font size is 1.5 times larger.
- French keyboards are not QWERTY, they are AZERTY instead.
- And many more.
You might ask, is there any way to prevent the problems?
I'm afraid there's the only way. Plan your QA carefully.
If you’re localizing the software into the language you don't speak, either have your translator to also chech your product for localization mistakes, or find a tester who speaks the localization language.
Obviously, Skype project team didn't do that.