ld, new, mergeCount, pullCount, oldCount }` object.
 * `old` is a hash of values that have not been merged into `target`.
 * `new` is `target`. `mergeCount` is the number of keys merged into
 * `new`, `pullCount` is the number of context and plural keys added to
 * `new` and `oldCount` is the number of keys that were either added to `old` or
 * `new` (if `keepRemoved` is true and `target` didn't have the corresponding
 * key).
 */
function mergeHashes(source, target) {var keepRemoved = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  var old = {};
  var mergeCount = 0;
  var pullCount = 0;
  var oldCount = 0;
  for (var key in source) {
    var hasNestedEntries =
    _typeof(target[key]) === 'object' && !Array.isArray(target[key]);

    if (hasNestedEntries) {
      var nested = mergeHashes(source[key], target[key], keepRemoved);
      mergeCount += nested.mergeCount;
      pullCount += nested.pullCount;
      if (Object.keys(nested.old).length) {
        old[key] = nested.old;
        oldCount += nested.oldCount;
      }
    } else {
      if (target[key] !== undefined) {
        if (typeof source[key] === 'string' || Array.isArray(source[key])) {
          target[key] = source[key];
          mergeCount += 1;
        } else {
          old[key] = source[key];
          oldCount += 1;
        }
      } else {
        // support for plural in keys
        var pluralRegex = /(_plural)|(_\d+)$/;
        var pluralMatch = pluralRegex.test(key);
        var singularKey = key.replace(pluralRegex, '');

        // support for context in keys
        var contextRegex = /_([^_]+)?$/;
        var contextMatch = contextRegex.test(singularKey);
        var rawKey = singularKey.replace(contextRegex, '');

        if (
        contextMatch && target[rawKey] !== undefined ||
        pluralMatch && target[singularKey] !== undefined)
        {
          target[key] = source[key];
          pullCount += 1;
        } else {
          if (keepRemoved) {
            target[key] = source[key];
          } else {
            old[key] = source[key];
          }
          oldCount += 1;
        }
      }
    }
  }

  return { old: old, "new": target, mergeCount: mergeCount, pullCount: pullCount, oldCount: oldCount };
}

/**
 * Merge `source` into `target` by merging nested dictionaries.
 */
function transferValues(source, target) {
  for (var key in source) {
    var sourceValue = source[key];
    var targetValue = target[key];
    if (
    _typeof(sourceValue) === 'object' &&
    _typeof(targetValue) === 'object' &&
    !Array.isArray(sourceValue))
    {
      transferValues(sourceValue, targetValue);
    } else {
      target[key] = sourceValue;
    }
  }
}