43
43
#include < string.h>
44
44
#include < cinttypes>
45
45
#include < unicode/listformatter.h>
46
+ #include < unicode/rbnf.h>
46
47
47
48
#include " qof.h"
48
49
#include " gnc-prefs.h"
@@ -1496,106 +1497,30 @@ gnc_wrap_text_with_bidi_ltr_isolate (const char* text)
1496
1497
/* *******************************************************************\
1497
1498
********************************************************************/
1498
1499
1499
- #define FUDGE .00001
1500
-
1501
- /* This function is basically untranslatable. I'd
1502
- guess out of the 29 translations we have, 20 will have their number
1503
- wordings in a totally different way than English has (not to
1504
- mention gender-dependent number endings). Which means this
1505
- word-by-word translation will be useless or even plain
1506
- wrong. For this reason, we don't even start to pretend a
1507
- word-by-word translation would be of any use, so we don't mark any
1508
- of these strings for translation. cstim, 2007-04-15. */
1509
- static const char * small_numbers[] =
1510
- {
1511
- /* Translators: This section is for generating the "amount, in
1512
- words" field when printing a check. This function gets the
1513
- wording right for English, but unfortunately not for most other
1514
- languages. Decide for yourself whether the check printing is
1515
- actually needed in your language; if not, you can safely skip the
1516
- translation of all of these strings. */
1517
- " Zero" , " One" , " Two" , " Three" , " Four" ,
1518
- " Five" , " Six" , " Seven" , " Eight" , " Nine" ,
1519
- " Ten" , " Eleven" , " Twelve" , " Thirteen" , " Fourteen" ,
1520
- " Fifteen" , " Sixteen" , " Seventeen" , " Eighteen" , " Nineteen" ,
1521
- " Twenty"
1522
- };
1523
- static const char * medium_numbers[] =
1524
- {
1525
- " Zero" , " Ten" , " Twenty" , " Thirty" , " Forty" ,
1526
- " Fifty" , " Sixty" , " Seventy" , " Eighty" , " Ninety"
1527
- };
1528
- static const char * big_numbers[] =
1529
- {
1530
- /* Translators: This is the word for the number 10^2 */
1531
- " Hundred" ,
1532
- /* Translators: This is the word for the number 10^3 */
1533
- " Thousand" ,
1534
- /* Translators: This is the word for the number 10^6, one thousand
1535
- thousands. */
1536
- " Million" ,
1537
- /* Translators: This is the word for the number 10^9, one thousand
1538
- millions. WATCH OUT: In British English and many other languages
1539
- this word is used for 10^12 which is one million millions! In
1540
- contrast to this, here in GnuCash this is used in the American
1541
- English meaning of 10^9. */
1542
- " Billion" ,
1543
- /* Translators: This is the word for the number 10^12, one million
1544
- millions. */
1545
- " Trillion" ,
1546
- /* Translators: This is the word for the number 10^15 */
1547
- " Quadrillion" ,
1548
- /* Translators: This is the word for the number 10^18 */
1549
- " Quintillion"
1550
- };
1551
-
1552
- static char *
1553
- integer_to_words (gint64 val)
1500
+ static std::string
1501
+ number_to_words (double val)
1554
1502
{
1555
- if (val == 0 )
1556
- return g_strdup (" zero" );
1557
- if (val < 0 )
1558
- val = -val;
1559
-
1560
- auto result = g_string_sized_new (100 );
1561
-
1562
- while (val >= 1000 )
1563
- {
1564
- int log_val = log10 (val) / 3 + FUDGE;
1565
- int pow_val = exp (log_val * 3 * G_LN10) + FUDGE;
1566
- int this_part = val / pow_val;
1567
- val -= this_part * pow_val;
1568
- auto tmp = integer_to_words (this_part);
1569
- g_string_append_printf (result, " %s %s " , tmp, gettext (big_numbers[log_val]));
1570
- g_free (tmp);
1571
- }
1572
-
1573
- if (val >= 100 )
1503
+ UErrorCode status{U_ZERO_ERROR};
1504
+ icu::RuleBasedNumberFormat formatter{icu::URBNF_SPELLOUT, icu::Locale{}, status};
1505
+ icu::UnicodeString result;
1506
+ std::string words;
1507
+ if (U_FAILURE (status))
1574
1508
{
1575
- int this_part = val / 100 ;
1576
- val -= this_part * 100 ;
1577
- g_string_append_printf (result, " %s %s " ,
1578
- gettext (small_numbers[this_part]),
1579
- gettext (big_numbers[0 ]));
1509
+ PERR (" Error creating formatter: %s" , u_errorName (status));
1510
+ return " " ;
1580
1511
}
1581
1512
1582
- if (val > 20 )
1513
+ formatter.format (std::fabs (val), result, status);
1514
+ if (U_FAILURE (status))
1583
1515
{
1584
- int this_part = val / 10 ;
1585
- val -= this_part * 10 ;
1586
- g_string_append (result, gettext (medium_numbers[this_part]));
1587
- g_string_append_c (result, ' ' );
1516
+ PERR (" Error formatting number: %s" , u_errorName (status));
1517
+ return " " ;
1588
1518
}
1589
1519
1590
- if (val > 0 )
1591
- {
1592
- int this_part = val;
1593
- g_string_append (result, gettext (small_numbers[this_part]));
1594
- g_string_append_c (result, ' ' );
1595
- }
1520
+ result.toUTF8String (words);
1521
+ DEBUG (" Number %f in words: %s" , val, words.c_str ());
1596
1522
1597
- result = g_string_truncate (result, result->len - 1 );
1598
- return g_string_free (result, FALSE );
1523
+ return words;
1599
1524
}
1600
1525
1601
1526
#ifdef _MSC_VER
@@ -1606,39 +1531,10 @@ static double round(double x)
1606
1531
}
1607
1532
#endif
1608
1533
1609
- char *
1610
- number_to_words (double val, int64_t denom)
1611
- {
1612
- if (val < 0 ) val = -val;
1613
- if (denom < 0 ) denom = -denom;
1614
-
1615
- auto int_part = floor (val);
1616
- auto frac_part = static_cast <int64_t >(round ((val - int_part) * denom));
1617
-
1618
- auto int_string = integer_to_words (int_part);
1619
- /* Inside of the gettext macro _(...) we must not use any macros but
1620
- only plain string literals. For this reason, convert the strings
1621
- separately. */
1622
- auto nomin_string = g_strdup_printf (" %02" PRId64, frac_part);
1623
- auto denom_string = g_strdup_printf (" %" PRId64, denom);
1624
- auto full_string =
1625
- /* Translators: This is for the "amount, in words" field in check
1626
- printing. The first %s is the integer amount of dollars (or
1627
- whatever currency), the second and third %s the cent amount as
1628
- a fraction, e.g. 47/100. */
1629
- g_strdup_printf (" %s and %s/%s" ,
1630
- int_string, nomin_string, denom_string);
1631
- g_free (int_string);
1632
- g_free (nomin_string);
1633
- g_free (denom_string);
1634
- return full_string;
1635
- }
1636
-
1637
1534
char *
1638
1535
numeric_to_words (gnc_numeric val)
1639
1536
{
1640
- return number_to_words (gnc_numeric_to_double (val),
1641
- gnc_numeric_denom (val));
1537
+ return g_strdup (number_to_words (gnc_numeric_to_double (val)).c_str ());
1642
1538
}
1643
1539
1644
1540
const char *
0 commit comments