code: function normalizeMessagePlaceholders(descriptor, messageIds) {
    const message = typeof descriptor.messageId === 'string' ? messageIds[descriptor.messageId] : descriptor.message;
    if (!descriptor.data) {
      return {
        message,
        data: typeof descriptor.messageId === 'string' ? {} : null,
      };
    }
  
    const normalizedData = Object.create(null);
    const interpolatedMessage = message.replace(/\{\{\s*([^{}]+?)\s*\}\}/g, (fullMatch, term) => {
      if (term in descriptor.data) {
        normalizedData[term] = descriptor.data[term];
        return descriptor.data[term];
      }
  
      return fullMatch;
    });
  
    return {
      message: interpolatedMessage,
      data: Object.freeze(normalizedData),
    };
  }
docs: Interpolates data placeholders in report messages
  @param {MessageDescriptor} descriptor The report message descriptor.
  @param {Object} messageIds Message IDs from rule metadata
  @returns {{message: string, data: Object}} The interpolated message and data for the descriptor