Skip to content

Commit

Permalink
Fix: fix & improve AR (#137)
Browse files Browse the repository at this point in the history
* Fix: fix & improve AR

* more tests

* AR improvements

* Add 1 test

* test params
  • Loading branch information
forzagreen authored Apr 14, 2024
1 parent ec37966 commit ee45900
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 100 deletions.
116 changes: 59 additions & 57 deletions lib/i18n/ar.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class Arabic extends AbstractLanguage {
'تسعة عشر',
],
feminine: [
'إحدى',
'واحدة',
'اثنتان',
'ثلاث',
'أربع',
Expand Down Expand Up @@ -64,10 +64,6 @@ export class Arabic extends AbstractLanguage {

arabicPluralGroups = ['', 'آلاف', 'ملايين', 'مليارات', 'تريليونات', 'كوادريليونات', 'كوينتليونات', 'سكستيليونات'];

// isCurrencyPartNameFeminine = true

// isCurrencyNameFeminine = false

constructor(options) {
options = Object.assign({
negativeWord: 'ناقص',
Expand All @@ -82,98 +78,101 @@ export class Arabic extends AbstractLanguage {
}

digitFeminineStatus(digit) {
// if ((groupLevel == -1 && this.isCurrencyPartNameFeminine) || (groupLevel == 0 && this.isCurrencyNameFeminine)) {
// return this.arabicFeminineOnes[digit]
// }
return this.ones[this.feminine ? 'feminine' : 'masculine'][digit - 1];
}

processArabicGroup(groupNumber, groupLevel, remainingNumber) {
/**
* Processes the Arabic group number and returns the corresponding Arabic representation.
* @param {number} groupNumber - The number to process. From 1 to 999.
* @param {number} groupLevel - The level of the group.
* Example: 12345678 is processed in blocks: '678' (group 0), '345' (group 1), '12' (group 2)
* @returns {string} The Arabic representation of the group number.
*/
processArabicGroup(groupNumber, groupLevel) {
let tens = groupNumber % 100;
const hundreds = groupNumber / 100;
let retVal = '';

if (hundreds > 0) {
retVal = (tens == 0 && Math.trunc(hundreds) == 2 ? this.arabicAppendedTwos[0] : this.arabicHundreds[Math.trunc(hundreds)]);
if (Math.trunc(hundreds) > 0) {
if (tens == 0 && Math.trunc(hundreds) == 2) {
retVal = this.arabicTwos[0];
} else {
retVal = this.arabicHundreds[Math.trunc(hundreds)];
if (retVal != '' && tens != 0) {
retVal += ' و';
}
}
}

if (tens > 0) {
if (tens < 20) {
if (tens == 2 && Math.trunc(hundreds) == 0 && groupLevel > 0) {
retVal = ([
2000, 2000000, 2000000000, 2000000000000, 2000000000000000, 2000000000000000000
].indexOf(this.number) != -1) ? this.arabicAppendedTwos[groupLevel] : this.arabicTwos[groupLevel];
} else {
// Add divider
if (retVal != '') {
retVal += ' و ';
}

if (tens == 1 && groupLevel > 0 && hundreds == 0) {
retVal += '';
} else if (
(tens == 1 || tens == 2) &&
(groupLevel == 0 || groupLevel == -1) &&
(hundreds == 0 && remainingNumber == 0)
) {
retVal += '';
if (tens > 0 && tens < 20) { // 1 -> 19
if (tens === 2 && Math.trunc(hundreds) === 0 && groupLevel > 0) {
const pow = Math.trunc(Math.log10(Number(this.number)));
if (pow % 3 === 0 && this.number === 2 * Math.pow(10, pow)) {
if (groupNumber === 2) {
retVal = this.arabicTwos[Math.trunc(groupLevel)];
} else {
retVal += this.digitFeminineStatus(Math.trunc(tens), groupLevel);
retVal = this.arabicAppendedTwos[Math.trunc(groupLevel)];
}
} else {
retVal = this.arabicTwos[Math.trunc(groupLevel)];
}
} else if (tens === 1 && groupLevel > 0) {
retVal += this.arabicGroup[Math.trunc(groupLevel)];
} else {
const ones = tens % 10;
tens = (tens / 10) - 2;

if (ones > 0) {
if (retVal != '' && tens < 4) {
retVal += ' و ';
}

retVal += this.digitFeminineStatus(ones, groupLevel);
}
if (retVal != '' && ones != 0) {
retVal += ' و ';
}

retVal += this.arabicTens[Math.trunc(tens)];
retVal += this.digitFeminineStatus(Math.trunc(tens), groupLevel);
}
} else if (tens >= 20) { // 20 -> 99
const ones = tens % 10;
const tensIndex = (tens / 10) - 2;
if (ones > 0) {
retVal += this.digitFeminineStatus(ones, groupLevel);
}
if (retVal != '' && ones != 0) {
retVal += ' و';
}
retVal += this.arabicTens[Math.trunc(tensIndex)];
}

return retVal;
}

/**
* Converts a number to its cardinal representation in Arabic.
* It process by blocks of 3 digits.
* @param {number} number - The number to convert.
* @returns {string} The cardinal representation of the number in Arabic.
*/
toCardinal(number) {
if (number == 0) {
return this.zero;
}

this.number = number;
let tempNumber = number;
let tempNumberDec;
let group = 0;
let retVal = '';

// Loop until number has been reduced to zero or less
while (tempNumber > 0) {
tempNumberDec = tempNumber;
// Get the remaining value after dividing by 1000
const numberToProcess = Number(tempNumber % 1000n); // Maximum: 999
// Divide number by 1000
tempNumber = tempNumber / 1000n;
const numberToProcess = Number(tempNumberDec % 1000n); // Maximum: 999
tempNumber = tempNumberDec / 1000n;

// Process "group"
const groupDescription = this.processArabicGroup(numberToProcess, group, tempNumber);
const groupDescription = this.processArabicGroup(numberToProcess, group);

// Did the group return anything?
if (groupDescription != '') {
// Is this after the first "group"?
if (group > 0) {
// Is the return value still empty?
// Is this after the first "group" ? Because nothing is appeded after group 0.
if (group > 0) { // hundreds, thousands, etc...
// Is the return value still empty ?
if (retVal != '') {
retVal = ' و ' + retVal;
retVal = ' و' + retVal;
}

// Process every number other than 2
if (numberToProcess != 2) {
if (numberToProcess > 2) {
if (numberToProcess % 100 != 1) {
if (numberToProcess >= 3 && numberToProcess <= 10) {
retVal = this.arabicPluralGroups[group] + ' ' + retVal;
Expand All @@ -199,6 +198,9 @@ export class Arabic extends AbstractLanguage {
group++;
}

// Replace multiple spaces with one space
retVal = retVal.replace(/ +/g, ' ');

return retVal.trim();
}
}
Expand Down
111 changes: 68 additions & 43 deletions test/i18n/ar.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,70 +2,95 @@ export default [
[0.01, 'صفر فاصلة صفر واحد'],
[1.7, 'واحد فاصلة سبعة'],
[1.007, 'واحد فاصلة صفر صفر سبعة'],
[17.42, 'سبعة عشر فاصلة اثنان و أربعون'],
[27.312, 'سبعة و عشرون فاصلة ثلاثمائة و اثنا عشر'],
[53.486, 'ثلاثة و خمسون فاصلة أربعمائةستة و ثمانون'], //FIXME
[300.42, 'ثلاثمائة فاصلة اثنان و أربعون'],
[4196.42, 'أربعة آلاف و مائةستة و تسعون فاصلة اثنان و أربعون'], //FIXME
[17.42, 'سبعة عشر فاصلة اثنان وأربعون'],
[27.312, 'سبعة وعشرون فاصلة ثلاثمائة واثنا عشر'],
[53.486, 'ثلاثة وخمسون فاصلة أربعمائة وستة وثمانون'],
[300.42, 'ثلاثمائة فاصلة اثنان وأربعون'],
[4196.42, 'أربعة آلاف ومائة وستة وتسعون فاصلة اثنان وأربعون'],

[-17.42, 'ناقص سبعة عشر فاصلة اثنان و أربعون'],
[-17.42, 'ناقص سبعة عشر فاصلة اثنان وأربعون'],
[-1, 'ناقص واحد'],
[-20, 'ناقص عشرون'],
[-20, 'سالب عشرون', { negativeWord: 'سالب' }],

[0, 'صفر'],
[1, 'واحد'],
[1, 'واحدة', { feminine: true }],
[2, 'اثنان'],
[3, 'ثلاثة'],
[3, 'ثلاث', { feminine: true }],
[11, 'أحد عشر'],
[11, 'إحدى عشرة', { feminine: true }],
[12, 'اثنا عشر'],
[16, 'ستة عشر'],
[19, 'تسعة عشر'],
[20, 'عشرون'],
[21, 'واحد و عشرون'],
[26, 'ستة و عشرون'],
[28, 'ثمانية و عشرون'],
[21, 'واحد وعشرون'],
[26, 'ستة وعشرون'],
[28, 'ثمانية وعشرون'],
[30, 'ثلاثون'],
[31, 'واحد و ثلاثون'],
[31, 'واحد وثلاثون'],
[40, 'أربعون'],
[44, 'أربعة و أربعون'],
[44, 'أربعة وأربعون'],
[50, 'خمسون'],
[55, 'خمسة و خمسون'],
[55, 'خمسة وخمسون'],
[60, 'ستون'],
[67, 'سبعة و ستون'],
[67, 'سبعة وستون'],
[70, 'سبعون'],
[79, 'تسعة و سبعون'],
[89, 'تسعة و ثمانون'],
[95, 'خمسة و تسعون'],
[79, 'تسعة وسبعون'],
[89, 'تسعة وثمانون'],
[95, 'خمسة وتسعون'],
[100, 'مائة'],
[101, 'مائة و واحد'],
[199, 'مائةتسعة و تسعون'],
[203, 'مئتان و ثلاثة'],
[287, 'مئتانسبعة و ثمانون'],
[356, 'ثلاثمائة و ستة و خمسون'],
[101, 'مائة وواحد'],
[110, 'مائة وعشرة'],
[110, 'مائة وعشر', { feminine: true }],
[120, 'مائة وعشرون'],
[130, 'مائة وثلاثون'],
[130, 'مائة وثلاثون', { feminine: true }],
[190, 'مائة وتسعون'],
[198, 'مائة وثمانية وتسعون'],
[199, 'مائة وتسعة وتسعون'],
[200, 'مئتان'],
[203, 'مئتان وثلاثة'],
[287, 'مئتان وسبعة وثمانون'],
[356, 'ثلاثمائة وستة وخمسون'],
[400, 'أربعمائة'],
[434, 'أربعمائة و أربعة و ثلاثون'],
[578, 'خمسمائةثمانية و سبعون'],
[689, 'ستمائةتسعة و ثمانون'],
[729, 'سبعمائة و تسعة و عشرون'],
[894, 'ثمانمائةأربعة و تسعون'],
[999, 'تسعمائةتسعة و تسعون'],
[1000, 'واحد ألف'],
[1001, 'واحد ألف و واحد'],
[1097, 'واحد ألف و سبعة و تسعون'],
[1104, 'واحد ألف و مائة و أربعة'],
[1243, 'واحد ألف و مئتان و ثلاثة و أربعون'],
[2385, 'ألفان و ثلاثمائةخمسة و ثمانون'],
[3766, 'ثلاثة آلاف و سبعمائةستة و ستون'],
[4196, 'أربعة آلاف و مائةستة و تسعون'], //FIXME
[5846, 'خمسة آلاف و ثمانمائة و ستة و أربعون'],
[6459, 'ستة آلاف و أربعمائة و تسعة و خمسون'],
[7232, 'سبعة آلاف و مئتان و اثنان و ثلاثون'],
[8569, 'ثمانية آلاف و خمسمائةتسعة و ستون'],
[9539, 'تسعة آلاف و خمسمائة و تسعة و ثلاثون'],
[1000000, 'واحد مليون'],
[1000001, 'واحد مليون و واحد'],
[434, 'أربعمائة وأربعة وثلاثون'],
[578, 'خمسمائة وثمانية وسبعون'],
[689, 'ستمائة وتسعة وثمانون'],
[729, 'سبعمائة وتسعة وعشرون'],
[810, 'ثمانمائة وعشرة'],
[820, 'ثمانمائة وعشرون'],
[823, 'ثمانمائة وثلاثة وعشرون'],
[833, 'ثمانمائة وثلاثة وثلاثون'],
[863, 'ثمانمائة وثلاثة وستون'],
[883, 'ثمانمائة وثلاثة وثمانون'],
[894, 'ثمانمائة وأربعة وتسعون'],
[999, 'تسعمائة وتسعة وتسعون'],
[1000, 'ألف'],
[2000, 'ألفان'],
[1001, 'ألف وواحد'],
[1097, 'ألف وسبعة وتسعون'],
[1104, 'ألف ومائة وأربعة'],
[1243, 'ألف ومئتان وثلاثة وأربعون'],
[2385, 'ألفان وثلاثمائة وخمسة وثمانون'],
[3766, 'ثلاثة آلاف وسبعمائة وستة وستون'],
[4196, 'أربعة آلاف ومائة وستة وتسعون'],
[5846, 'خمسة آلاف وثمانمائة وستة وأربعون'],
[6459, 'ستة آلاف وأربعمائة وتسعة وخمسون'],
[7232, 'سبعة آلاف ومئتان واثنان وثلاثون'],
[8569, 'ثمانية آلاف وخمسمائة وتسعة وستون'],
[9539, 'تسعة آلاف وخمسمائة وتسعة وثلاثون'],
[200200, 'مئتان ألفاً ومئتان'],
[200000, 'مئتان ألف'],
[300200, 'ثلاثمائة ألفاً ومئتان'],
[1000000, 'مليون'],
[1000001, 'مليون وواحد'],
[2000000, 'مليونان'],
[4000000, 'أربعة ملايين'],
[12345678, 'اثنا عشر مليوناً وثلاثمائة وخمسة وأربعون ألفاً وستمائة وثمانية وسبعون'],
[2000000000, 'ملياران'],
[10000000000000, 'عشرة تريليونات'],
[100000000000000, 'مائة تريليون'],
[1000000000000000000n, 'واحد كوينتليون'],
[1000000000000000000n, 'كوينتليون'],
];

0 comments on commit ee45900

Please sign in to comment.