PageRenderTime 48ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/functions/strings/setlocale.js

https://gitlab.com/orvi2014/phpjs
JavaScript | 380 lines | 276 code | 15 blank | 89 comment | 61 complexity | 8bdae6a6b08f39e04ce71d6e8ed988ad MD5 | raw file
  1. function setlocale(category, locale) {
  2. // discuss at: http://phpjs.org/functions/setlocale/
  3. // original by: Brett Zamir (http://brett-zamir.me)
  4. // original by: Blues at http://hacks.bluesmoon.info/strftime/strftime.js
  5. // original by: YUI Library: http://developer.yahoo.com/yui/docs/YAHOO.util.DateLocale.html
  6. // depends on: getenv
  7. // note: Is extensible, but currently only implements locales en,
  8. // note: en_US, en_GB, en_AU, fr, and fr_CA for LC_TIME only; C for LC_CTYPE;
  9. // note: C and en for LC_MONETARY/LC_NUMERIC; en for LC_COLLATE
  10. // note: Uses global: php_js to store locale info
  11. // note: Consider using http://demo.icu-project.org/icu-bin/locexp as basis for localization (as in i18n_loc_set_default())
  12. // example 1: setlocale('LC_ALL', 'en_US');
  13. // returns 1: 'en_US'
  14. var categ = '',
  15. cats = [],
  16. i = 0,
  17. d = this.window.document;
  18. // BEGIN STATIC
  19. var _copy = function _copy(orig) {
  20. if (orig instanceof RegExp) {
  21. return new RegExp(orig);
  22. } else if (orig instanceof Date) {
  23. return new Date(orig);
  24. }
  25. var newObj = {};
  26. for (var i in orig) {
  27. if (typeof orig[i] === 'object') {
  28. newObj[i] = _copy(orig[i]);
  29. } else {
  30. newObj[i] = orig[i];
  31. }
  32. }
  33. return newObj;
  34. };
  35. // Function usable by a ngettext implementation (apparently not an accessible part of setlocale(), but locale-specific)
  36. // See http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms though amended with others from
  37. // https://developer.mozilla.org/En/Localization_and_Plurals (new categories noted with "MDC" below, though
  38. // not sure of whether there is a convention for the relative order of these newer groups as far as ngettext)
  39. // The function name indicates the number of plural forms (nplural)
  40. // Need to look into http://cldr.unicode.org/ (maybe future JavaScript); Dojo has some functions (under new BSD),
  41. // including JSON conversions of LDML XML from CLDR: http://bugs.dojotoolkit.org/browser/dojo/trunk/cldr
  42. // and docs at http://api.dojotoolkit.org/jsdoc/HEAD/dojo.cldr
  43. var _nplurals1 = function(n) {
  44. // e.g., Japanese
  45. return 0;
  46. };
  47. var _nplurals2a = function(n) {
  48. // e.g., English
  49. return n !== 1 ? 1 : 0;
  50. };
  51. var _nplurals2b = function(n) {
  52. // e.g., French
  53. return n > 1 ? 1 : 0;
  54. };
  55. var _nplurals2c = function(n) {
  56. // e.g., Icelandic (MDC)
  57. return n % 10 === 1 && n % 100 !== 11 ? 0 : 1;
  58. };
  59. var _nplurals3a = function(n) {
  60. // e.g., Latvian (MDC has a different order from gettext)
  61. return n % 10 === 1 && n % 100 !== 11 ? 0 : n !== 0 ? 1 : 2;
  62. };
  63. var _nplurals3b = function(n) {
  64. // e.g., Scottish Gaelic
  65. return n === 1 ? 0 : n === 2 ? 1 : 2;
  66. };
  67. var _nplurals3c = function(n) {
  68. // e.g., Romanian
  69. return n === 1 ? 0 : (n === 0 || (n % 100 > 0 && n % 100 < 20)) ? 1 : 2;
  70. };
  71. var _nplurals3d = function(n) {
  72. // e.g., Lithuanian (MDC has a different order from gettext)
  73. return n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
  74. };
  75. var _nplurals3e = function(n) {
  76. // e.g., Croatian
  77. return n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 :
  78. 2;
  79. };
  80. var _nplurals3f = function(n) {
  81. // e.g., Slovak
  82. return n === 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2;
  83. };
  84. var _nplurals3g = function(n) {
  85. // e.g., Polish
  86. return n === 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
  87. };
  88. var _nplurals3h = function(n) {
  89. // e.g., Macedonian (MDC)
  90. return n % 10 === 1 ? 0 : n % 10 === 2 ? 1 : 2;
  91. };
  92. var _nplurals4a = function(n) {
  93. // e.g., Slovenian
  94. return n % 100 === 1 ? 0 : n % 100 === 2 ? 1 : n % 100 === 3 || n % 100 === 4 ? 2 : 3;
  95. };
  96. var _nplurals4b = function(n) {
  97. // e.g., Maltese (MDC)
  98. return n === 1 ? 0 : n === 0 || (n % 100 && n % 100 <= 10) ? 1 : n % 100 >= 11 && n % 100 <= 19 ? 2 : 3;
  99. };
  100. var _nplurals5 = function(n) {
  101. // e.g., Irish Gaeilge (MDC)
  102. return n === 1 ? 0 : n === 2 ? 1 : n >= 3 && n <= 6 ? 2 : n >= 7 && n <= 10 ? 3 : 4;
  103. };
  104. var _nplurals6 = function(n) {
  105. // e.g., Arabic (MDC) - Per MDC puts 0 as last group
  106. return n === 0 ? 5 : n === 1 ? 0 : n === 2 ? 1 : n % 100 >= 3 && n % 100 <= 10 ? 2 : n % 100 >= 11 && n % 100 <=
  107. 99 ? 3 : 4;
  108. };
  109. // END STATIC
  110. // BEGIN REDUNDANT
  111. try {
  112. this.php_js = this.php_js || {};
  113. } catch (e) {
  114. this.php_js = {};
  115. }
  116. var phpjs = this.php_js;
  117. // Reconcile Windows vs. *nix locale names?
  118. // Allow different priority orders of languages, esp. if implement gettext as in
  119. // LANGUAGE env. var.? (e.g., show German if French is not available)
  120. if (!phpjs.locales) {
  121. // Can add to the locales
  122. phpjs.locales = {};
  123. phpjs.locales.en = {
  124. 'LC_COLLATE' : // For strcoll
  125. function(str1, str2) {
  126. // Fix: This one taken from strcmp, but need for other locales; we don't use localeCompare since its locale is not settable
  127. return (str1 == str2) ? 0 : ((str1 > str2) ? 1 : -1);
  128. },
  129. 'LC_CTYPE' : {
  130. // Need to change any of these for English as opposed to C?
  131. an : /^[A-Za-z\d]+$/g,
  132. al : /^[A-Za-z]+$/g,
  133. ct : /^[\u0000-\u001F\u007F]+$/g,
  134. dg : /^[\d]+$/g,
  135. gr : /^[\u0021-\u007E]+$/g,
  136. lw : /^[a-z]+$/g,
  137. pr : /^[\u0020-\u007E]+$/g,
  138. pu : /^[\u0021-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u007E]+$/g,
  139. sp : /^[\f\n\r\t\v ]+$/g,
  140. up : /^[A-Z]+$/g,
  141. xd : /^[A-Fa-f\d]+$/g,
  142. CODESET : 'UTF-8',
  143. // Used by sql_regcase
  144. lower : 'abcdefghijklmnopqrstuvwxyz',
  145. upper : 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  146. },
  147. 'LC_TIME' : {
  148. // Comments include nl_langinfo() constant equivalents and any changes from Blues' implementation
  149. a : ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
  150. // ABDAY_
  151. A : ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
  152. // DAY_
  153. b : ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
  154. // ABMON_
  155. B : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October',
  156. 'November', 'December'
  157. ],
  158. // MON_
  159. c : '%a %d %b %Y %r %Z',
  160. // D_T_FMT // changed %T to %r per results
  161. p : ['AM', 'PM'],
  162. // AM_STR/PM_STR
  163. P : ['am', 'pm'],
  164. // Not available in nl_langinfo()
  165. r : '%I:%M:%S %p',
  166. // T_FMT_AMPM (Fixed for all locales)
  167. x : '%m/%d/%Y',
  168. // D_FMT // switched order of %m and %d; changed %y to %Y (C uses %y)
  169. X : '%r',
  170. // T_FMT // changed from %T to %r (%T is default for C, not English US)
  171. // Following are from nl_langinfo() or http://www.cptec.inpe.br/sx4/sx4man2/g1ab02e/strftime.4.html
  172. alt_digits : '',
  173. // e.g., ordinal
  174. ERA : '',
  175. ERA_YEAR : '',
  176. ERA_D_T_FMT : '',
  177. ERA_D_FMT : '',
  178. ERA_T_FMT : ''
  179. },
  180. // Assuming distinction between numeric and monetary is thus:
  181. // See below for C locale
  182. 'LC_MONETARY' : {
  183. // based on Windows "english" (English_United States.1252) locale
  184. int_curr_symbol : 'USD',
  185. currency_symbol : '$',
  186. mon_decimal_point : '.',
  187. mon_thousands_sep : ',',
  188. mon_grouping : [3],
  189. // 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])
  190. positive_sign : '',
  191. negative_sign : '-',
  192. int_frac_digits : 2,
  193. // Fractional digits only for money defaults?
  194. frac_digits : 2,
  195. p_cs_precedes : 1,
  196. // positive currency symbol follows value = 0; precedes value = 1
  197. p_sep_by_space : 0,
  198. // 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
  199. n_cs_precedes : 1,
  200. // see p_cs_precedes
  201. n_sep_by_space : 0,
  202. // see p_sep_by_space
  203. p_sign_posn : 3,
  204. // 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
  205. n_sign_posn : 0 // see p_sign_posn
  206. },
  207. 'LC_NUMERIC' : {
  208. // based on Windows "english" (English_United States.1252) locale
  209. decimal_point : '.',
  210. thousands_sep : ',',
  211. grouping : [3] // see mon_grouping, but for non-monetary values (use thousands_sep)
  212. },
  213. 'LC_MESSAGES' : {
  214. YESEXPR : '^[yY].*',
  215. NOEXPR : '^[nN].*',
  216. YESSTR : '',
  217. NOSTR : ''
  218. },
  219. nplurals : _nplurals2a
  220. };
  221. phpjs.locales.en_US = _copy(phpjs.locales.en);
  222. phpjs.locales.en_US.LC_TIME.c = '%a %d %b %Y %r %Z';
  223. phpjs.locales.en_US.LC_TIME.x = '%D';
  224. phpjs.locales.en_US.LC_TIME.X = '%r';
  225. // The following are based on *nix settings
  226. phpjs.locales.en_US.LC_MONETARY.int_curr_symbol = 'USD ';
  227. phpjs.locales.en_US.LC_MONETARY.p_sign_posn = 1;
  228. phpjs.locales.en_US.LC_MONETARY.n_sign_posn = 1;
  229. phpjs.locales.en_US.LC_MONETARY.mon_grouping = [3, 3];
  230. phpjs.locales.en_US.LC_NUMERIC.thousands_sep = '';
  231. phpjs.locales.en_US.LC_NUMERIC.grouping = [];
  232. phpjs.locales.en_GB = _copy(phpjs.locales.en);
  233. phpjs.locales.en_GB.LC_TIME.r = '%l:%M:%S %P %Z';
  234. phpjs.locales.en_AU = _copy(phpjs.locales.en_GB);
  235. // Assume C locale is like English (?) (We need C locale for LC_CTYPE)
  236. phpjs.locales.C = _copy(phpjs.locales.en);
  237. phpjs.locales.C.LC_CTYPE.CODESET = 'ANSI_X3.4-1968';
  238. phpjs.locales.C.LC_MONETARY = {
  239. int_curr_symbol : '',
  240. currency_symbol : '',
  241. mon_decimal_point : '',
  242. mon_thousands_sep : '',
  243. mon_grouping : [],
  244. p_cs_precedes : 127,
  245. p_sep_by_space : 127,
  246. n_cs_precedes : 127,
  247. n_sep_by_space : 127,
  248. p_sign_posn : 127,
  249. n_sign_posn : 127,
  250. positive_sign : '',
  251. negative_sign : '',
  252. int_frac_digits : 127,
  253. frac_digits : 127
  254. };
  255. phpjs.locales.C.LC_NUMERIC = {
  256. decimal_point : '.',
  257. thousands_sep : '',
  258. grouping : []
  259. };
  260. // D_T_FMT
  261. phpjs.locales.C.LC_TIME.c = '%a %b %e %H:%M:%S %Y';
  262. // D_FMT
  263. phpjs.locales.C.LC_TIME.x = '%m/%d/%y';
  264. // T_FMT
  265. phpjs.locales.C.LC_TIME.X = '%H:%M:%S';
  266. phpjs.locales.C.LC_MESSAGES.YESEXPR = '^[yY]';
  267. phpjs.locales.C.LC_MESSAGES.NOEXPR = '^[nN]';
  268. phpjs.locales.fr = _copy(phpjs.locales.en);
  269. phpjs.locales.fr.nplurals = _nplurals2b;
  270. phpjs.locales.fr.LC_TIME.a = ['dim', 'lun', 'mar', 'mer', 'jeu', 'ven', 'sam'];
  271. phpjs.locales.fr.LC_TIME.A = ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'];
  272. phpjs.locales.fr.LC_TIME.b = ['jan', 'f\u00E9v', 'mar', 'avr', 'mai', 'jun', 'jui', 'ao\u00FB', 'sep', 'oct',
  273. 'nov', 'd\u00E9c'
  274. ];
  275. phpjs.locales.fr.LC_TIME.B = ['janvier', 'f\u00E9vrier', 'mars', 'avril', 'mai', 'juin', 'juillet', 'ao\u00FBt',
  276. 'septembre', 'octobre', 'novembre', 'd\u00E9cembre'
  277. ];
  278. phpjs.locales.fr.LC_TIME.c = '%a %d %b %Y %T %Z';
  279. phpjs.locales.fr.LC_TIME.p = ['', ''];
  280. phpjs.locales.fr.LC_TIME.P = ['', ''];
  281. phpjs.locales.fr.LC_TIME.x = '%d.%m.%Y';
  282. phpjs.locales.fr.LC_TIME.X = '%T';
  283. phpjs.locales.fr_CA = _copy(phpjs.locales.fr);
  284. phpjs.locales.fr_CA.LC_TIME.x = '%Y-%m-%d';
  285. }
  286. if (!phpjs.locale) {
  287. phpjs.locale = 'en_US';
  288. var NS_XHTML = 'http://www.w3.org/1999/xhtml';
  289. var NS_XML = 'http://www.w3.org/XML/1998/namespace';
  290. if (d.getElementsByTagNameNS && d.getElementsByTagNameNS(NS_XHTML, 'html')[0]) {
  291. if (d.getElementsByTagNameNS(NS_XHTML, 'html')[0].getAttributeNS && d.getElementsByTagNameNS(NS_XHTML,
  292. 'html')[0].getAttributeNS(NS_XML, 'lang')) {
  293. phpjs.locale = d.getElementsByTagName(NS_XHTML, 'html')[0].getAttributeNS(NS_XML, 'lang');
  294. } else if (d.getElementsByTagNameNS(NS_XHTML, 'html')[0].lang) {
  295. // XHTML 1.0 only
  296. phpjs.locale = d.getElementsByTagNameNS(NS_XHTML, 'html')[0].lang;
  297. }
  298. } else if (d.getElementsByTagName('html')[0] && d.getElementsByTagName('html')[0].lang) {
  299. phpjs.locale = d.getElementsByTagName('html')[0].lang;
  300. }
  301. }
  302. // PHP-style
  303. phpjs.locale = phpjs.locale.replace('-', '_');
  304. // Fix locale if declared locale hasn't been defined
  305. if (!(phpjs.locale in phpjs.locales)) {
  306. if (phpjs.locale.replace(/_[a-zA-Z]+$/, '') in phpjs.locales) {
  307. phpjs.locale = phpjs.locale.replace(/_[a-zA-Z]+$/, '');
  308. }
  309. }
  310. if (!phpjs.localeCategories) {
  311. phpjs.localeCategories = {
  312. 'LC_COLLATE' : phpjs.locale,
  313. // for string comparison, see strcoll()
  314. 'LC_CTYPE' : phpjs.locale,
  315. // for character classification and conversion, for example strtoupper()
  316. 'LC_MONETARY' : phpjs.locale,
  317. // for localeconv()
  318. 'LC_NUMERIC' : phpjs.locale,
  319. // for decimal separator (See also localeconv())
  320. 'LC_TIME' : phpjs.locale,
  321. // for date and time formatting with strftime()
  322. 'LC_MESSAGES' : phpjs.locale // for system responses (available if PHP was compiled with libintl)
  323. };
  324. }
  325. // END REDUNDANT
  326. if (locale === null || locale === '') {
  327. locale = this.getenv(category) || this.getenv('LANG');
  328. } else if (Object.prototype.toString.call(locale) === '[object Array]') {
  329. for (i = 0; i < locale.length; i++) {
  330. if (!(locale[i] in this.php_js.locales)) {
  331. if (i === locale.length - 1) {
  332. // none found
  333. return false;
  334. }
  335. continue;
  336. }
  337. locale = locale[i];
  338. break;
  339. }
  340. }
  341. // Just get the locale
  342. if (locale === '0' || locale === 0) {
  343. if (category === 'LC_ALL') {
  344. for (categ in this.php_js.localeCategories) {
  345. // Add ".UTF-8" or allow ".@latint", etc. to the end?
  346. cats.push(categ + '=' + this.php_js.localeCategories[categ]);
  347. }
  348. return cats.join(';');
  349. }
  350. return this.php_js.localeCategories[category];
  351. }
  352. if (!(locale in this.php_js.locales)) {
  353. // Locale not found
  354. return false;
  355. }
  356. // Set and get locale
  357. if (category === 'LC_ALL') {
  358. for (categ in this.php_js.localeCategories) {
  359. this.php_js.localeCategories[categ] = locale;
  360. }
  361. } else {
  362. this.php_js.localeCategories[category] = locale;
  363. }
  364. return locale;
  365. }