[pim/korganizer] plugins/hebrewcalendar: plugins/hebrewcalendar/hebrew.cpp - use hebrew numerals in the dates

Allen Winter <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 7f103ed9cf18cdb5489bf5ec7c024d6b8958a88d by Allen Winter.
Committed on 07/08/2026 at 10:50.
Pushed by winterz into branch 'master'.

plugins/hebrewcalendar/hebrew.cpp - use hebrew numerals in the dates

M  +103  -1    plugins/hebrewcalendar/hebrew.cpp

https://invent.kde.org/pim/korganizer/-/commit/7f103ed9cf18cdb5489bf5ec7c024d6b8958a88d

diff --git a/plugins/hebrewcalendar/hebrew.cpp b/plugins/hebrewcalendar/hebrew.cpp
index b131b30a8..276117c98 100644
--- a/plugins/hebrewcalendar/hebrew.cpp
+++ b/plugins/hebrewcalendar/hebrew.cpp
@@ -41,6 +41,108 @@ void Hebrew::configure(QWidget *parent)
     dlg.exec();
 }
 
+static QString stringFromInteger(int number)
+{
+    if (QLocale().language() == QLocale::Hebrew) {
+        // Hebrew numbers are composed of combinations of normal letters which have a numeric value.
+        // This is a non-positional system, the numeric values are simply added together, however
+        // convention is for a RTL highest to lowest value ordering. There is also a degree of
+        // ambiguity due to the lack of a letter for 0, hence 5 and 5000 are written the same.
+        // Hebrew numbers are only used in dates.
+        // See https://en.wikipedia.org/wiki/Hebrew_numerals for more explanation
+
+        /*
+         *        Ref table for numbers to Hebrew chars
+         *
+         *        Value     1       2       3        4        5       6         7        8      9
+         *
+         *        x 1    Alef א  Bet  ב  Gimel ג  Dalet ד  He   ה  Vav  ו    Zayen ז  Het  ח  Tet  ט
+         *               0x05D0  0x05D1  0x05D2   0x05D3   0x05D4  0x05D5    0x05D6   0x05D7  0x05D8
+         *
+         *        x 10   Yod  י  Kaf  כ  Lamed ל  Mem  מ   Nun  נ  Samekh ס  Ayin ע   Pe   פ  Tzadi צ
+         *               0x05D9  0x05DB  0x05DC   0x05DE   0x05E0  0x05E1    0x05E2   0x05E4  0x05E6
+         *
+         *        x 100  Qof  ק  Resh ר  Shin ש   Tav  ת
+         *               0x05E7  0x05E8  0x05E9   0x05EA
+         *
+         *        Note special cases 15 = 9 + 6 = 96 טו and 16 = 9 + 7 = 97 טז
+         */
+
+        const unsigned int decade[] = {//  Tet = ט,    Yod = י,    Kaf = כ,    Lamed = ל,  Mem = מ
+                                       //  Nun = נ,    Samekh = ס, Ayin = ע,   Pe = פ,     Tsadi = צ
+                                       0x05D8,
+                                       0x05D9,
+                                       0x05DB,
+                                       0x05DC,
+                                       0x05DE,
+                                       0x05E0,
+                                       0x05E1,
+                                       0x05E2,
+                                       0x05E4,
+                                       0x05E6};
+
+        QString result;
+
+        // We have no rules for coping with numbers outside this range
+        if (number < 1 || number > 9999) {
+            return QString::number(number);
+        }
+
+        // Translate the thousands digit, just uses letter for number 1..9 ( א to ט, Alef to Tet )
+        // Years 5001-5999 do not have the thousands by convention
+        if (number >= 1000) {
+            if (number <= 5000 || number >= 6000) {
+                result += QChar(0x05D0 - 1 + number / 1000); // Alef א to Tet ט
+            }
+            number %= 1000;
+        }
+
+        // Translate the hundreds digit
+        // Use traditional method where we only have letters assigned values for 100, 200, 300 and 400
+        // so may need to repeat 400 twice to make up the required number
+        if (number >= 100) {
+            while (number >= 500) {
+                result += QChar(0x05EA); // Tav = ת
+                number -= 400;
+            }
+            result += QChar(0x05E7 - 1 + number / 100); // Qof = ק to xxx
+            number %= 100;
+        }
+
+        // Translate the tens digit
+        // The numbers 15 and 16 translate to letters that spell out the name of God which is
+        // forbidden, so require special treatment where 15 = 9 + 6 and 1 = 9 + 7.
+        if (number >= 10) {
+            if (number == 15 || number == 16) {
+                number -= 9;
+            }
+            result += static_cast<QChar>(decade[number / 10]);
+            number %= 10;
+        }
+
+        // Translate the ones digit, uses letter for number 1..9 ( א to ט, Alef to Tet )
+        if (number > 0) {
+            result += QChar(0x05D0 - 1 + number); // Alef = א to xxx
+        }
+
+        // When used in a string with mixed names and numbers the numbers need special chars to
+        // distinguish them from words composed of the same letters.
+        // Single digit numbers are followed by a geresh symbol ? (Unicode = 0x05F3), but we use
+        // single quote for convenience.
+        // Multiple digit numbers have a gershayim symbol ? (Unicode = 0x05F4) as second-to-last
+        // char, but we use double quote for convenience.
+        if (result.length() == 1) {
+            result += QLatin1Char('\'');
+        } else {
+            result.insert(result.length() - 1, QLatin1Char('\"'));
+        }
+
+        return result;
+    } else {
+        return QString::number(number);
+    }
+}
+
 static bool isLeapYear(int year)
 {
     return ((((7 * year) + 1) % 19) < 7);
@@ -122,7 +224,7 @@ Element::List Hebrew::createDayElements(const QDate &date)
     QString text;
     const KHolidays::HebrewDate hd = KHolidays::HebrewDate::fromSecular(date.year(), date.month(), date.day());
     const QStringList holidays = Holiday::findHoliday(hd, areWeInIsrael, showParsha, showChol, showOmer);
-    text = i18nc("1. day of the month 2. hebrew month", "%1 %2", hd.day(), monthName(hd.month(), hd.year()));
+    text = i18nc("1. day of the month 2. hebrew month", "%1 %2", stringFromInteger(hd.day()), monthName(hd.month(), hd.year()));
 
     for (const QString &holiday : holidays) {
         text += QLatin1StringView("<br/>\n") + holiday;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.