all files / src/ locales.jsx

33.03% Statements 36/109
23.21% Branches 13/56
26.67% Functions 4/15
27.84% Lines 27/97
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 149151×                                                               152×     152×         152×                                                                                                                                       152×     152×     2173× 2173×       2173× 2173× 152×   2173×                    
/* eslint-disable global-require, import/no-dynamic-require */
import React from 'react';
import { sprintf } from 'sprintf-js';
import i18n from './i18n';
 
function formatForReact(formatString, args) {
  const rv = [];
  let cursor = 0;
  sprintf.parse(formatString).forEach((match, idx) => {
    const cpoyMatch = match;
    let copyIdx = idx;
    if (typeof match === 'string') {
      rv.push(match);
    } else {
      let arg = null;
      if (match[2]) {
        arg = args[0][match[2][0]];
      } else if (match[1]) {
        arg = args[parseInt(match[1], 10) - 1];
      } else {
        arg = args[cursor++];
      }
      if (React.isValidElement(arg)) {
        rv.push(React.cloneElement(arg, { key: idx }));
      } else {
        cpoyMatch[2] = null;
        cpoyMatch[1] = 1;
        rv.push(<span key={copyIdx++}>
          {sprintf.format([cpoyMatch], [null, arg])}
        </span>);
      }
    }
  });
  return rv;
}
 
function argsInvolveReact(args) {
  if (Iargs.some(React.isValidElement)) {
    return true;
  }
  if (Iargs.length === 1 && typeof args[0] === 'object') {
    return Object.keys(args[0]).some(function (key) {
      return React.isValidElement(args[0][key]);
    });
  }
  return false;
}
 
export function parseComponentTemplate(string) {
  const rv = {};
  function process(startPos, group, inGroup) {
    const regex = /\[(.*?)(:|\])|\]/g;
    let match;
    const buf = [];
    let satisfied = false;
    let pos = regex.lastIndex = startPos;
    match = regex.exec(string);
    while (match !== null) {
      const substr = string.substr(pos, match.index - pos);
      if (substr !== '') {
        buf.push(substr);
      }
      if (match[0] === ']') {
        if (inGroup) {
          satisfied = true;
          break;
        } else {
          pos = regex.lastIndex;
          continue;
        }
      }
      if (match[2] === ']') {
        pos = regex.lastIndex;
      } else {
        pos = regex.lastIndex = process(regex.lastIndex, match[1], true);
      }
      buf.push({ group: match[1] });
      match = regex.exec(string);
    }
    let endPos = regex.lastIndex;
    if (!satisfied) {
      const rest = string.substr(pos);
      if (rest) {
        buf.push(rest);
      }
      endPos = string.length;
    }
    rv[group] = buf;
    return endPos;
  }
  process(0, 'root', false);
  return rv;
}
 
export function renderComponentTemplate(template, components) {
  let idx = 0;
  function renderGroup(group) {
    const children = [];
    (template[group] || []).forEach((item) => {
      if (typeof item === 'string') {
        children.push(<span key={idx++}>{item}</span>);
      } else {
        children.push(renderGroup(item.group));
      }
    });
    let reference = components[group] || <span key={idx++} />;
    if (!React.isValidElement(reference)) {
      reference = <span key={idx++}>{reference}</span>;
    }
    if (children.length > 0) {
      return React.cloneElement(reference, { key: idx++ }, children);
    }
    return React.cloneElement(reference, { key: idx++ });
  }
  return renderGroup('root');
}
 
export function format(formatString, args) {
  if (IargsInvolveReact(args)) {
    return formatForReact(formatString, args);
  }
  return sprintf(formatString, ...args);
}
 
export function gettext(string, ...args) {
  if (I!string || !i18n) {
    return string;
  }
 
  let rv = i18n.gettext(string);
  if (args.length > 0) {
    rv = format(rv, args);
  }
  return rv;
}
 
export function ngettext(singular, plural, ...args) {
  return format(i18n.ngettext(singular, plural, args[0] || 0), args);
}
 
export function gettextComponentTemplate(template, components) {
  const tmpl = parseComponentTemplate(i18n.gettext(template));
  return renderComponentTemplate(tmpl, components);
}
 
export const t = gettext;
export const tn = ngettext;
export const tct = gettextComponentTemplate;