| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
 | 'use strict';
var converter = require('./converter.js');
exports.extractNumberSymbols = extractNumberSymbols;
exports.extractCurrencySymbols = extractCurrencySymbols;
exports.extractDateTimeSymbols = extractDateTimeSymbols;
exports.pluralExtractor = pluralExtractor;
exports.outputLocale = outputLocale;
exports.correctedLocaleId = correctedLocaleId;
exports.findLocaleId = findLocaleId;
exports.serializeContent = serializeContent;
var goog = { provide: function() {},
  require: function() {},
  i18n: {currency: {}, pluralRules: {}} };
function findLocaleId(str, type) {
  if (type === 'num') {
    return (str.match(/^NumberFormatSymbols_(.+)$/) || [])[1];
  }
  if (type != 'datetime') { throw new Error('unknown type in findLocaleId: ' + type); }
  return (str.match(/^DateTimeSymbols_(.+)$/) || [])[1];
}
function getInfoForLocale(localeInfo, localeID) {
  if (!localeInfo[localeID]) {
    localeInfo[localeID] = {};
    //localeIds.push(localeID);
  }
  return localeInfo[localeID];
}
function extractNumberSymbols(content, localeInfo, currencySymbols) {
  //eval script in the current context so that we get access to all the symbols
  eval(content.toString());
  for (var propName in goog.i18n) {
    var localeID = findLocaleId(propName, 'num');
    if (localeID) {
      var info = getInfoForLocale(localeInfo, localeID);
      info.NUMBER_FORMATS =
          converter.convertNumberData(goog.i18n[propName], currencySymbols);
    }
  }
}
function extractCurrencySymbols(content) {
  //eval script in the current context so that we get access to all the symbols
  eval(content.toString());
  var currencySymbols = goog.i18n.currency.CurrencyInfo;
  currencySymbols.__proto__ = goog.i18n.currency.CurrencyInfoTier2;
  return currencySymbols;
}
function extractDateTimeSymbols(content, localeInfo) {
  //eval script in the current context so that we get access to all the symbols
  eval(content.toString());
  for (var propName in goog.i18n) {
    var localeID = findLocaleId(propName, 'datetime');
    if (localeID) {
      var info = getInfoForLocale(localeInfo, localeID);
      localeInfo[localeID].DATETIME_FORMATS =
          converter.convertDatetimeData(goog.i18n[propName]);
    }
  }
}
function pluralExtractor(content, localeInfo) {
  var contentText = content.toString();
  var localeIds = Object.keys(localeInfo);
  for (var i = 0; i < localeIds.length; i++) {
    //We don't need to care about country ID because the plural rules in more specific id are
    //always the same as those in its language ID.
    // e.g. plural rules for en_SG is the same as those for en.
    goog.LOCALE = localeIds[i].match(/[^_]+/)[0];
    try {
      eval(contentText);
    } catch(e) {
      console.log("Error in eval(contentText): " + e.stack);
    }
    if (!goog.i18n.pluralRules.select) {
      console.log('No select for lang [' + goog.LOCALE + ']');
      continue;
    }
    var temp = goog.i18n.pluralRules.select.toString().
        replace(/goog.i18n.pluralRules.Keyword/g, 'PLURAL_CATEGORY').replace(/\n/g, '');
    ///@@ is a crazy place holder to be replaced before writing to file
    localeInfo[localeIds[i]].pluralCat = "@@" + temp + "@@";
  }
}
function correctedLocaleId(localeID) {
// e.g. from zh_CN to zh-CN, from en_US to en-US
  return localeID.replace(/_/g, '-').toLowerCase();
}
function canonicalizeForJsonStringify(unused_key, object) {
  // This function is intended to be called as the 2nd argument to
  // JSON.stringify.  The goal here is to ensure that the generated JSON has
  // objects with their keys in ascending order.  Without this, it's much
  // harder to diff the generated files in src/ngLocale as the order isn't
  // exactly consistent.  We've gotten lucky in the past.
  //
  // Iteration order, for string keys, ends up being the same as insertion
  // order.  Refer :-
  //    1. http://ejohn.org/blog/javascript-in-chrome/
  //       (search for "for loop order").
  //       Currently all major browsers loop over the properties of an object
  //       in the order in which they were defined.
  //         - John Resig
  //    2. https://code.google.com/p/v8/issues/detail?id=164
  //       ECMA-262 does not specify enumeration order. The de facto standard
  //       is to match insertion order, which V8 also does ...
  if (typeof object != "object") {
    return object;
  }
  var result = {};
  Object.keys(object).sort().forEach(function(key) {
    result[key] = object[key];
  });
  return result;
}
function serializeContent(localeObj) {
  return JSON.stringify(localeObj, canonicalizeForJsonStringify, '  ')
    .replace(new RegExp('[\\u007f-\\uffff]', 'g'), function(c) { return '\\u'+('0000'+c.charCodeAt(0).toString(16)).slice(-4); })
    .replace(/"@@|@@"/g, '');
}
function outputLocale(localeInfo, localeID) {
  var fallBackID = localeID.match(/[A-Za-z]+/)[0],
      localeObj = localeInfo[localeID],
      fallBackObj = localeInfo[fallBackID];
  // fallBack to language formats when country format is missing
  // e.g. if NUMBER_FORMATS of en_xyz is not present, use the NUMBER_FORMATS of en instead
  if (!localeObj.NUMBER_FORMATS) {
    localeObj.NUMBER_FORMATS = fallBackObj.NUMBER_FORMATS;
  }
  // datetimesymbolsext.js provides more top level locales than the other
  // files.  We process datetimesymbolsext.js because we want the country
  // specific formats that are missing from datetimesymbols.js.  However, we
  // don't want to write locale files that only have dateformat (i.e. missing
  // number formats.)  So we skip them.
  if (!localeObj.NUMBER_FORMATS) {
    console.log("Skipping locale %j: Don't have any number formats", localeID);
    return null;
  }
  if (!localeObj.DATETIME_FORMATS) {
    localeObj.DATETIME_FORMATS = fallBackObj.DATETIME_FORMATS;
  }
  localeObj.id = correctedLocaleId(localeID);
  var prefix =
      'angular.module("ngLocale", [], ["$provide", function($provide) {\n' +
          'var PLURAL_CATEGORY = {' +
          'ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"' +
          '};\n' +
          '$provide.value("$locale", ';
  var suffix = ');\n}]);';
  localeObj = {
    DATETIME_FORMATS: localeObj.DATETIME_FORMATS,
    NUMBER_FORMATS: localeObj.NUMBER_FORMATS,
    pluralCat: localeObj.pluralCat,
    id: localeObj.id
  };
  var content = serializeContent(localeInfo[localeID]);
  return prefix + content + suffix;
}
 |