function createIcuMessageFn(filename, fileStrings = {}) {
  if (filename.startsWith('file://')) filename = url.fileURLToPath(filename);

  // In the common case, `filename` is an absolute path that needs to be transformed
  // to be relative to LH_ROOT. In other cases, `filename` might be the exact i18n identifier
  // already (see: stack-packs.js, or bundled lighthouse).
  if (path.isAbsolute(filename)) filename = path.relative(LH_ROOT, filename);

  /**
   * Combined so fn can access both caller's strings and i18n.UIStrings shared across LH.
   * @type {Record<string, string>}
   */
  const mergedStrings = {...UIStrings, ...fileStrings};

  /**
   * Convert a message string and replacement values into an `LH.IcuMessage`.
   * @param {string} message
   * @param {Record<string, string | number>} [values]
   * @return {LH.IcuMessage}
   */
  const getIcuMessageFn = (message, values) => {
    const keyname = Object.keys(mergedStrings).find(key => mergedStrings[key] === message);
    if (!keyname) throw new Error(`Could not locate: ${message}`);

    // `message` can be a UIString defined within the provided `fileStrings`, or it could be
    // one of the common strings found in `i18n.UIStrings`.
    const filenameToLookup = keyname in fileStrings ?
      filename :
      path.relative(LH_ROOT, getModulePath(import.meta));
    const unixStyleFilename = filenameToLookup.replace(/\\/g, '/');
    const i18nId = `${unixStyleFilename} | ${keyname}`;

    return {
      i18nId,
      values,
      formattedDefault: formatMessage(message, values, DEFAULT_LOCALE),
    };
  };

  return getIcuMessageFn;
}
Returns a function that generates `LH.IcuMessage` objects to localize the
messages in `fileStrings` and the shared `i18n.UIStrings`.
@param {string} filename
@param {Record<string, string>=} fileStrings