Hey
In every financial systems we should show the letter version of numbers particularly in prints. It is also very useful for large numbers to understand it. For example if you see this number in digits "900025235" you can't catch how much it is exactly in short view but not in letters "Nine hundred million twenty five thousand two hundred and thirty five".
I think Persian digits letters are one of the most difficult ones in the different languages. Today we are trying to handle this. First take a look here:
1.Usage
Our mission is to change the input hint whenever its value is changed. To register that to your input you should pass these steps:
- include jquery framework to your page
- include number.to.persian.letters.js to your page
- register your input to the engine on this way:
<script type="text/javascript"> $(function() { $(".toLetter").numberToLetter(); }); </script>
2.How it works
First take a look to the file number.to.persian.letters.js:
1 /** 2 * number.to.persian.letters.js 3 * @author: Mostafa Rastgar 4 * @version: 1.0.0 5 * 6 * Created by Mostafa Rastgar on 2012-07-11. Please report any bug at http://prgassist.blogspot.com/ 7 * 8 * Copyright (c) 2012 Mostafa Rastgar http://prgassist.blogspot.com/ 9 * 10 * 11 */ 12 $(function($) { 13 var names = {"0": {value:"\u0635\u0641\u0631", scale:false}, 14 "1": {value:"\u064a\u06a9", scale:false}, 15 "2": {value:"\u062f\u0648", scale:false}, 16 "3": {value:"\u0633\u0647", scale:false}, 17 "4": {value:"\u0686\u0647\u0627\u0631", scale:false}, 18 "5": {value:"\u067e\u0646\u062c", scale:false}, 19 "6": {value:"\u0634\u0634", scale:false}, 20 "7": {value:"\u0647\u0641\u062a", scale:false}, 21 "8": {value:"\u0647\u0634\u062a", scale:false}, 22 "9": {value:"\u0646\u0647", scale:false}, 23 "10": {value:"\u062f\u0647", scale:false}, 24 "11": {value:"\u064a\u0627\u0632\u062f\u0647", scale:false}, 25 "12": {value:"\u062f\u0648\u0627\u0632\u062f\u0647", scale:false}, 26 "13": {value:"\u0633\u064a\u0632\u062f\u0647", scale:false}, 27 "14": {value:"\u0686\u0647\u0627\u0631\u062f\u0647", scale:false}, 28 "15": {value:"\u067e\u0627\u0646\u0632\u062f\u0647", scale:false}, 29 "16": {value:"\u0634\u0627\u0646\u0632\u062f\u0647", scale:false}, 30 "17": {value:"\u0647\u0641\u062f\u0647", scale:false}, 31 "18": {value:"\u0647\u062c\u062f\u0647", scale:false}, 32 "19": {value:"\u0646\u0648\u0632\u062f\u0647", scale:false}, 33 "20": {value:"\u0628\u064a\u0633\u062a", scale:false}, 34 "30": {value:"\u0633\u064a", scale:false}, 35 "40": {value:"\u0686\u0647\u0644", scale:false}, 36 "50": {value:"\u067e\u0646\u062c\u0627\u0647", scale:false}, 37 "60": {value:"\u0634\u0635\u062a", scale:false}, 38 "70": {value:"\u0647\u0641\u062a\u0627\u062f", scale:false}, 39 "80": {value:"\u0647\u0634\u062a\u0627\u062f", scale:false}, 40 "90": {value:"\u0646\u0648\u062f", scale:false}, 41 "100": {value:"\u0635\u062f", scale:false}, 42 "200": {value:"\u062f\u0648\u064a\u0633\u062a", scale:false}, 43 "300": {value:"\u0633\u064a\u0635\u062f", scale:false}, 44 "400": {value:"\u0686\u0647\u0627\u0631\u0635\u062f", scale:false}, 45 "500": {value:"\u067e\u0627\u0646\u0635\u062f", scale:false}, 46 "600": {value:"\u0634\u0634\u0635\u062f", scale:false}, 47 "700": {value:"\u0647\u0641\u062a\u0635\u062f", scale:false}, 48 "800": {value:"\u0647\u0634\u062a\u0635\u062f", scale:false}, 49 "900": {value:"\u0646\u0647\u0635\u062f", scale:false}, 50 "1000": {value:"\u0647\u0632\u0627\u0631", scale:true}, 51 "1000000": {value:"\u0645\u064a\u0644\u064a\u0648\u0646", scale:true}, 52 "1000000000": {value:"\u0645\u064a\u0644\u064a\u0627\u0631\u062f", scale:true}, 53 "1000000000000": {value:"\u062a\u064a\u0644\u064a\u0627\u0631\u062f", scale:true}, 54 "1000000000000000": {value:"\u06a9\u0627\u062a\u064a\u0644\u064a\u0627\u0631\u062f", scale:true} 55 }; 56 $.fn.numberToLetter = function() { 57 $(this).change(function() { 58 numberChange($(this)); 59 }); 60 numberChange($(".toLetter")); 61 } 62 function numberChange(input){ 63 var value = input.val(); 64 input.attr({title:numberToLetter(value)}); 65 } 66 function numberToLetter(value) { 67 value = value.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"); 68 var parts = value.split(","); 69 var textParts = new Array(); 70 for (var i = 0; i < parts.length; i++) { 71 var setScale = renderNumber(parts[i], textParts); 72 if (setScale) { 73 renderScale((parts.length - i - 1), textParts); 74 } 75 } 76 77 var text = concatNumberTexts(textParts); 78 if (text == "" && value != "") { 79 return names["0"].value; 80 } else { 81 return text; 82 } 83 } 84 85 function concatNumberTexts(renderRepository) { 86 var text = ""; 87 for (var i = 0; i < renderRepository.length; i++) { 88 if (text != "") { 89 text += " "; 90 } 91 if (text != "" && allowComman(renderRepository[i])) { 92 text += "\u0648 "; 93 } 94 text += renderRepository[i]; 95 } 96 return text; 97 } 98 99 function renderScale(scaleIndex, renderRepository) { 100 var section = pow(scaleIndex * 3); 101 if (section > 1) { 102 renderRepository.push(names[section.toString()].value); 103 } 104 } 105 106 function renderTwoLengthNumber(num1, num2, renderRepository, setScale) { 107 if (num1 == "1") { 108 renderRepository.push(names[num1 + num2].value); 109 setScale = true; 110 } else { 111 if (num1 != "0") { 112 renderRepository.push(names[num1 + "0"].value); 113 setScale = true; 114 } 115 if (num2 != "0") { 116 renderRepository.push(names[num2].value); 117 setScale = true; 118 } 119 } 120 return setScale; 121 } 122 123 function renderNumber(digit, renderRepository) { 124 var setScale = false; 125 if (digit.length > 2) { 126 if (digit.charAt(0) != "0") { 127 renderRepository.push(names[digit.charAt(0) + "00"].value); 128 setScale = true; 129 } 130 setScale = renderTwoLengthNumber(digit.charAt(1), digit.charAt(2), renderRepository, setScale); 131 } else if (digit.length > 1) { 132 setScale = renderTwoLengthNumber(digit.charAt(0), digit.charAt(1), renderRepository, setScale); 133 } else if (digit.length > 0) { 134 if (digit.charAt(0) != "0") { 135 renderRepository.push(names[digit.charAt(0)].value); 136 setScale = true; 137 } 138 } 139 return setScale; 140 } 141 142 function allowComman(txt) { 143 for(var key in names){ 144 if(names[key].value == txt){ 145 return !names[key].scale; 146 } 147 } 148 return true; 149 } 150 151 function pow(powNum) { 152 var pow = 1; 153 for (var j = 0; j < powNum; j++) { 154 pow = pow * 10; 155 } 156 return pow; 157 } 158 }); 159we should have a map with digit key and the value is the written version of the key. This map is for translation usage(line 13).
2.1 numberToLetter function (line 66)
This is the major function to handle the job. In line 67 we categorize every three digits near together into a category. This is the scales like thousand, million, billion, ... . parts in line 68 is an array of 3 digits. textParts in line 69 is the translated version of parts. renderNumber in line 71 will fill textParts(refer to 2.2). finally the textParts items should be joined together in line 77(refer to 2.4).2.2 renderNumber function (line 123)
This function renders the letter and fill it to the 'renderRepository' parameter. Then returns a boolean to say if the scale should be rendered or not. If 3 zeros are near to each other the scale should not be rendered. For example 324000122.
2.3 renderTwoLengthNumber function (line 106)
This function should render two digits (num1, num2). There is a lot of exceptions between 10-20 in Persian. So we should handle this in here(lines 107,108). This function also fill the rendered text into the 'renderRepository'.
2.4 concatNumberTexts function (line 85)
This function concats the 'renderRepository' parameter items(textParts variable in numberToLetter function) together and returns full text. In Persian we shouldn't put 'and' after scales. So we should handle it here(lines 91,92).
You can download the client sample from here.