DEV Community

James Moberg
James Moberg

Posted on

1

Convert Numbers to Text using ColdFusion and ICU4J

(This is a repost from my abandoned tumblr blog; dated 2016-11-17)

A client requested that we spell out numbers on their website in order to clarify some financial totals.  I initially planned on using the ColdFusion NumberAsString UDF from 2002. After reviewing the results, I thought it was worth a unit test comparison to review the results against ICU4J (java).

In the end, I decided to use ICU4J because:

  • ICU4J converts text using 180+ locales. Numbers are translated to each language (Chinese, Thai, French, Spanish, etc)
  • UDF adds title case capitalization to all number strings. (if needed, you can do this separately.)
  • UDF doesn't support negative values and will throw a CF error.
  • UDF doesn't use hyphenized numbers ("Forty Three" versus "forty-three")
  • UDF uses "cardinal-verbose" format w/o hyphened numbers (Adds the word "and" where commas should be.)
  • UDF decimal places are treated as positive-type number words (instead of using "point four three" for ".43")
123 = "one hundred twenty-three"
100001 = "one hundred thousand one"
9 = "nine"
64578.25 = "sixty-four thousand five hundred seventy-eight point two five"
0.333 = "zero point three three three"
Enter fullscreen mode Exit fullscreen mode

Here's the CFML source code:
https://gist.github.com/JamoCA/cd343524e417f382d5c706954e52dfaf

<!--- 2016-11-17 SpellOutNumberUS UDF
Blog: https://dev.to/gamesover/convert-numbers-to-text-using-coldfusion-and-icu4j-33kn
Tweet: https://x.com/gamesover/status/1816618788944773584
Requires icu4j-55_1.jar from http://site.icu-project.org/home/why-use-icu4j (Copy to Java Path or use JavaLoader)
Number Formats (Availability determined based on locale)
%spellout-ordinal-verbose: one hundred and twenty-third
%spellout-ordinal: one hundred twenty-third
%spellout-cardinal-verbose: one hundred and twenty-three
%spellout-cardinal: one hundred twenty-three
%spellout-numbering-verbose: one hundred and twenty-three
%spellout-numbering: one hundred twenty-three
%spellout-numbering-year: one hundred twenty-three
Some locales may need <cfprocessingDirective pageencoding="utf-8"> and setLocale("LOCALE_CODE") in order to render
--->
<cfscript>
function spellOutNumberUS(myNumber){
var response = "unknown numeric value";
if (!StructKeyExists(Request, "spellOutUlocale")){
Request.spellOutUlocale = createObject("java","com.ibm.icu.util.ULocale");
Request.spellOutthisLocale = Request.spellOutUlocale.init("en_US");
Request.spellOutruleBased = createObject("java","com.ibm.icu.text.RuleBasedNumberFormat").init(Request.spellOutthisLocale, 1);
}
if (isNumeric(arguments.myNumber)){
if (int(arguments.myNumber) IS arguments.myNumber){
response = Request.spellOutruleBased.format(javacast("long", val(trim(arguments.myNumber))), "%spellout-numbering");
} else {
response = Request.spellOutruleBased.format(javacast("double", val(trim(arguments.myNumber))), "%spellout-numbering");
}
}
return response;
}
</cfscript>
<!--- Run some random number tests.
NOTE: I compared with NumberAsString UDF. http://cflib.org/udf/NumberAsString Some differences:
- ICU4J converts text using 180+ locales. Numbers are translated to each language (Chinese, Thai, French, Spanish, etc)
- UDF adds title case capitalization to all number strings. (if needed, you can do this separately.)
- UDF doesn't support negative values and will throw a CF error.
- UDF doesn't use hyphenized numbers ("Forty Three" versus "forty-three")
- UDF uses "cardinal-verbose" format w/o hyphened numbers (Adds the word "and" where commas should be.)
- UDF decimal places are treated as positive-type number words (instead of using "point four three" for ".43")
--->
<h1>ICU4J - Spell Out Numbers (US)</h1>
<ol>
<CFLOOP FROM="1" to="100" INDEX="thisNum">
<CFSET n = val(RandRange(1, 2147483646, "SHA1PRNG"))>
<CFSET NDec = 0>
<CFIF RandRange(1,2,"SHA1PRNG") eq 1>
<CFSET NDec = val(RandRange(0, 99, "SHA1PRNG")) / 100>
<CFSET N = N + NDec>
</CFIF>
<CFIF RandRange(1,2,"SHA1PRNG") eq 1>
<CFSET N = N * -1>
</CFIF>
<li><h3>#N# = <b>#DecimalFormat(N)#</b></h3><!---
UDF = <CFTRY>#NumberAsString(N)#<CFCATCH><b>ERROR - #CFCATCH.Message#</b></CFCATCH></CFTRY><br>--->
ICU4J = <CFTRY>#spellOutNumberUS(N)#<CFCATCH><b>ERROR - #CFCATCH.Message#</b></CFCATCH></CFTRY></li>
</CFLOOP>
</ol>
view raw SpellOutNumberUS.cfm hosted with ā¤ by GitHub

Do your career a big favor. Join DEV. (The website you're on right now)

It takes one minute, it's free, and is worth it for your career.

Get started

Community matters

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

šŸ‘‹ Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay