{
  "version": 3,
  "sources": ["i18n_strings.js"],
  "sourcesContent": ["/*\n * static/js/i18n_strings.js \u2014 read server-translated strings back into JS\n * (SNOW-620).\n *\n * ``makemessages`` scans templates and Python. It does not scan\n * JavaScript, so a string written as a JS literal is invisible to the\n * message catalogue and ships as English to every locale no matter how\n * complete that locale is. Roughly forty user-facing strings were in that\n * position across eight modules \u2014 the whole layers-menu sync dashboard,\n * every mutation and favourite failure toast, the update banner, and all\n * the timelapse controls.\n *\n * The fix already existed in the tree, used by exactly one module:\n * ``_map_downloads_sheet.html`` renders a hidden ``<template>`` of\n * ``{% trans %}`` spans and ``map_downloads_manager.js`` reads them back.\n * That read loop was thirty lines with two non-obvious details in it, and\n * eight more copies of it would be eight chances to get one of them\n * wrong \u2014 so it lives here now and every surface calls it.\n *\n * ## Usage\n *\n *   var STRINGS = self.pwaStrings.read('my-strings-template', {\n *     'save-failed': 'That could not be saved. Try again.',\n *   });\n *   el.textContent = STRINGS['save-failed'];\n *\n * The second argument is the English fallback, and it is not optional in\n * spirit: a module whose template is missing (a partial not included on\n * this page, a surface built before the template rendered) must still put\n * words on the screen rather than ``undefined``. The fallback is also the\n * only copy of the string a reader of the JS can see, so it doubles as\n * documentation of what the key means.\n *\n * ## Two details worth keeping\n *\n * **Whitespace is collapsed, not trimmed.** ``djangofmt`` reflows a long\n * ``{% blocktrans %}`` across lines to satisfy the line length it\n * enforces, which puts a newline and a run of source indentation into the\n * middle of the string. That is invisible in the template and rendered\n * verbatim into a ``window.confirm`` dialog. Collapsing on read makes\n * these strings immune to how the formatter chooses to wrap them, rather\n * than leaving templates that must never be reformatted.\n *\n * **Interpolation is by name, never positional.** Django's ``blocktrans``\n * emits ``%(name)s`` placeholders and a locale is free to reorder them \u2014\n * a German translation may well need the size before the region name. A\n * positional substitution silently swaps them.\n *\n * Dependency-free and DOM-light by design: everything except ``read``\n * takes plain values, so it is unit-tested directly\n * (tests/js/test_i18n_strings.js).\n */\n\n(function () {\n  'use strict';\n\n  /**\n   * Collapse every run of whitespace to a single space and trim.\n   *\n   * @param {string} value\n   * @returns {string}\n   */\n  function collapse(value) {\n    return String(value == null ? '' : value)\n      .replace(/\\s+/g, ' ')\n      .trim();\n  }\n\n  /**\n   * Read a strings ``<template>`` back into a plain object.\n   *\n   * Every ``[data-string]`` element inside the template contributes one\n   * entry, keyed by its ``data-string`` value. Keys absent from the\n   * template \u2014 or every key, when the template itself is absent \u2014 fall\n   * back to `fallbacks`.\n   *\n   * An empty or whitespace-only element does NOT override its fallback.\n   * A translator leaving a msgstr blank is how gettext spells \"not\n   * translated yet\", and Django renders that as the empty string; taking\n   * it literally would blank the control rather than show English.\n   *\n   * @param {string} templateId\n   * @param {Object<string, string>} fallbacks\n   * @param {Document} [doc] Injectable for tests.\n   * @returns {Object<string, string>}\n   */\n  function read(templateId, fallbacks, doc) {\n    var out = {};\n    var key;\n    var source = fallbacks || {};\n    for (key in source) {\n      if (Object.prototype.hasOwnProperty.call(source, key)) {\n        out[key] = source[key];\n      }\n    }\n\n    var d = doc || (typeof document !== 'undefined' ? document : null);\n    if (!d) return out;\n    var tpl = d.getElementById(templateId);\n    // `content` is absent on a <template> polyfilled away, and on any\n    // element that is not a template at all \u2014 an id collision would\n    // otherwise throw here and take the whole module down.\n    if (!tpl || !tpl.content) return out;\n\n    tpl.content.querySelectorAll('[data-string]').forEach(function (el) {\n      var text = collapse(el.textContent);\n      if (text) out[el.dataset.string] = text;\n    });\n    return out;\n  }\n\n  /**\n   * Substitute ``%(name)s``-style placeholders into a translated string.\n   *\n   * An unknown placeholder is left as-is rather than replaced with\n   * ``undefined``: a locale that invents a placeholder the caller does not\n   * supply should show a visibly wrong string, not a confidently wrong one.\n   *\n   * @param {string} template\n   * @param {Object<string, *>} values\n   * @returns {string}\n   */\n  function interpolate(template, values) {\n    if (!template) return '';\n    var source = values || {};\n    return String(template).replace(/%\\((\\w+)\\)s/g, function (match, key) {\n      return Object.prototype.hasOwnProperty.call(source, key)\n        ? String(source[key])\n        : match;\n    });\n  }\n\n  var HTML_ESCAPES = {\n    '&': '&amp;',\n    '<': '&lt;',\n    '>': '&gt;',\n    '\"': '&quot;',\n    \"'\": '&#x27;',\n  };\n\n  /**\n   * Escape a translated string for interpolation into an HTML string.\n   *\n   * Some surfaces assemble their markup by concatenation and assign it to\n   * ``innerHTML`` (``report.js``'s ineligible-user states). A translated\n   * string dropped into that unescaped is a markup injection waiting for\n   * the first locale whose copy contains a quote \u2014 ``aria-label=\"\u2026\"``\n   * closes early and the rest of the sentence becomes attributes. This is\n   * not about untrusted input, since translations are ours; it is that\n   * ordinary punctuation in ordinary prose would silently corrupt the DOM.\n   *\n   * Prefer ``textContent`` where the surface allows it \u2014 then no escaping\n   * is needed at all.\n   *\n   * @param {string} value\n   * @returns {string}\n   */\n  function escapeHtml(value) {\n    return String(value == null ? '' : value).replace(/[&<>\"']/g, function (ch) {\n      return HTML_ESCAPES[ch];\n    });\n  }\n\n  self.pwaStrings = Object.freeze({\n    read: read,\n    interpolate: interpolate,\n    collapse: collapse,\n    escapeHtml: escapeHtml,\n  });\n})();\n"],
  "mappings": "CAqDC,UAAY,CACX,aAQA,SAASA,EAASC,EAAO,CACvB,OAAO,OAAOA,GAAgB,EAAU,EACrC,QAAQ,OAAQ,GAAG,EACnB,KAAK,CACV,CAoBA,SAASC,EAAKC,EAAYC,EAAWC,EAAK,CACxC,IAAIC,EAAM,CAAC,EACPC,EACAC,EAASJ,GAAa,CAAC,EAC3B,IAAKG,KAAOC,EACN,OAAO,UAAU,eAAe,KAAKA,EAAQD,CAAG,IAClDD,EAAIC,CAAG,EAAIC,EAAOD,CAAG,GAIzB,IAAIE,EAAIJ,IAAQ,OAAO,SAAa,IAAc,SAAW,MAC7D,GAAI,CAACI,EAAG,OAAOH,EACf,IAAII,EAAMD,EAAE,eAAeN,CAAU,EAIrC,MAAI,CAACO,GAAO,CAACA,EAAI,SAEjBA,EAAI,QAAQ,iBAAiB,eAAe,EAAE,QAAQ,SAAUC,EAAI,CAClE,IAAIC,EAAOZ,EAASW,EAAG,WAAW,EAC9BC,IAAMN,EAAIK,EAAG,QAAQ,MAAM,EAAIC,EACrC,CAAC,EACMN,CACT,CAaA,SAASO,EAAYC,EAAUC,EAAQ,CACrC,GAAI,CAACD,EAAU,MAAO,GACtB,IAAIN,EAASO,GAAU,CAAC,EACxB,OAAO,OAAOD,CAAQ,EAAE,QAAQ,eAAgB,SAAUE,EAAOT,EAAK,CACpE,OAAO,OAAO,UAAU,eAAe,KAAKC,EAAQD,CAAG,EACnD,OAAOC,EAAOD,CAAG,CAAC,EAClBS,CACN,CAAC,CACH,CAEA,IAAIC,EAAe,CACjB,IAAK,QACL,IAAK,OACL,IAAK,OACL,IAAK,SACL,IAAK,QACP,EAmBA,SAASC,EAAWjB,EAAO,CACzB,OAAO,OAAOA,GAAgB,EAAU,EAAE,QAAQ,WAAY,SAAUkB,EAAI,CAC1E,OAAOF,EAAaE,CAAE,CACxB,CAAC,CACH,CAEA,KAAK,WAAa,OAAO,OAAO,CAC9B,KAAMjB,EACN,YAAaW,EACb,SAAUb,EACV,WAAYkB,CACd,CAAC,CACH,GAAG",
  "names": ["collapse", "value", "read", "templateId", "fallbacks", "doc", "out", "key", "source", "d", "tpl", "el", "text", "interpolate", "template", "values", "match", "HTML_ESCAPES", "escapeHtml", "ch"]
}
