Translating financial values
I wonder if anyone can help. I speak absolutely no Russian and I'm working on localising some software for a Russian company (witht he help of a translator). One of the requirements they have is for invoices to be produced with a "narrative" financial value, so for instance
150.89
would be printed as
ONE HUNDRED AND FIFTY ROUBLES (EIGHTY NINE KOPECKS)
I have access to a translator who will do the translation of the various words:
ONE, TWO, THREE, HUNDRED, MILLION etc.
But it appears that the Russian language has different words for plurals etc. depending on the value. Can anyone explain the logic behind the numbering system?
For instance, I could write
ONE ROUBLE (no plural)
TWO (2-4)ROUBLES -a plural for a quantity of 2 to 4
THREE (2-4)ROUBLES
FOUR (2-4)ROUBLES
FIVE ROUBLES -a normal plural?
I'm really sorry if this doesn't make sense! The translator I'm working with is also finding it really hard to understand what I want, and can't explain to me why the values my program generates aren't right!!
Re: Translating financial values
рубль (rouble) is of masculine gender
копейка (copeck) is of feminine gender
тысяча (thousand) - feminine
миллион, миллиард... etc (million, billion... etc) - masculine
first comes the masculine form then the feminine:
1 один (рубль, миллион) / одна (копейка, тысяча)
2-4 (рубля) / (копейки / тысячи)
5-20 (рублей) / (копеек / тысяч)
21-24 (рубля) / (копейки / тысячи)
25-30 (рублей) / (копеек / тысяч)
31-34 (рубля) / (копейки / тысячи)
...
100 рублей / (копеек / тысяч)
101, 102... the same as 1, 2 etc.
1000 - одна тысяча рублей
Well, even the localized code wouldn't work correctly. The algorithms are simply too different.
There are many working solutions, however, but their realization and support are offered in Russian only.
You can google for 'сумма прописью алгоритм', but all links would be in Russian.
I wish I could help you more but I cannot imagine how a localization can be done without knowledge of the language you're localizing into.
P.S. I have a solution for MS Excel VBA for Russian. PM me if you need further information.
Re: Translating financial values
what I'm trying to do is come up with an algorithm for assembling a set of English "tokens"... so although there might not be an English word that is directly equivalent, I would build a string of tokens, that could then be translated. Reading the tokens in English would be a nonsense, but hopefully they would directly translate to something sensible in Russian.
so to really simplify what I did for 1, 2, 3, 4, 5 roubles, what I have done is:
ONE ROUBLE_TOKEN_1
TWO ROUBLE_TOKEN_2
THREE ROUBLE_TOKEN_2
FOUR ROUBLE_TOKEN_2
FIVE ROUBLE_TOKEN_3
Where ONE, TWO, THREE, FOUR, FIVE directly translate to Russian
and ROUBLE_TOKEN_1, ROUBLE_TOKEN_2 and ROUBLE_TOKEN_3 translate to the appropriate Russian words.
I basically need to understand how I construct a set of tokens/words that can be translated to the correct words.
I think I may need to refer this to a programmer who has some Russian language skills, as I'm really struggling with the masculine/feminine aspect!!
Again, sorry if this all sounds stupid, I think I'm way out of my depth here!
Re: Translating financial values
To explain more... what I've done is generated every number from 1 - 1000 using the technique I described in my previous post.
For some reason, the logic I've used has resulted in the following errors:
Value Incorrect Narrative Correct form
100.00 ОДИН СТО Рублей СТО Рублей
200.00 ДВА СТО Рублей ДВЕСТИ РУБЛЕЙ
300.00 ТРИ СТО Рублей ТРИСТА РУБЛЕЙ
400.00 ЧЕТЫРЕ СТО Рублей ЧЕТЫРЕСТА РУБЛЕЙ
500.00 ПЯТЬ СТО Рублей ПЯТЬСОТ Рублей
600.00 ШЕСТЬ СТО Рублей ШЕСТЬСОТ РУБЛЕЙ
700.00 СЕМЬ СТО Рублей СЕМЬСОТ РУБЛЕЙ
800.00 ВОСЕМЬ СТО Рублей ВОСЕМЬСОТ РУБЛЕЙ
900.00 ДЕВЯТЬ СТО Рублей ДЕВЯТЬСОТ РУБЛЕЙ
I don't understand the rule that I'm, missing that has caused this error.
Re: Translating financial values
Why not use a solution that already exists? (there are many free code examples. of course the comments to the code are in Russian which complicates your problem a bit).
What programming language do you use? C++? C#? Java?
Re: Translating financial values
Aha! and now we arrive at the crux of the problem!
I'm using a proprietary programming language, and this is the first time it has been used to provide a solution to a customer who speaks Russian!
I'll have a look for a C# version and see if I can figure out what it's doing.
Thanks for your help though!
Re: Translating financial values
I don't suppose you could give me a phrase I could google to get such a code snippet!?
I find it hard to even describe what I'm doing in English...
Re: Translating financial values
The simplest solution was found tens years before the first computer was invented. They just use reduction "руб." & "коп."
Re: Translating financial values
No they need 'сумма прописью'
Here's an example. You'll need to work with it a bit.
Add 'рублей' if the figure ends with 5,6,7,8,9,0 or 11-19.
Add 'рубля' if the figure ends with 1-4 except 11-14
Taken from here:
http://www.sysman.ru/index.php?showtopic=4339
Code:
// A set of C# classes for spelling Russian numerics
// Copyright (c) 2002 RSDN Group
using System;
using System.Text;
using System.Xml;
using System.Configuration;
using System.Collections.Specialized;
namespace RSDN
{
public class RusNumber
{
private static string[] hunds =
{
"", "сто ", "двести ", "триста ", "четыреста ",
"пятьсот ", "шестьсот ", "семьсот ", "восемьсот ", "девятьсот "
};
private static string[] tens =
{
"", "десять ", "двадцать ", "тридцать ", "сорок ", "пятьдесят ",
"шестьдесят ", "семьдесят ", "восемьдесят ", "девяносто "
};
public static string Str(int val, bool male, string one, string two, string five)
{
string[] frac20 =
{
"", "один ", "два ", "три ", "четыре ", "пять ", "шесть ",
"семь ", "восемь ", "девять ", "десять ", "одиннадцать ",
"двенадцать ", "тринадцать ", "четырнадцать ", "пятнадцать ",
"шестнадцать ", "семнадцать ", "восемнадцать ", "девятнадцать "
};
int num = val % 1000;
if(0 == num) return "";
if(num < 0) throw new ArgumentOutOfRangeException("val", "Параметр не может быть отрицательным");
if(!male)
{
frac20[1] = "одна ";
frac20[2] = "две ";
}
StringBuilder r = new StringBuilder(hunds[num / 100]);
if(num % 100 < 20)
{
r.Append(frac20[num % 100]);
}
else
{
r.Append(tens[num % 100 / 10]);
r.Append(frac20[num % 10]);
}
r.Append(Case(num, one, two, five));
if(r.Length != 0) r.Append(" ");
return r.ToString();
}
public static string Case(int val, string one, string two, string five)
{
int t=(val % 100 > 20) ? val % 10 : val % 20;
switch (t)
{
case 1: return one;
case 2: case 3: case 4: return two;
default: return five;
}
}
};
struct CurrencyInfo
{
public bool male;
public string seniorOne, seniorTwo, seniorFive;
public string juniorOne, juniorTwo, juniorFive;
};
public class RusCurrencySectionHandler:IConfigurationSectionHandler
{
public object Create( object parent, object configContext, XmlNode section )
{
foreach(XmlNode curr in section.ChildNodes)
{
if(curr.Name=="currency")
{
XmlNode senior=curr["senior"];
XmlNode junior=curr["junior"];
RusCurrency.Register(
curr.Attributes["code"].InnerText,
(curr.Attributes["male"].InnerText == "1"),
senior.Attributes["one"].InnerText,
senior.Attributes["two"].InnerText,
senior.Attributes["five"].InnerText,
junior.Attributes["one"].InnerText,
junior.Attributes["two"].InnerText,
junior.Attributes["five"].InnerText);
}
}
return null;
}
};
public class RusCurrency
{
private static HybridDictionary currencies = new HybridDictionary();
static RusCurrency()
{
Register("RUR", true, "рубль", "рубля", "рублей", "копейка", "копейки", "копеек");
Register("EUR", true, "евро", "евро", "евро", "евроцент", "евроцента", "евроцентов");
Register("USD", true, "доллар", "доллара", "долларов", "цент", "цента", "центов");
ConfigurationSettings.GetConfig("currency-names");
}
public static void Register(string currency, bool male,
string seniorOne, string seniorTwo, string seniorFive,
string juniorOne, string juniorTwo, string juniorFive)
{
CurrencyInfo info;
info.male = male;
info.seniorOne = seniorOne; info.seniorTwo = seniorTwo; info.seniorFive = seniorFive;
info.juniorOne = juniorOne; info.juniorTwo = juniorTwo; info.juniorFive = juniorFive;
currencies.Add(currency, info);
}
public static string Str(double val)
{
return Str(val, "RUR");
}
public static string Str(double val, string currency)
{
if(!currencies.Contains(currency))
throw new ArgumentOutOfRangeException("currency", "Валюта \""+currency+"\" не зарегистрирована");
CurrencyInfo info = (CurrencyInfo)currencies[currency];
return Str(val, info.male,
info.seniorOne, info.seniorTwo, info.seniorFive,
info.juniorOne, info.juniorTwo, info.juniorFive);
}
public static string Str(double val, bool male,
string seniorOne, string seniorTwo, string seniorFive,
string juniorOne, string juniorTwo, string juniorFive)
{
bool minus = false;
if(val < 0) { val = - val; minus = true; }
int n = (int) val;
int remainder = (int) (( val - n + 0.005 ) * 100);
StringBuilder r = new StringBuilder();
if(0 == n) r.Append("0 ");
if(n % 1000 != 0)
r.Append(RusNumber.Str(n, male, seniorOne, seniorTwo, seniorFive));
else
r.Append(seniorFive);
n /= 1000;
r.Insert(0, RusNumber.Str(n, false, "тысяча", "тысячи", "тысяч"));
n /= 1000;
r.Insert(0, RusNumber.Str(n, true, "миллион", "миллиона", "миллионов"));
n /= 1000;
r.Insert(0, RusNumber.Str(n, true, "миллиард", "миллиарда", "миллиардов"));
n /= 1000;
r.Insert(0, RusNumber.Str(n, true, "триллион", "триллиона", "триллионов"));
n /= 1000;
r.Insert(0, RusNumber.Str(n, true, "триллиард", "триллиарда", "триллиардов"));
if(minus) r.Insert(0, "минус ");
r.Append(remainder.ToString("00 "));
r.Append(RusNumber.Case(remainder, juniorOne, juniorTwo, juniorFive));
//Делаем первую букву заглавной
r[0] = char.ToUpper(r[0]);
return r.ToString();
}
};
};
Re: Translating financial values
Quote:
Originally Posted by kingmunkyman
To explain more... what I've done is generated every number from 1 - 1000 using the technique I described in my previous post.
For some reason, the logic I've used has resulted in the following errors:
Value Incorrect Narrative Correct form
100.00 ОДИН СТО Рублей СТО Рублей
200.00 ДВА СТО Рублей ДВЕСТИ РУБЛЕЙ
300.00 ТРИ СТО Рублей ТРИСТА РУБЛЕЙ
400.00 ЧЕТЫРЕ СТО Рублей ЧЕТЫРЕСТА РУБЛЕЙ
500.00 ПЯТЬ СТО Рублей ПЯТЬСОТ Рублей
600.00 ШЕСТЬ СТО Рублей ШЕСТЬСОТ РУБЛЕЙ
700.00 СЕМЬ СТО Рублей СЕМЬСОТ РУБЛЕЙ
800.00 ВОСЕМЬ СТО Рублей ВОСЕМЬСОТ РУБЛЕЙ
900.00 ДЕВЯТЬ СТО Рублей ДЕВЯТЬСОТ РУБЛЕЙ
I don't understand the rule that I'm, missing that has caused this error.
I can explain why it happens if you are interested.
You try to construct numbers of hundreds the same way as you do it in English (one hundred, two hundred etc.). That does not work for Russian. You do not say in English "one ten, two ten, three ten", do you? You say "ten, twenty, thirty etc." instead.
In Russian, we have special words for hundreds as well. They are exactly what is provided in your example above.