Converting Numbers to Arabic Words in OnlyOffice
IMPORTANT: This script requires OnlyOffice version 9 and above for proper RTL support.
Hey,
Since I already tackled converting numbers to French Number to Words Conversion for OnlyOffice (=NOMBREENLETTRES) words, I thought, why not take on Arabic too? Especially for Algerian Dinars, because let’s be real… no one wants to write out “one billion two hundred thirty-four million…” manually. So, I whipped up this script to do the dirty work for you. Hope it makes your life easier!
What This Magical Script Can Do:
Converts Numbers to Arabic Words : Yes, even numbers that make accountants cry. Billions? Bring it on.
Handles Decimals : Converts fractional values into “سنتيم” (cents), so your invoices don’t look like a math experiment gone wrong.
Respects (Most) Arabic Grammar Rules : Singular, dual, and plural forms? Check. No awkward mistakes like saying اثنان مليون (two million) should be مليونان (I see you, bad translations).
Doesn’t Freak Out Over Large Numbers : Whether it’s thousands, millions, or billions, the script keeps things classy and grammatically cool
(function() {
/**
* Convertit un nombre en lettres avec la devise "dinar algérien".
* @customfunction
* @param {number} Nb Le nombre à convertir.
* @returns {string} Le nombre en lettres avec la devise.
* @author: Cheikh GPT 😜
*/
function numberToArabicDinar(num) {
if (typeof num !== 'number') {
num = parseFloat(num);
}
if (isNaN(num) || num < 0) return "خطأ: إدخال غير صالح";
num = parseFloat(num.toFixed(2)); // Arrondir à 2 décimales
let ones = ["", "واحد", "اثنان", "ثلاثة", "أربعة", "خمسة", "ستة", "سبعة", "ثمانية", "تسعة"];
let teens = ["عشرة", "أحد عشر", "اثنا عشر", "ثلاثة عشر", "أربعة عشر", "خمسة عشر", "ستة عشر", "سبعة عشر", "ثمانية عشر", "تسعة عشر"];
let tens = ["", "", "عشرين", "ثلاثين", "أربعين", "خمسين", "ستين", "سبعين", "ثمانين", "تسعين"];
let hundreds = ["", "مئة", "مئتان", "ثلاثمئة", "أربعمئة", "خمسمئة", "ستمئة", "سبعمئة", "ثمانمئة", "تسعمئة"];
var connector = " و"; // Espace insécable
function convertBelowThousand(n) {
let words = "";
if (n >= 100) {
words += hundreds[Math.floor(n / 100)];
n %= 100;
if (n > 0) words += connector;
}
if (n >= 20) {
let unit = n % 10;
let ten = Math.floor(n / 10);
words += (unit > 0) ? ones[unit] + connector + tens[ten] : tens[ten];
} else if (n >= 10) {
words += teens[n - 10];
} else if (n > 0) {
words += ones[n];
}
return words;
}
function convertNumberToWords(n) {
if (n < 1000) return convertBelowThousand(n);
let words = "";
let billions = Math.floor(n / 1000000000);
if (billions > 0) {
words += (billions === 1) ? "مليار" :
(billions === 2) ? "ملياران" :
(billions <= 10) ? convertBelowThousand(billions) + " مليارات" :
convertBelowThousand(billions) + " مليار";
n %= 1000000000;
if (n > 0) words += connector;
}
let millions = Math.floor(n / 1000000);
if (millions > 0) {
words += (millions === 1) ? "مليون" :
(millions === 2) ? "مليونان" :
(millions <= 10) ? convertBelowThousand(millions) + " ملايين" :
convertBelowThousand(millions) + " مليون";
n %= 1000000;
if (n > 0) words += connector;
}
let thousands = Math.floor(n / 1000);
if (thousands > 0) {
words += (thousands === 1) ? "ألف" :
(thousands === 2) ? "ألفان" :
(thousands <= 10) ? convertBelowThousand(thousands) + " آلاف" :
convertBelowThousand(thousands) + " ألف";
n %= 1000;
if (n > 0) words += connector;
}
if (n > 0) words += convertBelowThousand(n);
return words;
}
let integerPart = Math.floor(num);
let fractionPart = Math.round((num - integerPart) * 100);
let result = "";
if (integerPart === 0) {
result = "صفر دينار جزائري";
} else if (integerPart === 1) {
result = "دينار جزائري واحد";
} else if (integerPart === 2) {
result = "ديناران جزائريان";
} else {
result = convertNumberToWords(integerPart) + " دينار جزائري";
}
if (fractionPart > 0) {
result += connector;
result += (fractionPart === 1) ? "سنتيم واحد" :
(fractionPart === 2) ? "سنتيمان" :
convertBelowThousand(fractionPart) + " سنتيم";
}
return result;
}
// Register function initially
Api.AddCustomFunction(numberToArabicDinar);
// Ensure function registers when the document loads
window.Asc.plugin.onDocumentContentReady = function() {
Api.AddCustomFunction(numberToArabicDinar);
};
})();
A Few Totally Necessary Notes:
- Grammar Perfectionists, LOOK AWAY: Technically, Arabic grammar has different forms for some numbers (e.g., “دينارا جزائريا” vs. “دينار جزائري” vs. “دنانير جزائرية”). But guess what? I took the easy route and picked one consistent form. Invoices aren’t winning poetry awards, right?
- Masculine vs Feminine Words, Pick a Side: The word “dinar” (دينار) is masculine in Arabic, so the numbers should follow suit. But here’s the plot twist : when “dinar” goes plural, it suddenly switches to feminine (دنانير جزائرية). Yeah, Arabic likes to keep things interesting.
Technically:
- دينار جزائري 1(one Algerian dinar, masculine)
- ديناران جزائريان 2(two Algerian dinars, still masculine)
- دنانير جزائرية 3(three Algerian dinars, now feminine, because why not?)
But instead of playing grammatical gymnastics, I decided to keep it simple by always using the singular form (دينار جزائري). It’s not 100% accurate, but for invoices? Good enough. If anyone complains, tell them to take it up with the Arabic language department. ![]()
If you need this script for feminine currency like “lira,” you have two options: (1) manually adjust the wording, or (2) add a ton of extra code, making this script as bloated as a Windows update. Your call.
- Rounding Done Right: This script trims numbers to two decimal places. So if you try 1.009, it will be converted to Arabic text for 1.01. If your currency needs three or four decimal places, tweak this line:
num = parseFloat(num.toFixed(2)) - Why Are There Weird Boxes Instead of Arabic Letters? Your font choice is betraying you. Switch to one that supports Arabic, like Arial or Amiri… and you’ll be fine.
- Negative Numbers? Seriously? I added some basic warnings, like one for negative numbers, but I didn’t go all out with error handling. Who in their right mind invoices debt, anyway?? (If you do, please share…I promise I won’t judge… much.
) - Testing? Yeah, Sort of. This script has been through some light testing (I don’t deal with Arabic invoices daily). If you find bugs, congrats… you just volunteered to fix them.
Feel free to improve it, share it, or adapt it for whatever open-source madness you’re working on. ![]()
PS. (Because drama)
Technically you can use AI to do the dirty job but guess what :
- Sure, you could unleash a +7B parameter monster to do this. I tried. Cool results, but by the time it’s done, your invoice total has already changed.
- Online AI ?! Meh… Talk to me when you get a job inside a cave with no internet like I often do

- There is no three… Have fun

- The three : I’m not a programmer anymore… This was done by the help of Cheikh GPT… Ask it for debug

Quick Update:
- Fixed ghosting (
#NAME?) by making the script load every time the document opens. - Loads only when doc is ready.