| [5] | 1 | <!--- |
|---|
| 2 | Name : utils.cfc |
|---|
| 3 | Author : Paul Hastings, Raymond Camden |
|---|
| 4 | Created : October 29, 2003 |
|---|
| 5 | Last Updated : 11/30/06 (rkc) |
|---|
| 6 | - added more BIDI languages in isBIDI method, tracking CLDR changes |
|---|
| 7 | - cleaned up & fixed bugs in loadLocale where calendar, etc were init using server default locale |
|---|
| 8 | - added hacks to cover datetime varchar goop coming out of mysql (instead of datetime object) |
|---|
| 9 | - added getCurrentLocale() to show what locale is currently loaded |
|---|
| 10 | - added datetimeLocaleFormat() to format date/time |
|---|
| 11 | History : Two fixes for BD compat (rkc 10/12/06) |
|---|
| 12 | : Java to cf locale mapping, thanks Tom J @ Adobe (rkc 10/30/06) |
|---|
| 13 | Purpose : Locale utils. Lots of help from Paul Hastings. Basically, since CF's locale funcs |
|---|
| 14 | don't accept Java locales, I wrote these functions instead. |
|---|
| 15 | |
|---|
| 16 | Most of these methods operate on the current locale. |
|---|
| 17 | |
|---|
| 18 | To Do - handle converting from UTC to local time, modded by user pref TZ |
|---|
| 19 | ---> |
|---|
| 20 | |
|---|
| 21 | <cfcomponent displayName="Utils" output="false"> |
|---|
| 22 | |
|---|
| 23 | <!--- Default locale ---> |
|---|
| 24 | <cfset loadLocale()> |
|---|
| 25 | |
|---|
| 26 | <cffunction name="dateLocaleFormat" access="public" returnType="string" output="false" |
|---|
| 27 | hint="locale version of dateFormat"> |
|---|
| 28 | <cfargument name="date" type="date" required="true"> |
|---|
| 29 | <cfargument name="style" type="string" required="false" default="LONG"> |
|---|
| 30 | <cfscript> |
|---|
| 31 | // hack to trap & fix varchar mystery goop coming out of mysql datetimes |
|---|
| 32 | try { |
|---|
| 33 | return variables.aDateFormat.getDateInstance(variables.aDateFormat[arguments.style],variables.thisLocale).format(arguments.date); |
|---|
| 34 | } |
|---|
| 35 | catch(Any e) { |
|---|
| 36 | variables.aCalendar.setTime(arguments.date); |
|---|
| 37 | return variables.aDateFormat.getDateInstance(variables.aDateFormat[arguments.style],variables.thisLocale).format(variables.aCalendar.getTime()); |
|---|
| 38 | } |
|---|
| 39 | </cfscript> |
|---|
| 40 | </cffunction> |
|---|
| 41 | |
|---|
| 42 | <cffunction name="getAvailableLocales" access="public" returnType="array" output="false" |
|---|
| 43 | hint="Returns an array of locales."> |
|---|
| 44 | <cfscript> |
|---|
| 45 | var i=0; |
|---|
| 46 | var theseLocales=arrayNew(1); |
|---|
| 47 | var orgLocales = ""; |
|---|
| 48 | |
|---|
| 49 | if ( server.coldfusion.productname eq "bluedragon" ) { |
|---|
| 50 | // this is only needed for BD.NET, but works for BD Java editions also |
|---|
| 51 | orgLocales=createObject("java","com.nary.util.Locales").getAvailableLocales(); |
|---|
| 52 | } else { |
|---|
| 53 | orgLocales=createObject("java","java.util.Locale").getAvailableLocales(); |
|---|
| 54 | } |
|---|
| 55 | |
|---|
| 56 | // we skip plain languages, en, fr, ar, etc. |
|---|
| 57 | for (i=1; i LTE arrayLen(orgLocales); i=i+1) { |
|---|
| 58 | if (listLen(orgLocales[i].toString(),"_") GT 1) { |
|---|
| 59 | arrayAppend(theseLocales,orgLocales[i].toString()); |
|---|
| 60 | } // if |
|---|
| 61 | } //for |
|---|
| 62 | return theseLocales; |
|---|
| 63 | </cfscript> |
|---|
| 64 | </cffunction> |
|---|
| 65 | |
|---|
| 66 | <cffunction name="getLocalizedDays" access="public" returnType="array" output="false" |
|---|
| 67 | hint="Returns localized days"> |
|---|
| 68 | <cfscript> |
|---|
| 69 | var localizedShortDays=""; |
|---|
| 70 | var i=0; |
|---|
| 71 | var tmp=variables.dateSymbols.getShortWeekdays(); |
|---|
| 72 | // kludge java returns NULL first element in array so can't use arrayDeleteAt |
|---|
| 73 | tmp=listToArray(arrayToList(tmp)); |
|---|
| 74 | // more kludge, fixup days to match week start |
|---|
| 75 | switch (weekStarts()) { |
|---|
| 76 | case 1: //starts on sunday, just return day names |
|---|
| 77 | localizedShortDays=tmp; |
|---|
| 78 | break; |
|---|
| 79 | |
|---|
| 80 | case 2: // euro dates, starts on monday needs kludge |
|---|
| 81 | localizedShortDays=arrayNew(1); |
|---|
| 82 | localizedShortDays[7]=tmp[1]; //move sunday to last |
|---|
| 83 | for (i=1; i LTE 6; i=i+1) { |
|---|
| 84 | localizedShortDays[i]=tmp[i+1]; |
|---|
| 85 | } |
|---|
| 86 | break; |
|---|
| 87 | |
|---|
| 88 | case 7: // starts saturday, usually arabic, needs kludge |
|---|
| 89 | localizedShortDays=arrayNew(1); |
|---|
| 90 | localizedShortDays[1]=tmp[7]; //move saturday to first |
|---|
| 91 | for (i=1; i LTE 6; i=i+1) { |
|---|
| 92 | localizedShortDays[i+1]=tmp[i]; |
|---|
| 93 | } |
|---|
| 94 | break; |
|---|
| 95 | } |
|---|
| 96 | return localizedShortDays; |
|---|
| 97 | </cfscript> |
|---|
| 98 | </cffunction> |
|---|
| 99 | |
|---|
| 100 | <cffunction name="getLocalizedMonth" access="public" returnType="string" output="false" |
|---|
| 101 | hint="Returns localized month"> |
|---|
| 102 | <cfargument name="month" type="numeric" required="true"> |
|---|
| 103 | <cfscript> |
|---|
| 104 | variables.sDateFormat.init("MMMM",variables.thisLocale); |
|---|
| 105 | return variables.sDateFormat.format(createDate(1999,arguments.month,1)); |
|---|
| 106 | </cfscript> |
|---|
| 107 | |
|---|
| 108 | </cffunction> |
|---|
| 109 | |
|---|
| 110 | <cffunction name="getLocalizedName" access="public" returnType="string" output="false" |
|---|
| 111 | hint="Returns current locale name"> |
|---|
| 112 | <cfreturn variables.localeName> |
|---|
| 113 | </cffunction> |
|---|
| 114 | |
|---|
| 115 | <cffunction name="getCurrentLocale" access="public" returnType="string" output="false" |
|---|
| 116 | hint="Returns current locale"> |
|---|
| 117 | <cfreturn variables.thisLocale> |
|---|
| 118 | </cffunction> |
|---|
| 119 | |
|---|
| 120 | <cffunction name="getLocalizedYear" access="public" returnType="string" output="false" |
|---|
| 121 | hint="Returns localized year, probably only useful for BE calendars like in thailand, etc."> |
|---|
| 122 | <cfargument name="thisYear" type="numeric" required="true"> |
|---|
| 123 | <cfscript> |
|---|
| 124 | variables.sDateFormat.init("yyyy",variables.thisLocale); |
|---|
| 125 | return variables.sDateFormat.init("yyyy",variables.thisLocale).format(createDate(arguments.thisYear,1,1)); |
|---|
| 126 | </cfscript> |
|---|
| 127 | </cffunction> |
|---|
| 128 | |
|---|
| 129 | <cffunction name="isBIDI" access="public" returnType="boolean" output="false"> |
|---|
| 130 | <cfreturn listFind(variables.BIDILanguages,variables.lang)> |
|---|
| 131 | </cffunction> |
|---|
| 132 | |
|---|
| 133 | <cffunction name="loadLocale" access="public" returnType="void" output="false" |
|---|
| 134 | hint="Loads a locale."> |
|---|
| 135 | <cfargument name="locale" type="string" default="en_US" required="false"> |
|---|
| 136 | |
|---|
| 137 | <cfif NOT isValidLocale(arguments.locale)> |
|---|
| 138 | <cfthrow message="Invalid locale specified."> |
|---|
| 139 | <cfelseif not listLen(arguments.locale,"_") is 2 or |
|---|
| 140 | not len(listFirst(arguments.locale,"_")) is 2 or |
|---|
| 141 | not len(listLast(arguments.locale,"_")) is 2> |
|---|
| 142 | <cfthrow message="Specified locale must be of the form language_country where language and country are 2 characters each, en_US, fr_FR, etc."> |
|---|
| 143 | </cfif> |
|---|
| 144 | |
|---|
| 145 | <cfset variables.lang = listFirst(arguments.locale,"_")> |
|---|
| 146 | <cfset variables.country = listLast(arguments.locale,"_")> |
|---|
| 147 | |
|---|
| 148 | <cfset variables.BIDIlanguages="ar,he,fa,ps"><!--- couple more BIDI writing systems ---> |
|---|
| 149 | <cfset variables.thisLocale=createObject("java","java.util.Locale").init(variables.lang, variables.country)> |
|---|
| 150 | <cfset variables.localeName=variables.thisLocale.getDisplayName(variables.thisLocale)> |
|---|
| 151 | <cfset variables.aDateFormat=createObject("java","java.text.DateFormat")> |
|---|
| 152 | <cfset variables.sDateFormat=createObject("java","java.text.SimpleDateFormat")> |
|---|
| 153 | <cfset variables.aCalendar=createObject("java","java.util.GregorianCalendar").init(variables.thisLocale)> |
|---|
| 154 | <cfset variables.dateSymbols=createObject("java","java.text.DateFormatSymbols").init(variables.thisLocale)> |
|---|
| 155 | </cffunction> |
|---|
| 156 | |
|---|
| 157 | <cffunction name="timeLocaleFormat" access="public" returnType="string" output="false" |
|---|
| 158 | hint="locale version of timeFormat"> |
|---|
| 159 | <cfargument name="date" type="date" required="true"> |
|---|
| 160 | <cfargument name="style" type="string" required="false" default="SHORT"> |
|---|
| 161 | <cfscript> |
|---|
| 162 | // hack to trap & fix varchar mystery goop coming out of mysql datetimes |
|---|
| 163 | try { |
|---|
| 164 | return variables.aDateFormat.getTimeInstance(variables.aDateFormat[arguments.style],variables.thisLocale).format(arguments.date); |
|---|
| 165 | } |
|---|
| 166 | catch (Any e) { |
|---|
| 167 | variables.aCalendar.setTime(arguments.date); |
|---|
| 168 | return variables.aDateFormat.getTimeInstance(variables.aDateFormat[arguments.style],variables.thisLocale).format(variables.aCalendar.getTime()); |
|---|
| 169 | } |
|---|
| 170 | </cfscript> |
|---|
| 171 | </cffunction> |
|---|
| 172 | |
|---|
| 173 | <cffunction name="datetimeLocaleFormat" access="public" returnType="string" output="false" |
|---|
| 174 | hint="locale date/time format"> |
|---|
| 175 | <cfargument name="date" type="date" required="true"> |
|---|
| 176 | <cfargument name="dateStyle" type="string" required="false" default="SHORT"> |
|---|
| 177 | <cfargument name="timeStyle" type="string" required="false" default="SHORT"> |
|---|
| 178 | <cfscript> |
|---|
| 179 | // hack to trap & fix varchar mystery goop coming out of mysql datetimes |
|---|
| 180 | try { |
|---|
| 181 | return variables.aDateFormat.getDateTimeInstance(variables.aDateFormat[arguments.dateStyle],variables.aDateFormat[arguments.timeStyle],variables.thisLocale).format(arguments.date); |
|---|
| 182 | } |
|---|
| 183 | catch (Any e) { |
|---|
| 184 | variables.aCalendar.setTime(arguments.date); |
|---|
| 185 | return variables.aDateFormat.getDateTimeInstance(variables.aDateFormat[arguments.dateStyle],variables.aDateFormat[arguments.timeStyle],variables.thisLocale).format(variables.aCalendar.getTime()); |
|---|
| 186 | } |
|---|
| 187 | </cfscript> |
|---|
| 188 | </cffunction> |
|---|
| 189 | |
|---|
| 190 | <cffunction name="isValidLocale" access="public" returnType="boolean" output="false"> |
|---|
| 191 | <cfargument name="thisLocale" type="string" required="true"> |
|---|
| 192 | <cfscript> |
|---|
| 193 | var locales=arrayToList(getAvailableLocales()); |
|---|
| 194 | return listFind(locales,arguments.thisLocale) gte 1; |
|---|
| 195 | </cfscript> |
|---|
| 196 | </cffunction> |
|---|
| 197 | |
|---|
| 198 | |
|---|
| 199 | <cffunction name="weekStarts" access="public" returnType="string" output="false" |
|---|
| 200 | hint="Determines the first DOW"> |
|---|
| 201 | <cfscript> |
|---|
| 202 | return variables.aCalendar.getFirstDayOfWeek(); |
|---|
| 203 | </cfscript> |
|---|
| 204 | </cffunction> |
|---|
| 205 | |
|---|
| 206 | <cffunction name="java2CF" access="public" returnType="string" output="false" hint="Switches Java locale to CF locale (for CF6)"> |
|---|
| 207 | <cfargument name="javalocale" type="string" required="false" default="#variables.lang#_#variables.country#"> |
|---|
| 208 | |
|---|
| 209 | <cfswitch expression="#arguments.javalocale#"> |
|---|
| 210 | |
|---|
| 211 | <cfcase value="nl_BE"> |
|---|
| 212 | <cfreturn "Dutch (Belgian)"> |
|---|
| 213 | </cfcase> |
|---|
| 214 | |
|---|
| 215 | <cfcase value="nl_NK"> |
|---|
| 216 | <cfreturn "Dutch (Standard)"> |
|---|
| 217 | </cfcase> |
|---|
| 218 | |
|---|
| 219 | <cfcase value="en_AU"> |
|---|
| 220 | <cfreturn "English (Australian)"> |
|---|
| 221 | </cfcase> |
|---|
| 222 | |
|---|
| 223 | <cfcase value="en_CA"> |
|---|
| 224 | <cfreturn "English (Canadian)"> |
|---|
| 225 | </cfcase> |
|---|
| 226 | |
|---|
| 227 | <cfcase value="en_GB"> |
|---|
| 228 | <cfreturn "English (UK)"> |
|---|
| 229 | </cfcase> |
|---|
| 230 | |
|---|
| 231 | <cfcase value="en_NZ"> |
|---|
| 232 | <cfreturn "English (New Zealand)"> |
|---|
| 233 | </cfcase> |
|---|
| 234 | |
|---|
| 235 | <cfcase value="en_US"> |
|---|
| 236 | <cfreturn "English (US)"> |
|---|
| 237 | </cfcase> |
|---|
| 238 | |
|---|
| 239 | <cfdefaultcase> |
|---|
| 240 | <cfreturn "English (US)"> |
|---|
| 241 | </cfdefaultcase> |
|---|
| 242 | |
|---|
| 243 | <cfcase value="fr_BE"> |
|---|
| 244 | <cfreturn "French (Belgian)"> |
|---|
| 245 | </cfcase> |
|---|
| 246 | |
|---|
| 247 | <cfcase value="fr_CA"> |
|---|
| 248 | <cfreturn "French (Canadian)"> |
|---|
| 249 | </cfcase> |
|---|
| 250 | |
|---|
| 251 | <cfcase value="fr_FR"> |
|---|
| 252 | <cfreturn "French (Standard)"> |
|---|
| 253 | </cfcase> |
|---|
| 254 | |
|---|
| 255 | <cfcase value="fr_CH"> |
|---|
| 256 | <cfreturn "French (Swiss)"> |
|---|
| 257 | </cfcase> |
|---|
| 258 | |
|---|
| 259 | <cfcase value="de_AT"> |
|---|
| 260 | <cfreturn "German (Austrian)"> |
|---|
| 261 | </cfcase> |
|---|
| 262 | |
|---|
| 263 | <cfcase value="de_DE"> |
|---|
| 264 | <cfreturn "German (Standard)"> |
|---|
| 265 | </cfcase> |
|---|
| 266 | |
|---|
| 267 | <cfcase value="de_CH"> |
|---|
| 268 | <cfreturn "German (Swiss)"> |
|---|
| 269 | </cfcase> |
|---|
| 270 | |
|---|
| 271 | <cfcase value="it_IT"> |
|---|
| 272 | <cfreturn "Italian (Standard)"> |
|---|
| 273 | </cfcase> |
|---|
| 274 | |
|---|
| 275 | <cfcase value="it_CH"> |
|---|
| 276 | <cfreturn "Italian (Swiss)"> |
|---|
| 277 | </cfcase> |
|---|
| 278 | |
|---|
| 279 | <cfcase value="no_NO"> |
|---|
| 280 | <cfreturn "Norwegian (Bokmal)"> |
|---|
| 281 | </cfcase> |
|---|
| 282 | |
|---|
| 283 | <cfcase value="no_NO@nynorsk"> |
|---|
| 284 | <cfreturn "Norwegian (Nynorsk)"> |
|---|
| 285 | </cfcase> |
|---|
| 286 | |
|---|
| 287 | <cfcase value="pt_BR"> |
|---|
| 288 | <cfreturn "Portuguese (Brazilian)"> |
|---|
| 289 | </cfcase> |
|---|
| 290 | |
|---|
| 291 | <cfcase value="pt_PT"> |
|---|
| 292 | <cfreturn "Portuguese (Standard)"> |
|---|
| 293 | </cfcase> |
|---|
| 294 | |
|---|
| 295 | <cfcase value="es_MX"> |
|---|
| 296 | <cfreturn "Spanish (Mexican)"> |
|---|
| 297 | </cfcase> |
|---|
| 298 | |
|---|
| 299 | <!--- Only support Spanish Standard |
|---|
| 300 | <cfcase value="es_ES"> |
|---|
| 301 | <cfreturn "Spanish (Modern)"> |
|---|
| 302 | </cfcase> |
|---|
| 303 | ---> |
|---|
| 304 | <cfcase value="es_ES"> |
|---|
| 305 | <cfreturn "Spanish (Standard)"> |
|---|
| 306 | </cfcase> |
|---|
| 307 | |
|---|
| 308 | <cfcase value="sv_SE"> |
|---|
| 309 | <cfreturn "Swedish"> |
|---|
| 310 | </cfcase> |
|---|
| 311 | |
|---|
| 312 | <cfcase value="ja_JP"> |
|---|
| 313 | <cfreturn "Japanese"> |
|---|
| 314 | </cfcase> |
|---|
| 315 | |
|---|
| 316 | <cfcase value="ko_KR"> |
|---|
| 317 | <cfreturn "Korean"> |
|---|
| 318 | </cfcase> |
|---|
| 319 | |
|---|
| 320 | <cfcase value="zh_CN"> |
|---|
| 321 | <cfreturn "Chinese (China)"> |
|---|
| 322 | </cfcase> |
|---|
| 323 | |
|---|
| 324 | <cfcase value="zh_HK"> |
|---|
| 325 | <cfreturn "Chinese (Hong Kong)"> |
|---|
| 326 | </cfcase> |
|---|
| 327 | |
|---|
| 328 | <cfcase value="zh_TW"> |
|---|
| 329 | <cfreturn "Chinese (Taiwan)"> |
|---|
| 330 | </cfcase> |
|---|
| 331 | |
|---|
| 332 | </cfswitch> |
|---|
| 333 | </cffunction> |
|---|
| 334 | |
|---|
| 335 | </cfcomponent> |
|---|
| 336 | |
|---|