JavaScript setlocale
Set locale information
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 18 19 2021 22 23 24 2526 27 28 29 3031 32 33 34 3536 37 38 39 4041 42 43 44 4546 47 48 49 5051 52 53 54 5556 57 58 59 6061 62 63 64 6566 67 68 69 7071 72 73 74 7576 77 78 79 8081 82 83 84 8586 87 88 89 9091 92 93 94 9596 97 98 99 100101 102 103 104 105106 107 108 109 110111 112 113 114 115116 117 118 119 120121 122 123 124 125126 127 128 129 130131 132 133 134 135136 137 138 139 140141 142 143 144 145146 147 148 149 150151 152 153 154 155156 157 158 159 160161 162 163 164 165166 167 168 169 170171 172 173 174 175176 177 178 179 180181 182 183 184 185186 187 188 189 190191 192 193 194 195196 197 198 199 200201 202 203 204 205206 207 208 209 210211 212 213 214 215216 217 218 219 220221 222 223 224 225226 227 228 229 230231 232 233 234 235236 237 238 239 240241 242 243 244 245246 247 248 249 250251 252 253 254 255256 257 258 259 260261 262 263 264 265266 267 268 269 270271 272 273 274 275276 277 278 279 280281 282 283 284 285286 287 288 289 290291 292 293 294 295296 297 298 299 300301 302 303 304 305306 307 308 309 310311 312 313 314 315316 317 318 319 320321 | function setlocale (category, locale) { // Set locale information // // version: 1008.1718 // discuss at: http://phpjs.org/functions/setlocale // + original by: Brett Zamir (http://brett-zamir.me) // + derived from: Blues at http://hacks.bluesmoon.info/strftime/strftime.js // + derived from: YUI Library: http://developer.yahoo.com/yui/docs/YAHOO.util.DateLocale.html // - depends on: getenv // % note 1: Is extensible, but currently only implements locales en, // % note 1: en_US, en_GB, en_AU, fr, and fr_CA for LC_TIME only; C for LC_CTYPE; // % note 1: C and en for LC_MONETARY/LC_NUMERIC; en for LC_COLLATE // % note 2: Uses global: php_js to store locale info // % note 3: Consider using http://demo.icu-project.org/icu-bin/locexp as basis for localization (as in i18n_loc_set_default()) // * example 1: setlocale('LC_ALL', 'en_US'); // * returns 1: 'en_US' var categ = '', cats = [], i = 0, d = this.window.document; // BEGIN STATIC var _copy = function _copy (orig) { if (orig instanceof RegExp) { return new RegExp(orig); } else if (orig instanceof Date) { return new Date(orig); } var newObj = {}; for (var i in orig) { if (typeof orig[i] === 'object') { newObj[i] = _copy(orig[i]); } else { newObj[i] = orig[i]; } } return newObj; }; // Function usable by a ngettext implementation (apparently not an accessible part of setlocale(), but locale-specific) // See http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms though amended with others from // https://developer.mozilla.org/En/Localization_and_Plurals (new categories noted with "MDC" below, though // not sure of whether there is a convention for the relative order of these newer groups as far as ngettext) // The function name indicates the number of plural forms (nplural) // Need to look into http://cldr.unicode.org/ (maybe future JavaScript); Dojo has some functions (under new BSD), // including JSON conversions of LDML XML from CLDR: http://bugs.dojotoolkit.org/browser/dojo/trunk/cldr // and docs at http://api.dojotoolkit.org/jsdoc/HEAD/dojo.cldr var _nplurals1 = function (n) { // e.g., Japanese return 0; }; var _nplurals2a = function (n) { // e.g., English return n !== 1 ? 1 : 0; }; var _nplurals2b = function (n) { // e.g., French return n > 1 ? 1 : 0; }; var _nplurals2c = function (n) { // e.g., Icelandic (MDC) return n % 10 === 1 && n % 100 !== 11 ? 0 : 1; }; var _nplurals3a = function (n) { // e.g., Latvian (MDC has a different order from gettext) return n % 10 === 1 && n % 100 !== 11 ? 0 : n !== 0 ? 1 : 2; }; var _nplurals3b = function (n) { // e.g., Scottish Gaelic return n === 1 ? 0 : n === 2 ? 1 : 2; }; var _nplurals3c = function (n) { // e.g., Romanian return n === 1 ? 0 : (n === 0 || (n % 100 > 0 && n % 100 < 20)) ? 1 : 2; }; var _nplurals3d = function (n) { // e.g., Lithuanian (MDC has a different order from gettext) return n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && (n % 100 <10 || n % 100 >= 20) ? 1 : 2; }; var _nplurals3e = function (n) { // e.g., Croatian return n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >=2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2; }; var _nplurals3f = function (n) { // e.g., Slovak return n === 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2; }; var _nplurals3g = function (n) { // e.g., Polish return n === 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2; }; var _nplurals3h = function (n) { // e.g., Macedonian (MDC) return n % 10 === 1 ? 0 : n % 10 === 2 ? 1 : 2; }; var _nplurals4a = function (n) { // e.g., Slovenian return n % 100 === 1 ? 0 : n % 100 === 2 ? 1 : n % 100 === 3 || n % 100 === 4 ? 2 : 3; }; var _nplurals4b = function (n) { // e.g., Maltese (MDC) return n === 1 ? 0 : n === 0 || (n % 100 && n % 100 <= 10) ? 1 : n % 100 >= 11 && n % 100 <= 19 ? 2 : 3; }; var _nplurals5 = function (n) { // e.g., Irish Gaeilge (MDC) return n === 1 ? 0 : n === 2 ? 1 : n >=3 && n <= 6 ? 2 : n >= 7 && n <= 10 ? 3 : 4; }; var _nplurals6 = function (n) { // e.g., Arabic (MDC) - Per MDC puts 0 as last group return n === 0 ? 5 : n === 1 ? 0 : n === 2 ? 1 : n % 100 >= 3 && n % 100 <= 10 ? 2 : n % 100 >= 11 && n % 100 <= 99 ? 3 : 4; }; // END STATIC // BEGIN REDUNDANT this.php_js = this.php_js || {}; var phpjs = this.php_js; // Reconcile Windows vs. *nix locale names? // Allow different priority orders of languages, esp. if implement gettext as in // LANGUAGE env. var.? (e.g., show German if French is not available) if (!phpjs.locales) { // Can add to the locales phpjs.locales = {}; phpjs.locales.en = { 'LC_COLLATE' : // For strcoll function ( str1, str2 ) { // Fix: This one taken from strcmp, but need for other locales; we don't use localeCompare since its locale is not settable return ( str1 == str2 ) ? 0 : ( ( str1 > str2 ) ? 1 : -1 ); } , 'LC_CTYPE' : { // Need to change any of these for English as opposed to C? an: /^[A-Za-z\d]+$/g, al: /^[A-Za-z]+$/g, ct: /^[\u0000-\u001F\u007F]+$/g, dg: /^[\d]+$/g, gr: /^[\u0021-\u007E]+$/g, lw: /^[a-z]+$/g, pr: /^[\u0020-\u007E]+$/g, pu: /^[\u0021-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u007E]+$/g, sp: /^[\f\n\r\t\v ]+$/g, up: /^[A-Z]+$/g, xd: /^[A-Fa-f\d]+$/g, CODESET : 'UTF-8', // Used by sql_regcase lower : 'abcdefghijklmnopqrstuvwxyz', upper : 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' }, 'LC_TIME' : { // Comments include nl_langinfo() constant equivalents and any changes from Blues' implementation a: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // ABDAY_ A: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // DAY_ b: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // ABMON_ B: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], // MON_ c: '%a %d %b %Y %r %Z', // D_T_FMT // changed %T to %r per results p: ['AM', 'PM'], // AM_STR/PM_STR P: ['am', 'pm'], // Not available in nl_langinfo() r: '%I:%M:%S %p', // T_FMT_AMPM (Fixed for all locales) x: '%m/%d/%Y', // D_FMT // switched order of %m and %d; changed %y to %Y (C uses %y) X: '%r', // T_FMT // changed from %T to %r (%T is default for C, not English US) // Following are from nl_langinfo() or http://www.cptec.inpe.br/sx4/sx4man2/g1ab02e/strftime.4.html alt_digits : '', // e.g., ordinal ERA : '', ERA_YEAR : '', ERA_D_T_FMT : '', ERA_D_FMT : '', ERA_T_FMT : '' }, // Assuming distinction between numeric and monetary is thus: // See below for C locale 'LC_MONETARY' : { // Based on Windows "english" (English_United States.1252) locale int_curr_symbol : 'USD', currency_symbol : '$', mon_decimal_point : '.', mon_thousands_sep : ',', mon_grouping : [3], // use mon_thousands_sep; "" for no grouping; additional array members indicate successive group lengths after first group (e.g., if to be 1,23,456, could be [3, 2]) positive_sign : '', negative_sign : '-', int_frac_digits : 2, // Fractional digits only for money defaults? frac_digits : 2, p_cs_precedes : 1, // positive currency symbol follows value = 0; precedes value = 1 p_sep_by_space : 0, // 0: no space between curr. symbol and value; 1: space sep. them unless symb. and sign are adjacent then space sep. them from value; 2: space sep. sign and value unless symb. and sign are adjacent then space separates n_cs_precedes : 1, // see p_cs_precedes n_sep_by_space : 0, // see p_sep_by_space p_sign_posn : 3, // 0: parentheses surround quantity and curr. symbol; 1: sign precedes them; 2: sign follows them; 3: sign immed. precedes curr. symbol; 4: sign immed. succeeds curr. symbol n_sign_posn : 0 // see p_sign_posn }, 'LC_NUMERIC' : { // Based on Windows "english" (English_United States.1252) locale decimal_point : '.', thousands_sep : ',', grouping : [3] // see mon_grouping, but for non-monetary values (use thousands_sep) }, 'LC_MESSAGES' : { YESEXPR : '^[yY].*', NOEXPR : '^[nN].*', YESSTR : '', NOSTR : '' }, nplurals : _nplurals2a }; phpjs.locales.en_US = _copy(phpjs.locales.en); phpjs.locales.en_US.LC_TIME.c = '%a %d %b %Y %r %Z'; phpjs.locales.en_US.LC_TIME.x = '%D'; phpjs.locales.en_US.LC_TIME.X = '%r'; // The following are based on *nix settings phpjs.locales.en_US.LC_MONETARY.int_curr_symbol = 'USD '; phpjs.locales.en_US.LC_MONETARY.p_sign_posn = 1; phpjs.locales.en_US.LC_MONETARY.n_sign_posn = 1; phpjs.locales.en_US.LC_MONETARY.mon_grouping = [3, 3]; phpjs.locales.en_US.LC_NUMERIC.thousands_sep = ''; phpjs.locales.en_US.LC_NUMERIC.grouping = []; phpjs.locales.en_GB = _copy(phpjs.locales.en); phpjs.locales.en_GB.LC_TIME.r = '%l:%M:%S %P %Z'; phpjs.locales.en_AU = _copy(phpjs.locales.en_GB); phpjs.locales.C = _copy(phpjs.locales.en); // Assume C locale is like English (?) (We need C locale for LC_CTYPE) phpjs.locales.C.LC_CTYPE.CODESET = 'ANSI_X3.4-1968'; phpjs.locales.C.LC_MONETARY = { int_curr_symbol : '', currency_symbol : '', mon_decimal_point : '', mon_thousands_sep : '', mon_grouping : [], p_cs_precedes : 127, p_sep_by_space : 127, n_cs_precedes : 127, n_sep_by_space : 127, p_sign_posn : 127, n_sign_posn : 127, positive_sign : '', negative_sign : '', int_frac_digits : 127, frac_digits : 127 }; phpjs.locales.C.LC_NUMERIC = { decimal_point : '.', thousands_sep : '', grouping : [] }; phpjs.locales.C.LC_TIME.c = '%a %b %e %H:%M:%S %Y'; // D_T_FMT phpjs.locales.C.LC_TIME.x = '%m/%d/%y'; // D_FMT phpjs.locales.C.LC_TIME.X = '%H:%M:%S'; // T_FMT phpjs.locales.C.LC_MESSAGES.YESEXPR = '^[yY]'; phpjs.locales.C.LC_MESSAGES.NOEXPR = '^[nN]'; phpjs.locales.fr =_copy(phpjs.locales.en); phpjs.locales.fr.nplurals = _nplurals2b; phpjs.locales.fr.LC_TIME.a = ['dim', 'lun', 'mar', 'mer', 'jeu', 'ven', 'sam']; phpjs.locales.fr.LC_TIME.A = ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi']; phpjs.locales.fr.LC_TIME.b = ['jan', 'f\u00E9v', 'mar', 'avr', 'mai', 'jun', 'jui', 'ao\u00FB', 'sep', 'oct', 'nov', 'd\u00E9c']; phpjs.locales.fr.LC_TIME.B = ['janvier', 'f\u00E9vrier', 'mars', 'avril', 'mai', 'juin', 'juillet', 'ao\u00FBt', 'septembre', 'octobre', 'novembre', 'd\u00E9cembre']; phpjs.locales.fr.LC_TIME.c = '%a %d %b %Y %T %Z'; phpjs.locales.fr.LC_TIME.p = ['', '']; phpjs.locales.fr.LC_TIME.P = ['', '']; phpjs.locales.fr.LC_TIME.x = '%d.%m.%Y'; phpjs.locales.fr.LC_TIME.X = '%T'; phpjs.locales.fr_CA = _copy(phpjs.locales.fr); phpjs.locales.fr_CA.LC_TIME.x = '%Y-%m-%d'; } if (!phpjs.locale) { phpjs.locale = 'en_US'; var NS_XHTML = 'http://www.w3.org/1999/xhtml'; var NS_XML = 'http://www.w3.org/XML/1998/namespace'; if (d.getElementsByTagNameNS && d.getElementsByTagNameNS(NS_XHTML, 'html')[0]) { if (d.getElementsByTagNameNS(NS_XHTML, 'html')[0].getAttributeNS && d.getElementsByTagNameNS(NS_XHTML, 'html')[0].getAttributeNS(NS_XML, 'lang')) { phpjs.locale = d.getElementsByTagName(NS_XHTML, 'html')[0].getAttributeNS(NS_XML, 'lang'); } else if (d.getElementsByTagNameNS(NS_XHTML, 'html')[0].lang) { // XHTML 1.0 only phpjs.locale = d.getElementsByTagNameNS(NS_XHTML, 'html')[0].lang; } } else if (d.getElementsByTagName('html')[0] && d.getElementsByTagName('html')[0].lang) { phpjs.locale = d.getElementsByTagName('html')[0].lang; } } phpjs.locale = phpjs.locale.replace('-', '_'); // PHP-style // Fix locale if declared locale hasn't been defined if (!(phpjs.locale in phpjs.locales)) { if (phpjs.locale.replace(/_[a-zA-Z]+$/, '') in phpjs.locales) { phpjs.locale = phpjs.locale.replace(/_[a-zA-Z]+$/, ''); } } if (!phpjs.localeCategories) { phpjs.localeCategories = { 'LC_COLLATE': phpjs.locale, // for string comparison, see strcoll() 'LC_CTYPE': phpjs.locale,// for character classification and conversion, for example strtoupper() 'LC_MONETARY': phpjs.locale,// for localeconv() 'LC_NUMERIC': phpjs.locale,// for decimal separator (See also localeconv()) 'LC_TIME': phpjs.locale,// for date and time formatting with strftime() 'LC_MESSAGES':phpjs.locale// for system responses (available if PHP was compiled with libintl) }; } // END REDUNDANT if (locale === null || locale === '') { locale = this.getenv(category) || this.getenv('LANG'); } else if (locale instanceof Array) { for (i=0; i < locale.length; i++) { if (!(locale[i] in this.php_js.locales)) { if (i === locale.length-1) { return false; // none found } continue; } locale = locale[i]; break; } } // Just get the locale if (locale === '0' || locale === 0) { if (category === 'LC_ALL') { for (categ in this.php_js.localeCategories) { cats.push(categ+'='+this.php_js.localeCategories[categ]); // Add ".UTF-8" or allow ".@latint", etc. to the end? } return cats.join(';'); } return this.php_js.localeCategories[category]; } if (!(locale in this.php_js.locales)) { return false; // Locale not found } // Set and get locale if (category === 'LC_ALL') { for (categ in this.php_js.localeCategories) { this.php_js.localeCategories[categ] = locale; } } else { this.php_js.localeCategories[category] = locale; } return locale;} |
Examples
Running
1 | setlocale('LC_ALL', 'en_US'); |
Should return
1 | 'en_US' |
Dependencies
In order to use this function, you also need:
Open syntax issues
php.js uses JsLint to help us keep our code consistent and prevent some common bugs.
Eventually we want all code to pass or at least take into consideration most fixes suggested by JsLint, following this JsLint configuration we’ve decided on.
Authors
Thanks to the following developers, you get to have setlocale goodness in JavaScript.
No comments yet. Be the first!
spread the word:
Use any PHP function in JavaScript
These kind folks have already donated: @HalfWinter, Paulo Freitas, Andros Peña Romo, Nitin Gupta, @nikosdion, Anonymous, Anonymous and Shawn Houser.
<your name here>