grammar.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.Grammar = exports.ATTRIBUTE = void 0;
  4. exports.correctFont = correctFont;
  5. const DomUtil = require("../common/dom_util.js");
  6. const engine_js_1 = require("../common/engine.js");
  7. const LocaleUtil = require("../l10n/locale_util.js");
  8. const locale_js_1 = require("../l10n/locale.js");
  9. exports.ATTRIBUTE = 'grammar';
  10. class Grammar {
  11. static getInstance() {
  12. Grammar.instance = Grammar.instance || new Grammar();
  13. return Grammar.instance;
  14. }
  15. static parseInput(grammar) {
  16. const attributes = {};
  17. const components = grammar.split(':');
  18. for (const component of components) {
  19. const comp = component.split('=');
  20. const key = comp[0].trim();
  21. if (comp[1]) {
  22. attributes[key] = comp[1].trim();
  23. continue;
  24. }
  25. key.match(/^!/)
  26. ? (attributes[key.slice(1)] = false)
  27. : (attributes[key] = true);
  28. }
  29. return attributes;
  30. }
  31. static parseState(stateStr) {
  32. const state = {};
  33. const corrections = stateStr.split(' ');
  34. for (const correction of corrections) {
  35. const corr = correction.split(':');
  36. const key = corr[0];
  37. const value = corr[1];
  38. state[key] = value ? value : true;
  39. }
  40. return state;
  41. }
  42. static translateString(text) {
  43. if (text.match(/:unit$/)) {
  44. return Grammar.translateUnit(text);
  45. }
  46. const engine = engine_js_1.Engine.getInstance();
  47. let result = engine.evaluator(text, engine.dynamicCstr);
  48. result = result === null ? text : result;
  49. if (Grammar.getInstance().getParameter('plural')) {
  50. result = locale_js_1.LOCALE.FUNCTIONS.plural(result);
  51. }
  52. return result;
  53. }
  54. static translateUnit(text) {
  55. text = Grammar.prepareUnit(text);
  56. const engine = engine_js_1.Engine.getInstance();
  57. const plural = Grammar.getInstance().getParameter('plural');
  58. const strict = engine.strict;
  59. const baseCstr = `${engine.locale}.${engine.modality}.default`;
  60. engine.strict = true;
  61. let cstr;
  62. let result;
  63. if (plural) {
  64. cstr = engine.defaultParser.parse(baseCstr + '.plural');
  65. result = engine.evaluator(text, cstr);
  66. }
  67. if (result) {
  68. engine.strict = strict;
  69. return result;
  70. }
  71. cstr = engine.defaultParser.parse(baseCstr + '.default');
  72. result = engine.evaluator(text, cstr);
  73. engine.strict = strict;
  74. if (!result) {
  75. return Grammar.cleanUnit(text);
  76. }
  77. if (plural) {
  78. result = locale_js_1.LOCALE.FUNCTIONS.plural(result);
  79. }
  80. return result;
  81. }
  82. static prepareUnit(text) {
  83. const match = text.match(/:unit$/);
  84. return match
  85. ? text.slice(0, match.index).replace(/\s+/g, ' ') +
  86. text.slice(match.index)
  87. : text;
  88. }
  89. static cleanUnit(text) {
  90. if (text.match(/:unit$/)) {
  91. return text.replace(/:unit$/, '');
  92. }
  93. return text;
  94. }
  95. clear() {
  96. this.parameters_ = {};
  97. this.stateStack_ = [];
  98. }
  99. setParameter(parameter, value) {
  100. const oldValue = this.parameters_[parameter];
  101. value
  102. ? (this.parameters_[parameter] = value)
  103. : delete this.parameters_[parameter];
  104. return oldValue;
  105. }
  106. getParameter(parameter) {
  107. return this.parameters_[parameter];
  108. }
  109. setCorrection(correction, func) {
  110. this.corrections_[correction] = func;
  111. }
  112. setPreprocessor(preprocessor, func) {
  113. this.preprocessors_[preprocessor] = func;
  114. }
  115. getCorrection(correction) {
  116. return this.corrections_[correction];
  117. }
  118. getState() {
  119. const pairs = [];
  120. for (const [key, val] of Object.entries(this.parameters_)) {
  121. pairs.push(typeof val === 'string' ? key + ':' + val : key);
  122. }
  123. return pairs.join(' ');
  124. }
  125. processSingles() {
  126. const assignment = {};
  127. for (const single of this.singles) {
  128. assignment[single] = false;
  129. }
  130. this.singles = [];
  131. this.pushState(assignment);
  132. }
  133. pushState(assignment) {
  134. for (let [key, value] of Object.entries(assignment)) {
  135. if (key.match(/^\?/)) {
  136. delete assignment[key];
  137. key = key.slice(1);
  138. this.singles.push(key);
  139. }
  140. assignment[key] = this.setParameter(key, value);
  141. }
  142. this.stateStack_.push(assignment);
  143. }
  144. popState() {
  145. const assignment = this.stateStack_.pop();
  146. for (const [key, val] of Object.entries(assignment)) {
  147. this.setParameter(key, val);
  148. }
  149. }
  150. setAttribute(node) {
  151. if (node && node.nodeType === DomUtil.NodeType.ELEMENT_NODE) {
  152. const state = this.getState();
  153. if (state) {
  154. node.setAttribute(exports.ATTRIBUTE, state);
  155. }
  156. }
  157. }
  158. preprocess(text) {
  159. return this.runProcessors(text, this.preprocessors_);
  160. }
  161. correct(text) {
  162. return this.runProcessors(text, this.corrections_);
  163. }
  164. apply(text, opt_flags) {
  165. this.currentFlags = opt_flags || {};
  166. text =
  167. this.currentFlags.adjust || this.currentFlags.preprocess
  168. ? Grammar.getInstance().preprocess(text)
  169. : text;
  170. if (this.parameters_['translate'] || this.currentFlags.translate) {
  171. text = Grammar.translateString(text);
  172. }
  173. text =
  174. this.currentFlags.adjust || this.currentFlags.correct
  175. ? Grammar.getInstance().correct(text)
  176. : text;
  177. this.currentFlags = {};
  178. return text;
  179. }
  180. runProcessors(text, funcs) {
  181. for (const [key, val] of Object.entries(this.parameters_)) {
  182. const func = funcs[key];
  183. if (!func) {
  184. continue;
  185. }
  186. text = val === true ? func(text) : func(text, val);
  187. }
  188. return text;
  189. }
  190. constructor() {
  191. this.currentFlags = {};
  192. this.parameters_ = {};
  193. this.corrections_ = {};
  194. this.preprocessors_ = {};
  195. this.stateStack_ = [];
  196. this.singles = [];
  197. }
  198. }
  199. exports.Grammar = Grammar;
  200. function correctFont(text, correction) {
  201. if (!correction || !text) {
  202. return text;
  203. }
  204. const regexp = locale_js_1.LOCALE.FUNCTIONS.fontRegexp(LocaleUtil.localFont(correction));
  205. return text.replace(regexp, '');
  206. }
  207. function correctCaps(text) {
  208. let cap = locale_js_1.LOCALE.ALPHABETS.capPrefix[engine_js_1.Engine.getInstance().domain];
  209. if (typeof cap === 'undefined') {
  210. cap = locale_js_1.LOCALE.ALPHABETS.capPrefix['default'];
  211. }
  212. return correctFont(text, cap);
  213. }
  214. function addAnnotation(text, annotation) {
  215. return text + ':' + annotation;
  216. }
  217. function numbersToAlpha(text) {
  218. return text.match(/\d+/)
  219. ? locale_js_1.LOCALE.NUMBERS.numberToWords(parseInt(text, 10))
  220. : text;
  221. }
  222. function noTranslateText(text) {
  223. if (text.match(new RegExp('^[' + locale_js_1.LOCALE.MESSAGES.regexp.TEXT + ']+$'))) {
  224. Grammar.getInstance().currentFlags['translate'] = false;
  225. }
  226. return text;
  227. }
  228. Grammar.getInstance().setCorrection('localFont', LocaleUtil.localFont);
  229. Grammar.getInstance().setCorrection('localRole', LocaleUtil.localRole);
  230. Grammar.getInstance().setCorrection('localEnclose', LocaleUtil.localEnclose);
  231. Grammar.getInstance().setCorrection('ignoreFont', correctFont);
  232. Grammar.getInstance().setPreprocessor('annotation', addAnnotation);
  233. Grammar.getInstance().setPreprocessor('noTranslateText', noTranslateText);
  234. Grammar.getInstance().setCorrection('ignoreCaps', correctCaps);
  235. Grammar.getInstance().setPreprocessor('numbers2alpha', numbersToAlpha);