DonatShell
Server IP : 180.180.241.3  /  Your IP : 216.73.216.252
Web Server : Microsoft-IIS/7.5
System : Windows NT NETWORK-NHRC 6.1 build 7601 (Windows Server 2008 R2 Standard Edition Service Pack 1) i586
User : IUSR ( 0)
PHP Version : 5.3.28
Disable Function : NONE
MySQL : ON  |  cURL : ON  |  WGET : OFF  |  Perl : OFF  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /Program Files (x86)/Mozilla Firefox/updated/browser/features/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME SHELL ]     

Current File : /Program Files (x86)/Mozilla Firefox/updated/browser/features/screenshots@mozilla.org.xpi
PK
!<}
88)bootstrap.jsPK
!<\?W"?install.rdfPK
!<0ߦ'fBwebextension/_locales/ach/messages.jsonPK
!<

&QQwebextension/_locales/ar/messages.jsonPK
!<NZ&dwebextension/_locales/az/messages.jsonPK
!<#i&vwebextension/_locales/be/messages.jsonPK
!<Q[[&-webextension/_locales/bg/messages.jsonPK
!<Zj  )̤webextension/_locales/bn_BD/messages.jsonPK
!<-2II&3webextension/_locales/ca/messages.jsonPK
!<//'webextension/_locales/cak/messages.jsonPK
!<hU?``&4webextension/_locales/cs/messages.jsonPK
!<y>]uu&webextension/_locales/cy/messages.jsonPK
!<?E00&webextension/_locales/da/messages.jsonPK
!<&webextension/_locales/de/messages.jsonPK
!<'*webextension/_locales/dsb/messages.jsonPK
!<tSS&<webextension/_locales/el/messages.jsonPK
!<Sb1)fUwebextension/_locales/en_GB/messages.jsonPK
!<sZ)Xbwebextension/_locales/en_US/messages.jsonPK
!<-&rwebextension/_locales/eo/messages.jsonPK
!<H7)nwebextension/_locales/es_AR/messages.jsonPK
!<LivHH)webextension/_locales/es_CL/messages.jsonPK
!<2_)2webextension/_locales/es_ES/messages.jsonPK
!<%T)webextension/_locales/es_MX/messages.jsonPK
!<OH%==&webextension/_locales/et/messages.jsonPK
!<ɂ&*webextension/_locales/fa/messages.jsonPK
!<EE&webextension/_locales/fi/messages.jsonPK
!<޳Kyy&webextension/_locales/fr/messages.jsonPK
!<qX!!)webextension/_locales/fy_NL/messages.jsonPK
!<-:);%webextension/_locales/ga_IE/messages.jsonPK
!<}l)6webextension/_locales/gu_IN/messages.jsonPK
!<jI55&+Qwebextension/_locales/he/messages.jsonPK
!<
ii)cwebextension/_locales/hi_IN/messages.jsonPK
!<CC&Twebextension/_locales/hr/messages.jsonPK
!<R'ۍwebextension/_locales/hsb/messages.jsonPK
!</\\&webextension/_locales/hu/messages.jsonPK
!<#)webextension/_locales/hy_AM/messages.jsonPK
!<&webextension/_locales/id/messages.jsonPK
!<[M.&webextension/_locales/it/messages.jsonPK
!<gj&webextension/_locales/ja/messages.jsonPK
!<@88&webextension/_locales/ka/messages.jsonPK
!<`*
'lwebextension/_locales/kab/messages.jsonPK
!<&y,webextension/_locales/kk/messages.jsonPK
!<حJVV&GDwebextension/_locales/km/messages.jsonPK
!<O&Dwebextension/_locales/ko/messages.jsonPK
!<"#'Wwebextension/_locales/lij/messages.jsonPK
!< H??&:gwebextension/_locales/lo/messages.jsonPK
!<{	&webextension/_locales/lt/messages.jsonPK
!<*&webextension/_locales/mk/messages.jsonPK
!<mnn&webextension/_locales/mr/messages.jsonPK
!<"'&nwebextension/_locales/ms/messages.jsonPK
!</&webextension/_locales/my/messages.jsonPK
!<Jg()webextension/_locales/nb_NO/messages.jsonPK
!<(
kk&webextension/_locales/nl/messages.jsonPK
!<)|webextension/_locales/nn_NO/messages.jsonPK
!<+$$)Rwebextension/_locales/pa_IN/messages.jsonPK
!<jǡ&webextension/_locales/pl/messages.jsonPK
!<u9\YY)/webextension/_locales/pt_BR/messages.jsonPK
!<$t՛)BAwebextension/_locales/pt_PT/messages.jsonPK
!<r&!Swebextension/_locales/rm/messages.jsonPK
!<HVV&Ddwebextension/_locales/ro/messages.jsonPK
!<:R&gwebextension/_locales/ru/messages.jsonPK
!<(&$webextension/_locales/sk/messages.jsonPK
!<~&]webextension/_locales/sl/messages.jsonPK
!<1				&-webextension/_locales/sq/messages.jsonPK
!<Hbgg&zwebextension/_locales/sr/messages.jsonPK
!<I3)%webextension/_locales/sv_SE/messages.jsonPK
!<l!l!&webextension/_locales/ta/messages.jsonPK
!<{c		&webextension/_locales/te/messages.jsonPK
!<]HE&webextension/_locales/th/messages.jsonPK
!<։$$&webextension/_locales/tl/messages.jsonPK
!<-j&T*webextension/_locales/tr/messages.jsonPK
!<:g&d<webextension/_locales/uk/messages.jsonPK
!<.[=ll&Swebextension/_locales/ur/messages.jsonPK
!<ó\&Shwebextension/_locales/uz/messages.jsonPK
!<z99&6pwebextension/_locales/vi/messages.jsonPK
!<z'-)twebextension/_locales/zh_CN/messages.jsonPK
!<c)webextension/_locales/zh_TW/messages.jsonPK
!<X\%webextension/assertIsBlankDocument.jsPK
!<i{Bkwebextension/assertIsTrusted.jsPK
!<Q[		$<webextension/background/analytics.jsPK
!<V&webextension/background/auth.jsPK
!<7

(޽webextension/background/communication.jsPK
!<~%webextension/background/deviceInfo.jsPK
!<.]((webextension/background/main.jsPK
!<)Pwebextension/background/selectorLoader.jsPK
!<k{]]$:webextension/background/senderror.jsPK
!<Z"*webextension/background/startBackground.jsPK
!<ټ#%webextension/background/takeshot.jsPK
!<7webextension/blank.htmlPK
!<\k#W7webextension/build/buildSettings.jsPK
!<e55(p8webextension/build/inlineSelectionCss.jsPK
!<'0##cnwebextension/build/onboardingCss.jsPK
!<)7,
,
$8webextension/build/onboardingHtml.jsPK
!<ws||webextension/build/raven.jsPK
!<X*S*S
webextension/build/shot.jsPK
!<
+`webextension/catcher.jsPK
!<ڪhwebextension/clipboard.jsPK
!<ʋ@00mwebextension/domainFromUrl.jsPK
!<avݺ%Hqwebextension/icons/back-highlight.svgPK
!<vX.twebextension/icons/back.svgPK
!<31ז
wwebextension/icons/cancel.svgPK
!<< zwebextension/icons/cloud.svgPK
!<I4)|webextension/icons/copy.pngPK
!<Pwebextension/icons/done.svgPK
!<webextension/icons/download.svgPK
!<1!webextension/icons/icon-16-v2.svgPK
!<P!webextension/icons/icon-32-v2.svgPK
!<(+Cwebextension/icons/icon-highlight-32-v2.svgPK
!<&77)webextension/icons/icon-starred-32-v2.svgPK
!<k5webextension/icons/icon-welcome-face-without-eyes.svgPK
!<$әwebextension/icons/menu-fullpage.svgPK
!<~7*"webextension/icons/menu-myshot.svgPK
!<**#jwebextension/icons/menu-visible.svgPK
!<;kk#էwebextension/icons/onboarding-1.pngPK
!<6{v{v#	webextension/icons/onboarding-2.pngPK
!<q<q<#	webextension/icons/onboarding-3.pngPK
!<OP<P<#[	webextension/icons/onboarding-4.pngPK
!<1
webextension/log.jsPK
!<[{HH
webextension/makeUuid.jsPK
!<55w

webextension/manifest.jsonPK
!<		#
webextension/onboarding/slides.htmlPK
!<1++!
webextension/onboarding/slides.jsPK
!<iج||Y9
webextension/randomString.jsPK
!<--';
webextension/selector/callBackground.jsPK
!<gs*
*
)>
webextension/selector/documentMetadata.jsPK
!<,RR H
webextension/selector/shooter.jsPK
!<N-UU_
webextension/selector/ui.jsPK
!<ۯejj"N
webextension/selector/uicontrol.jsPK
!<T9+m webextension/selector/util.jsPK
!<ϵ|9,webextension/sitehelper.jsPK)PK
!<}
88bootstrap.js/* globals ADDON_DISABLE */
const OLD_ADDON_PREF_NAME = "extensions.jid1-NeEaf3sAHdKHPA@jetpack.deviceIdInfo";
const OLD_ADDON_ID = "jid1-NeEaf3sAHdKHPA@jetpack";
const ADDON_ID = "screenshots@mozilla.org";
const TELEMETRY_ENABLED_PREF = "datareporting.healthreport.uploadEnabled";
const PREF_BRANCH = "extensions.screenshots.";
const USER_DISABLE_PREF = "extensions.screenshots.disabled";
const SYSTEM_DISABLE_PREF = "extensions.screenshots.system-disabled";

const { interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
                                  "resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Console",
                                  "resource://gre/modules/Console.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                  "resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LegacyExtensionsUtils",
                                  "resource://gre/modules/LegacyExtensionsUtils.jsm");

let addonResourceURI;
let appStartupDone;
let appStartupPromise = new Promise((resolve, reject) => {
  appStartupDone = resolve;
});

const prefs = Services.prefs;
const prefObserver = {
  register() {
    prefs.addObserver(PREF_BRANCH, this, false); // eslint-disable-line mozilla/no-useless-parameters
  },

  unregister() {
    prefs.removeObserver(PREF_BRANCH, this, false); // eslint-disable-line mozilla/no-useless-parameters
  },

  observe(aSubject, aTopic, aData) {
    // aSubject is the nsIPrefBranch we're observing (after appropriate QI)
    // aData is the name of the pref that's been changed (relative to aSubject)
    if (aData == USER_DISABLE_PREF || aData == SYSTEM_DISABLE_PREF) {
      // eslint-disable-next-line promise/catch-or-return
      appStartupPromise = appStartupPromise.then(handleStartup);
    }
  }
};

const appStartupObserver = {
  register() {
    Services.obs.addObserver(this, "sessionstore-windows-restored", false); // eslint-disable-line mozilla/no-useless-parameters
  },

  unregister() {
    Services.obs.removeObserver(this, "sessionstore-windows-restored", false); // eslint-disable-line mozilla/no-useless-parameters
  },

  observe() {
    appStartupDone();
    this.unregister();
  }
}

const APP_STARTUP = 1;
let startupReason;

function startup(data, reason) { // eslint-disable-line no-unused-vars
  startupReason = reason;
  if (reason === APP_STARTUP) {
    appStartupObserver.register();
  } else {
    appStartupDone();
  }
  prefObserver.register();
  addonResourceURI = data.resourceURI;
  // eslint-disable-next-line promise/catch-or-return
  appStartupPromise = appStartupPromise.then(handleStartup);
}

function shutdown(data, reason) { // eslint-disable-line no-unused-vars
  prefObserver.unregister();
  const webExtension = LegacyExtensionsUtils.getEmbeddedExtensionFor({
    id: ADDON_ID,
    resourceURI: addonResourceURI
  });
  // Immediately exit if Firefox is exiting, #3323
  if (reason === APP_SHUTDOWN) {
    stop(webExtension, reason);
    return;
  }
  // Because the prefObserver is unregistered above, this _should_ terminate the promise chain.
  appStartupPromise = appStartupPromise.then(() => { stop(webExtension, reason); });
}

function install(data, reason) {} // eslint-disable-line no-unused-vars

function uninstall(data, reason) {} // eslint-disable-line no-unused-vars

function getBoolPref(pref) {
  return prefs.getPrefType(pref) && prefs.getBoolPref(pref);
}

function shouldDisable() {
  return getBoolPref(USER_DISABLE_PREF) || getBoolPref(SYSTEM_DISABLE_PREF);
}

function handleStartup() {
  const webExtension = LegacyExtensionsUtils.getEmbeddedExtensionFor({
    id: ADDON_ID,
    resourceURI: addonResourceURI
  });

  if (!shouldDisable() && !webExtension.started) {
    return start(webExtension);
  } else if (shouldDisable()) {
    return stop(webExtension, ADDON_DISABLE);
  }
}

function start(webExtension) {
  return webExtension.startup(startupReason).then((api) => {
    api.browser.runtime.onMessage.addListener(handleMessage);
    return Promise.resolve(null);
  }).catch((err) => {
    // The startup() promise will be rejected if the webExtension was
    // already started (a harmless error), or if initializing the
    // WebExtension failed and threw (an important error).
    console.error(err);
    if (err.message !== "This embedded extension has already been started") {
      // TODO: Should we send these errors to Sentry? #2420
    }
  });
}

function stop(webExtension, reason) {
  return Promise.resolve(webExtension.shutdown(reason));
}

function handleMessage(msg, sender, sendReply) {
  if (!msg) {
    return;
  }

  if (msg.funcName === "getTelemetryPref") {
    let telemetryEnabled = getBoolPref(TELEMETRY_ENABLED_PREF);
    sendReply({type: "success", value: telemetryEnabled});
  } else if (msg.funcName === "getOldDeviceInfo") {
    let oldDeviceInfo = prefs.prefHasUserValue(OLD_ADDON_PREF_NAME) && prefs.getCharPref(OLD_ADDON_PREF_NAME);
    sendReply({type: "success", value: oldDeviceInfo || null});
  } else if (msg.funcName === "removeOldAddon") {
    AddonManager.getAddonByID(OLD_ADDON_ID, (addon) => {
      prefs.clearUserPref(OLD_ADDON_PREF_NAME);
      if (addon) {
        addon.uninstall();
      }
      sendReply({type: "success", value: !!addon});
    });
    return true;
  }
}
PK
!<\?Winstall.rdf<?xml version="1.0" encoding="UTF-8"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
  <Description about="urn:mozilla:install-manifest">
    <em:id>screenshots@mozilla.org</em:id>
    <em:name>Firefox Screenshots</em:name>
    <em:targetApplication>
      <Description>
        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!--Firefox-->
        <em:minVersion>51.0a1</em:minVersion>
        <em:maxVersion>*</em:maxVersion>
      </Description>
    </em:targetApplication>
    <em:type>2</em:type>
    <em:version>10.12.0</em:version>
    <em:bootstrap>true</em:bootstrap>
    <em:homepageURL>https://pageshot.net/</em:homepageURL>
    <em:multiprocessCompatible>true</em:multiprocessCompatible>
  </Description>
</RDF>
PK
!<0ߦ'webextension/_locales/ach/messages.json{
  "addonDescription": {
    "message": "Mak vidio ma ki ngolo macego cego ki cal me wang kio ki i Kakube ka igwok gi pi tutunu onyo matwal."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Mak cal me wang kio"
  },
  "myShotsLink": {
    "message": "Cal Na"
  },
  "screenshotInstructions": {
    "message": "Ywar onyo dii ii potbuk me yero bute. Dii ESC me juko."
  },
  "saveScreenshotSelectedArea": {
    "message": "Gwoki"
  },
  "saveScreenshotVisibleArea": {
    "message": "Gwok ma nen"
  },
  "saveScreenshotFullPage": {
    "message": "Gwok potbuk weng"
  },
  "cancelScreenshot": {
    "message": "Juki"
  },
  "downloadScreenshot": {
    "message": "Gam"
  },
  "notificationLinkCopiedTitle": {
    "message": "Ki loko kakube"
  },
  "notificationLinkCopiedDetails": {
    "message": "Ki loko kakube me cal mamegi i bao me coc. Dii $META_KEY$-V me mwono ne.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Pe tye katic."
  },
  "requestErrorDetails": {
    "message": "Timwa kica! Pe onongo wa twero gwoko cal mamegi. Tim ber item doki lacen."
  },
  "connectionErrorTitle": {
    "message": "Pe watwero kube ki cal me wang kio mamegi."
  },
  "connectionErrorDetails": {
    "message": "Tim ber i rot kakube ni me intanet. Kace itwero kube i intanet, peko mo pi tutuno romo bedo tye i tic me Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Pe onongo wa twero gwoko cal mamegi pien peko mo tye i tic me Firefox Screenshots. Tim ber item doki lacen."
  },
  "unshootablePageErrorTitle": {
    "message": "Pe watwero mako cal me wang kio me potbuk man."
  },
  "unshootablePageErrorDetails": {
    "message": "Man pe obedo Kakube me rwom, pi meno pe watwero mako cal me wang kio ne."
  },
  "selfScreenshotErrorTitle": {
    "message": "Pe itwero mako cal me potbuk pa Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Yer mamegi tidi tutwal"
  },
  "genericErrorTitle": {
    "message": "Woo! Firefox Screenshots opo oo."
  },
  "genericErrorDetails": {
    "message": "Pe wa ngeyo ngo ma otime kombedi. Iromo temo ne doki onyo mako cal pa potbuk mukene?"
  },
  "tourBodyOne": {
    "message": "Maki, gwoki, ki nywak cal me wang kio labongo weko Firefox."
  },
  "tourHeaderTwo": {
    "message": "Mak ngo ma imito keken"
  },
  "tourBodyTwo": {
    "message": "Dii ka i ywar me mako cal pa but potbuk keken. Itwero bene wot iwiye me wero yer mamegi."
  },
  "tourHeaderThree": {
    "message": "Mak dirica onyo Potbuk weng"
  },
  "tourBodyThree": {
    "message": "Yer mapeca ma i tung lacuc malo me mako kabedo ma nen i dirica onyo me mako potbuk weng."
  },
  "tourHeaderFour": {
    "message": "Kit ma imito"
  },
  "tourBodyFour": {
    "message": "Gwok cal mamegi ma ki ngolo ii Kakube pi nywako i yoo ma yot, onyo gamo gi i kompiuta ni. Itwero bene diyo mapeca me Cal Na me nongo cal ma i mako weng."
  },
  "tourSkip": {
    "message": "Kal"
  },
  "tourNext": {
    "message": "Cal malubo"
  },
  "tourPrevious": {
    "message": "Cal mukato"
  },
  "tourDone": {
    "message": "Otum"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Tic ki Firefox Screenshots nyuto, ni i yee $TERMSANDPRIVACYNOTICETERMSLINK$ ki $TERMSANDPRIVACYNOTICEPRIVACYLINK$ me tic me Cloud pa Firefox.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Cik"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Ngec me mung"
  }
}PK
!<

&webextension/_locales/ar/messages.json{
  "addonDescription": {
    "message": "خذ مقاطع و لقطات من الوب و احفظهم مؤقتًا أو دائمًا."
  },
  "addonAuthorsList": {
    "message": "موزيلا <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "خذ لقطة شاشة"
  },
  "myShotsLink": {
    "message": "لقطاتي"
  },
  "screenshotInstructions": {
    "message": "اسحب أو انقر في الصفحة لاختيار منطقة. اضغط ESC للإلغاء."
  },
  "saveScreenshotSelectedArea": {
    "message": "احفظ"
  },
  "saveScreenshotVisibleArea": {
    "message": "احفظ الجزء المرئي"
  },
  "saveScreenshotFullPage": {
    "message": "احفظ كل الصفحة"
  },
  "cancelScreenshot": {
    "message": "ألغِ"
  },
  "downloadScreenshot": {
    "message": "نزّل"
  },
  "notificationLinkCopiedTitle": {
    "message": "نُسخ الرابط"
  },
  "notificationLinkCopiedDetails": {
    "message": "نُسِخَ رابط اللقطة إلى الحافظة. اضغط $META_KEY$-V للصقها.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "خارج الخدمة."
  },
  "requestErrorDetails": {
    "message": "تعذّر حفظ لقطتك. رجاء أعد المحاولة فيما بعد."
  },
  "connectionErrorTitle": {
    "message": "تعذّر الاتصال بلقطات شاشتك."
  },
  "connectionErrorDetails": {
    "message": "رجاء فحص اتصال الإنترنت. إذا كان باستطاعتك الاتصال بالإنترنت، فربما هناك عطل مؤقت في خدمة «لقطات شاشة فَيَرفُكس»."
  },
  "loginErrorDetails": {
    "message": "تعذّر حفظ لقطتك لعُطل في خدمة «لقطات شاشة فَيَرفُكس». رجاء إعادة المحاولة لاحقًا."
  },
  "unshootablePageErrorTitle": {
    "message": "تعذّر أخذ لقطة شاشة لهذه الصفحة."
  },
  "unshootablePageErrorDetails": {
    "message": "ليست هذه صفحة وِب قياسية، لذا لا يمكنك أخذ لقطة لها."
  },
  "selfScreenshotErrorTitle": {
    "message": "لا يمكننا أخذ لقطة لصفحة من صفحات «لقطات شاشة فَيَرفُكس»!"
  },
  "emptySelectionErrorTitle": {
    "message": "التحديد صغير جدا"
  },
  "privateWindowErrorTitle": {
    "message": "لقطات الشاشة معطّلة في وضع التصفح الخاص"
  },
  "privateWindowErrorDetails": {
    "message": "نأسف على الإزعاج. نعمل على هذه الخاصية للإصدارات اللاحقة."
  },
  "genericErrorTitle": {
    "message": "هناك عطل في «لقطات شاشة فَيَرفُكس»."
  },
  "genericErrorDetails": {
    "message": "لسنا متأكدين ما المشكلة. أتمانع إعادة المحاولة أو أخذ لقطة لصفحة أخرى؟"
  },
  "tourBodyOne": {
    "message": "خذ لقطات الشاشة و احفظها و شاركها دون مغادرة فَيَرفُكس."
  },
  "tourHeaderTwo": {
    "message": "التقط ما تريده فقط"
  },
  "tourBodyTwo": {
    "message": "انقر و اسحب لالتقاط جزء معين من الصفحة. يمكنك أيضًا التحويم لإبراز التحديد."
  },
  "tourHeaderThree": {
    "message": "التقط النوافذ أو صفحات كاملة"
  },
  "tourBodyThree": {
    "message": "اختر الأزرار في أعلى اليمين لالتقاط المنطقة المرئية في النافذة أو الصفحة كلها."
  },
  "tourHeaderFour": {
    "message": "كما تريدها"
  },
  "tourBodyFour": {
    "message": "احفظ اللقطات التي أخذتها على الوب لمشاركتها بسهولة، أو نزّلها على حاسوبك. يمكنك أيضًل النقر على زر ”لقطاتي“ للعثور على كل اللقطات التي أخذتها."
  },
  "tourSkip": {
    "message": "تخطَّ"
  },
  "tourNext": {
    "message": "الشريحة التالية"
  },
  "tourPrevious": {
    "message": "الشريحة السابقة"
  },
  "tourDone": {
    "message": "تمّ"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "استخدامك لخدمات «لقطات شاشة فَيَرفُكس» يعني موافقتك على $TERMSANDPRIVACYNOTICETERMSLINK$ و $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "الشروط"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "تنويه الخصوصية"
  }
}PK
!<NZ&webextension/_locales/az/messages.json{
  "addonDescription": {
    "message": "Web səhifələrin ekran görüntülərini alın, müvəqqəti və ya qalıcı saxlayın."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Ekran görüntüsü al"
  },
  "myShotsLink": {
    "message": "Ekran Görüntülərim"
  },
  "screenshotInstructions": {
    "message": "Səhifədə hər hansı bir yerdə sürüşdürərək və ya basaraq ərazini seçin. Ləğv etmək üçün ESC basın."
  },
  "saveScreenshotSelectedArea": {
    "message": "Saxla"
  },
  "saveScreenshotVisibleArea": {
    "message": "Görünən ərazini saxla"
  },
  "saveScreenshotFullPage": {
    "message": "Tam səhifəni saxla"
  },
  "cancelScreenshot": {
    "message": "Ləğv et"
  },
  "downloadScreenshot": {
    "message": "Endir"
  },
  "notificationLinkCopiedTitle": {
    "message": "Keçid köçürüldü"
  },
  "notificationLinkCopiedDetails": {
    "message": "Ekran görüntüsünün keçidi buferə köçürüldü. Yapışdırmaq üçün $META_KEY$-V basın.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Xəta baş verdi."
  },
  "requestErrorDetails": {
    "message": "Üzr istəyirik! Ekran görüntünüzü saxlaya bilmədik. Lütfən biraz sonra təkrar yoxlayın."
  },
  "connectionErrorTitle": {
    "message": "Ekran görüntülərinizə qoşula bilmirik."
  },
  "connectionErrorDetails": {
    "message": "Lütfən internet bağlantınızı yoxlayın. Əgər internetdə problem yoxdursa Firefox Screenshots xidmətində müvəqqəti xəta ola bilər."
  },
  "loginErrorDetails": {
    "message": "Firefox Screenshots xidmətindəki müvəqqəti xəta üzündən ekran görüntünüzü saxlaya bilmədik. Lütfən biraz sonra təkrar yoxlayın."
  },
  "unshootablePageErrorTitle": {
    "message": "Bu səhifənin ekran görüntüsü alına bilmir."
  },
  "unshootablePageErrorDetails": {
    "message": "Bu normal Web səhifəsi deyil, bu səbəbdən ekran görüntüsünü almaq mümkün olmur."
  },
  "selfScreenshotErrorTitle": {
    "message": "Firefox Screenshots səhifəsinin ekran görüntüsünü ala bilməzsiz!"
  },
  "emptySelectionErrorTitle": {
    "message": "Seçiminiz çox balacadır"
  },
  "privateWindowErrorTitle": {
    "message": "Ekran görüntüləri Məxfi Səyahət rejimində sönülüdür"
  },
  "privateWindowErrorDetails": {
    "message": "Narahatlıq üçün üzr istəyirik. Gələcək buraxılışlarda bu özəllik üzərində işləyirik."
  },
  "genericErrorTitle": {
    "message": "Off! Firefox Screenshots dəli olub."
  },
  "genericErrorDetails": {
    "message": "Nə baş verdiyindən əmin deyilik. Bir daha yoxlayın və ya başqa səhifənin ekran görüntüsünü alaraq işləyib işləmədiyinə əmin olun."
  },
  "tourBodyOne": {
    "message": "Firefoxu tərk etmədən ekran görüntüləri alın, saxlayın və paylaşın."
  },
  "tourHeaderTwo": {
    "message": "İstədiyiniz hər şeyin görüntüsünü alın"
  },
  "tourBodyTwo": {
    "message": "Səhifənin hər hansı bir hissəsini almaq üçün basın və ya sürüşdürün. Seçiminizi işıqlandırmaq üçün üzərinə gedin."
  },
  "tourHeaderThree": {
    "message": "Pəncərəni və ya bütün səhifəni çəkin"
  },
  "tourBodyThree": {
    "message": "Sadəcə pəncərədə görünən hissəni və ya bütün səhifəni çəkmək üçün sağ üstdəki düymələrdən birini seçin."
  },
  "tourHeaderFour": {
    "message": "İstədiyiniz kimi"
  },
  "tourBodyFour": {
    "message": "Kəsdiyiniz hissələri rahat paylaşmaq üçün internetdə saxlayın və ya kompüterinizə endirin. Həmçinin Ekran Görüntülərim düyməsinə basaraq çəkdiyiniz bütün ekran görüntülərini görə bilərsiz."
  },
  "tourSkip": {
    "message": "Ötür"
  },
  "tourNext": {
    "message": "Növbəti Slayd"
  },
  "tourPrevious": {
    "message": "Əvvəlki Slayd"
  },
  "tourDone": {
    "message": "Tamamlandı"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Firefox Screenshots işlədərək $TERMSANDPRIVACYNOTICETERMSLINK$ və $TERMSANDPRIVACYNOTICEPRIVACYLINK$ ilə razılaşmış olursunuz.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Şərtlər"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Məxfilik Bildirişi"
  }
}PK
!<#i&webextension/_locales/be/messages.json{
  "addonDescription": {
    "message": "Рабіце кліпы і здымкі экрана ў Сеціве і захоўвайце іх часова або назаўжды."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Зрабіць здымак экрана"
  },
  "myShotsLink": {
    "message": "Мае здымкі"
  },
  "screenshotInstructions": {
    "message": "Пацягніце або пстрыкніце на старонцы для выбару вобласці. Для адмены націсніце ESC."
  },
  "saveScreenshotSelectedArea": {
    "message": "Захаваць"
  },
  "saveScreenshotVisibleArea": {
    "message": "Захаваць бачную вобласць"
  },
  "saveScreenshotFullPage": {
    "message": "Захаваць усю старонку"
  },
  "cancelScreenshot": {
    "message": "Скасаваць"
  },
  "downloadScreenshot": {
    "message": "Сцягнуць"
  },
  "notificationLinkCopiedTitle": {
    "message": "Спасылка скапіявана"
  },
  "notificationLinkCopiedDetails": {
    "message": "Спасылка на ваш здымак была скапіявана ў буфер абмену. Націсніце $META_KEY$-V для ўстаўкі.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Адбылася памылка."
  },
  "requestErrorDetails": {
    "message": "Выбачайце! Нам не ўдалося захаваць ваш здымак. Паспрабуйце пазней."
  },
  "connectionErrorTitle": {
    "message": "Мы не можам атрымаць доступ да вашых скрыншотаў."
  },
  "connectionErrorDetails": {
    "message": "Калі ласка, праверце ваша злучэнне з Інтэрнэтам. Калі ў вас усё ў парадку з падлучэннем да Інтэрнэту, магчыма, паўсталі часовыя праблемы са службай Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Нам не ўдалося захаваць ваш здымак, таму што ўзніклі праблемы са службай Firefox Screenshots. Паспрабуйце пазней."
  },
  "unshootablePageErrorTitle": {
    "message": "Мы не можам зрабіць скрыншот гэтай старонкі."
  },
  "unshootablePageErrorDetails": {
    "message": "Гэта не стандартная вэб-старонка, таму вы не можаце зрабіць яе скрыншот."
  },
  "selfScreenshotErrorTitle": {
    "message": "Вы не можаце зрабіць здымак старонкі Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Абраная вобласць занадта малая"
  },
  "privateWindowErrorTitle": {
    "message": "Здымкі экрана адключаны ў рэжыме прыватнага аглядання"
  },
  "privateWindowErrorDetails": {
    "message": "Прабачце за нязручнасць. Мы працуем над даданнем гэтай магчымасці у будучыя выпускі."
  },
  "genericErrorTitle": {
    "message": "Вой! З Firefox Screenshots нешта не так."
  },
  "genericErrorDetails": {
    "message": "Мы не ўпэўненыя, у чым праблема. Паспрабаваць яшчэ раз, ці зрабіць здымак іншай старонкі?"
  },
  "tourBodyOne": {
    "message": "Рабіце здымкі экрана, захоўвайце і дзяліцеся імі не выходзячы з Firefox."
  },
  "tourHeaderTwo": {
    "message": "Рабіце скрыншоты чаго заўгодна"
  },
  "tourBodyTwo": {
    "message": "Пстрыкніце і пацягніце мышшу для захопу часткі старонкі. Вы таксама можаце навесці курсор мышы для падсвятлення абранай вобласці."
  },
  "tourHeaderThree": {
    "message": "Рабіце захоп вокнаў або цэлых старонак"
  },
  "tourBodyThree": {
    "message": "З дапамогай кнопак у верхнім правым куце выбірайце захоп бачнай вобласці акна або старонкі цалкам."
  },
  "tourHeaderFour": {
    "message": "Як вам падабаецца"
  },
  "tourBodyFour": {
    "message": "Захоўваеце свае здымкі ў Інтэрнэце, каб лёгка імі дзяліцца, або загружайце іх на свой камп'ютар. Вы таксама можаце прагледзець усе захаваныя здымкі, націснуўшы на кнопку Мае здымкі."
  },
  "tourSkip": {
    "message": "Прапусьціць"
  },
  "tourNext": {
    "message": "Наступны слайд"
  },
  "tourPrevious": {
    "message": "Папярэдні слайд"
  },
  "tourDone": {
    "message": "Гатова"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Выкарыстоўваючы Firefox Screenshots, вы згаджаецеся з $TERMSANDPRIVACYNOTICETERMSLINK$ і $TERMSANDPRIVACYNOTICEPRIVACYLINK$ Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Умовамі выкарыстання"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Паведамленнем аб прыватнасці"
  }
}PK
!<Q[[&webextension/_locales/bg/messages.json{
  "addonDescription": {
    "message": "Прави клипове и снимки на уебстраница и ги запазва временно или за постоянно."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Снимка на екрана"
  },
  "myShotsLink": {
    "message": "Моите снимки"
  },
  "screenshotInstructions": {
    "message": "За да изберете участък влачете или щракнете с мишката в страницата. Натиснете ESC за отказ."
  },
  "saveScreenshotSelectedArea": {
    "message": "Запазване"
  },
  "saveScreenshotVisibleArea": {
    "message": "Запазване на видимата област"
  },
  "saveScreenshotFullPage": {
    "message": "Запазване на цялата страница"
  },
  "cancelScreenshot": {
    "message": "Отказ"
  },
  "downloadScreenshot": {
    "message": "Изтегляне"
  },
  "notificationLinkCopiedTitle": {
    "message": "Препратката е копирана"
  },
  "notificationLinkCopiedDetails": {
    "message": "Препратка към снимката е копирана в системния буфер. За да я поставите натиснете $META_KEY$-V.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Повреда."
  },
  "requestErrorDetails": {
    "message": "Съжаляваме! Снимката не е запазена. Опитайте по-късно."
  },
  "connectionErrorTitle": {
    "message": "Няма връзка с вашите снимки."
  },
  "connectionErrorDetails": {
    "message": "Моля, проверете своята връзка към интернет. Ако имате връзка с Мрежата, в такъв случай може да има временен проблем с услугата на Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Снимката не може да бъде запазена, защото има проблем с услугата на Firefox Screenshots. Опитайте по-късно."
  },
  "unshootablePageErrorTitle": {
    "message": "Снимка на тази страница не може да бъде направена."
  },
  "unshootablePageErrorDetails": {
    "message": "Това не е обикновена уебстраница и за това снимка не може да ѝ бъде направена."
  },
  "selfScreenshotErrorTitle": {
    "message": "Не може да правите снимки на страницата на Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Избраната област е твърде малка"
  },
  "privateWindowErrorTitle": {
    "message": "Правене на снимки е изключено в поверителен режим"
  },
  "privateWindowErrorDetails": {
    "message": "Съжаляваме за неудобството. Очаквайте тази възможност в бъдещите версии."
  },
  "genericErrorTitle": {
    "message": "Леле! Нещо се обърка с Firefox Screenshots."
  },
  "genericErrorDetails": {
    "message": "Не сме сигурни какво точно се случи. Може да опитате отново, както и да снимате друга страница."
  },
  "tourBodyOne": {
    "message": "Правете, запазвайте и споделяйте снимки на екрана без да напускате Firefox."
  },
  "tourHeaderTwo": {
    "message": "Уловете само нужното"
  },
  "tourBodyTwo": {
    "message": "Щракнете с мишката или влачете, за да уловите части от страницата. А когато посочите елементи от страницата – те се осветяват."
  },
  "tourHeaderThree": {
    "message": "Улавяйте прозорци и цели страници"
  },
  "tourBodyThree": {
    "message": "Използвайте бутоните в горния десен ъгъл, за да уловите само видимата част или цялата страница."
  },
  "tourHeaderFour": {
    "message": "Както ви харесва"
  },
  "tourBodyFour": {
    "message": "Запазвайте снимките на страници от Мрежата, за да ги споделяте по-лесно или ги изтегляйте на компютъра си. А бутонът „Моите снимки“ ще ви покаже всички направени от вас снимки."
  },
  "tourSkip": {
    "message": "Пропускане"
  },
  "tourNext": {
    "message": "Напред"
  },
  "tourPrevious": {
    "message": "Назад"
  },
  "tourDone": {
    "message": "Готово"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Използвайки Firefox Screenshots вие се съгласявате с $TERMSANDPRIVACYNOTICETERMSLINK$ и $TERMSANDPRIVACYNOTICEPRIVACYLINK$ на облачните услуги на Firefox.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Условията"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Политиката на поверителност"
  }
}PK
!<Zj  )webextension/_locales/bn_BD/messages.json{
  "addonDescription": {
    "message": "ওয়েব থেকে ক্লিপ এবং স্ক্রিনশট নিন এবং সেগুলো সাময়িকভাবে বা স্থায়ীভাবে সংরক্ষণ করুন।"
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "একটি স্ক্রীনশট নিন"
  },
  "myShotsLink": {
    "message": "আমার সটসমূহ"
  },
  "screenshotInstructions": {
    "message": "ড্রাগ করে অথবা পেজে ক্লিক করে একটি অংশ নির্বাচন করুন। বাতিল করতে ESC টিপুন।"
  },
  "saveScreenshotSelectedArea": {
    "message": "সংরক্ষণ"
  },
  "saveScreenshotVisibleArea": {
    "message": "যতটুকু দেখা যাচ্ছে সংরক্ষণ করুন"
  },
  "saveScreenshotFullPage": {
    "message": "সম্পূর্ণ পেজ সংরক্ষণ করুন"
  },
  "cancelScreenshot": {
    "message": "বাতিল"
  },
  "downloadScreenshot": {
    "message": "ডাউনলোড"
  },
  "notificationLinkCopiedTitle": {
    "message": "লিঙ্ক কপি করা হয়েছে"
  },
  "notificationLinkCopiedDetails": {
    "message": "আপার সট এর লিংক ক্লিপবোর্ডে কপি করা হয়েছে। পেস্ট করতে $META_KEY$-V চাপুন।",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "বিকল।"
  },
  "requestErrorDetails": {
    "message": "দুঃখিত! আমরা আপনার সট সংরক্ষণ করতে পারিনি। অনুগ্রহ পুনরায় চেষ্টা করুন।"
  },
  "connectionErrorTitle": {
    "message": "আমরা আপনার স্ক্রিটসটসমূহ সংযোগ করতে পারছি না।"
  },
  "connectionErrorDetails": {
    "message": "অনুগ্রহ করে আপনার ইন্টারনেট সংযোগ পরীক্ষা করুন। আর যদি আপনার ইন্টারনেট সংযোগ ঠিক থাকে, তাহলে Firefox স্ক্রিনশট সেবাটিতে সাময়িক সমস্যা দেখা দিয়েছে।"
  },
  "loginErrorDetails": {
    "message": "আমরা আপনার শট সংরক্ষণ করতে পারিনি কারণ সেখানে Firefox স্ক্রিণশট সেবার সমস্যা আছে। অনুগ্রহ করে আবার চেস্টা করুন।"
  },
  "unshootablePageErrorTitle": {
    "message": "আমার এই পেজের স্ক্রিনশট নিতে পারব না।"
  },
  "unshootablePageErrorDetails": {
    "message": "এটা কোন আদর্শ ওয়েব পেজ না, তাই আপনি এটার স্ক্রিনশট তুলতে পারবেন না।"
  },
  "selfScreenshotErrorTitle": {
    "message": "আপনি Firefox স্ক্রিনশটের পেজের শট নিতে পারেন না!"
  },
  "emptySelectionErrorTitle": {
    "message": "আপনি অল্প স্থান নির্বাচন করেছেন"
  },
  "privateWindowErrorTitle": {
    "message": "ব্যক্তিগত ব্রাউজিং মোডে স্ক্রিনশট নেওয়া নিস্ক্রিয় করা হয়েছে"
  },
  "privateWindowErrorDetails": {
    "message": "অসুবিধার জন্য দুঃখিত। আমরা এই বৈশিষ্ট্যটি নিয়ে কাজ করছি, খুব শীঘ্রই রিলিজ করা হবে।"
  },
  "genericErrorTitle": {
    "message": "আয় হায়! Firefox স্ক্রিনশট পাগল হয়ে গেছে।"
  },
  "genericErrorDetails": {
    "message": "এই মাত্র কি ঘটেছে আমরা নিশ্চিত নই। আপনি কি অনুগ্রহ করে পুরনায় সট নেবেন কিংবা ভিন্ন একটি পেজে চেষ্টা করবেন?"
  },
  "tourBodyOne": {
    "message": "Firefox ত্যাগ করা ছাড়াই স্ক্রিনশট তোল, সংরক্ষণ কর এবং শেয়ার কর।"
  },
  "tourHeaderTwo": {
    "message": "ক্যাপচার করুন আপনি যা চান"
  },
  "tourBodyTwo": {
    "message": "একটি পেজের কিয়দংশ ক্যাপচার করতে ক্লিক করে ড্রাগ করুন। অতঃপর আপনি মাউজ হোভার করে আপনার নির্বাচিত অংশ হাইলাইট করতে পারবেন।"
  },
  "tourHeaderThree": {
    "message": "উইন্ডো ক্যাপচার করুন অথবা পুরো পেজ"
  },
  "tourBodyThree": {
    "message": "ইউন্ডোতে দৃশ্যমান অংশ অথবা সম্পূর্ণ পেজ ক্যাপচার করতে উপরে ডানদিকের বাটনগুলো থেকে নির্বাচন করুন।"
  },
  "tourHeaderFour": {
    "message": "আপনি যেমন পছন্দ করেন"
  },
  "tourBodyFour": {
    "message": "আপনার ক্রপ করা সটসমূহ ওয়েবে রাখুন সহজে শেয়ার করার সুবিধার্থে, অথবা আপনার কম্পিউটারে ডাউনলোড করুন। আপনার সকল সটসমূহ খুঁজে পেতে আমার সটসমূহ বাটনে ক্লিক করুন।"
  },
  "tourSkip": {
    "message": "এড়িয়ে যান"
  },
  "tourNext": {
    "message": "পরবর্তী স্লাইড"
  },
  "tourPrevious": {
    "message": "পূর্ববর্তী স্লাইড"
  },
  "tourDone": {
    "message": "সম্পন্ন"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Firefox Screenshots ব্যবহারে, আপনি Firefox Cloud Services এর $TERMSANDPRIVACYNOTICETERMSLINK$ এবং $TERMSANDPRIVACYNOTICEPRIVACYLINK$ নীতিতে সম্মত হয়েছেন।",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "শর্তাবলী"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "গোপনীয়তা নীতি"
  }
}PK
!<-2II&webextension/_locales/ca/messages.json{
  "addonDescription": {
    "message": "Feu captures de pantalla de pàgines web i deseu-les temporalment o per sempre."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Fes una captura de pantalla"
  },
  "myShotsLink": {
    "message": "Les meves captures"
  },
  "screenshotInstructions": {
    "message": "Arrossegueu o feu clic a la pàgina per seleccionar una regió. Premeu ESC per cancel·lar."
  },
  "saveScreenshotSelectedArea": {
    "message": "Desa"
  },
  "saveScreenshotVisibleArea": {
    "message": "Captura la part visible"
  },
  "saveScreenshotFullPage": {
    "message": "Captura tota la pàgina"
  },
  "cancelScreenshot": {
    "message": "Cancel·la"
  },
  "downloadScreenshot": {
    "message": "Baixa"
  },
  "notificationLinkCopiedTitle": {
    "message": "S'ha copiat l'enllaç"
  },
  "notificationLinkCopiedDetails": {
    "message": "L'enllaç de la captura s'ha copiat al porta-retalls. Premeu $META_KEY$-V per enganxar-lo.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "No funciona."
  },
  "requestErrorDetails": {
    "message": "Malauradament, s'ha pogut desar la vostra captura. Torneu a provar més tard."
  },
  "connectionErrorTitle": {
    "message": "No s'ha pogut accedir a les vostres captures de pantalla."
  },
  "connectionErrorDetails": {
    "message": "Comproveu la connexió a Internet. Si podeu connectar-vos a Internet, podria ser un problema temporal del servei del Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "No s'ha pogut desar la vostra captura perquè hi ha un problema amb el servei del Firefox Screenshots. Torneu-ho a provar més tard."
  },
  "unshootablePageErrorTitle": {
    "message": "No es pot fer una captura de pantalla d'aquesta pàgina."
  },
  "unshootablePageErrorDetails": {
    "message": "No podeu fer una captura de pantalla perquè aquesta no és una pàgina web estàndard."
  },
  "selfScreenshotErrorTitle": {
    "message": "No podeu fer una captura de pantalla de la pàgina del Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "La selecció és massa petita"
  },
  "privateWindowErrorTitle": {
    "message": "Les captures de pantalla estan desactivades en el mode de navegació privada"
  },
  "privateWindowErrorDetails": {
    "message": "Perdoneu les molèsties. Estem treballant en aquesta característica per a versions futures."
  },
  "genericErrorTitle": {
    "message": "El Firefox Screenshots ha tingut un problema."
  },
  "genericErrorDetails": {
    "message": "S'ha produït un error inesperat. Torneu-ho a provar o captureu una altra pàgina."
  },
  "tourBodyOne": {
    "message": "Feu, deseu i compartiu captures de pantalla sense sortir del Firefox."
  },
  "tourHeaderTwo": {
    "message": "Captureu tot allò que vulgueu"
  },
  "tourBodyTwo": {
    "message": "Feu clic i arrossegueu per capturar només una part de la pàgina. També podeu moure el ratolí per sobre per ressaltar la vostra selecció."
  },
  "tourHeaderThree": {
    "message": "Captureu la finestra o la pàgina sencera"
  },
  "tourBodyThree": {
    "message": "Seleccioneu amb els botons de la part superior dreta si voleu capturar l'àrea visible de la finestra o la pàgina sencera."
  },
  "tourHeaderFour": {
    "message": "Com vulgueu"
  },
  "tourBodyFour": {
    "message": "Deseu les vostres captures al web per compartir-les fàcilment o baixeu-les a l'ordinador. També podeu fer clic al botó «Les meves captures» per veure totes les captures que heu fet."
  },
  "tourSkip": {
    "message": "OMET"
  },
  "tourNext": {
    "message": "Diapositiva següent"
  },
  "tourPrevious": {
    "message": "Diapositiva anterior"
  },
  "tourDone": {
    "message": "Fet"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Si utilitzeu el Firefox Screenshots, esteu acceptant les nostres $TERMSANDPRIVACYNOTICETERMSLINK$ i l'$TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "condicions d'ús"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "avís de privadesa"
  }
}PK
!<//'webextension/_locales/cak/messages.json{
  "addonDescription": {
    "message": "Ke'achapa' silowachib'al chuqa' chapoj wachib'äl pan Ajk'amaya'l richin ye'ayäk."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Tichap jun Chapoj Wachib'äl"
  },
  "myShotsLink": {
    "message": "Taq Nuwachib'al"
  },
  "screenshotInstructions": {
    "message": "Taqirirej o tapitz'a' ri ruxaq richin nacha' ri k'ojlem. Tapitz'a' ESC richin niq'at."
  },
  "saveScreenshotSelectedArea": {
    "message": "Tiyak"
  },
  "saveScreenshotVisibleArea": {
    "message": "Tiyak wachel"
  },
  "saveScreenshotFullPage": {
    "message": "Tiyak chijun ruxaq"
  },
  "cancelScreenshot": {
    "message": "Tiq'at"
  },
  "downloadScreenshot": {
    "message": "Tiqasäx"
  },
  "notificationLinkCopiedTitle": {
    "message": "Ximonel Wachib'en"
  },
  "notificationLinkCopiedDetails": {
    "message": "Xwachib'ëx pa molwuj ri ruximonel awachib'al. Tapitz'a' $META_KEY$-V richin natz'äm.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Man nisamäj ta."
  },
  "requestErrorDetails": {
    "message": "¡Takuyu! Man yojtikïr ta niqayäk ri awachib'al. Tatojtob'ej jumej."
  },
  "connectionErrorTitle": {
    "message": "Man yojtikïr ta yojok pari taq chapoj awachib'al."
  },
  "connectionErrorDetails": {
    "message": "Tanik'oj awokem pa K'amaya'l. We yatok pa K'amaya'l, rik'in jub'a' xtuya' k'ayewal pa rusamaj ri Firefox taq Chapoj Wachib'äl."
  },
  "loginErrorDetails": {
    "message": "Man xkatikïr ta xtayäk ri awachib'al ruma jun ruk'ayewal toq nisamäj ri Firefox Chapoj Wachib'äl. Tatojtob'ej chik pa jun mej."
  },
  "unshootablePageErrorTitle": {
    "message": "Man yojtikïr ta nichap ruwachib'al re ruxaq re'."
  },
  "unshootablePageErrorDetails": {
    "message": "Re re' man pa rub'eyal ta chi ruxaq Ajk'amaya'l, ruma ri' man yojtikïr ta niqachäp ruwachib'al."
  },
  "selfScreenshotErrorTitle": {
    "message": "¡Man yatikïr ta nawelesaj ruwachib'al jun ruxaq Firefox Chapoj Wachib'äl!"
  },
  "emptySelectionErrorTitle": {
    "message": "Yalan ko'öl ri acha'oj"
  },
  "privateWindowErrorTitle": {
    "message": "Echupun ri Chapoj taq Wachib'äl pa Ichinan Okem pa K'amaya'l"
  },
  "privateWindowErrorDetails": {
    "message": "Takuyu' chi qe ruma ri k'ayewal. Tajin niqasamajij re rub'anikil re' richin ri ch'aqa' chik taq ruwäch."
  },
  "genericErrorTitle": {
    "message": "¡Itz! Itzel xe'el ri Firefox Chapoj Wachib'äl."
  },
  "genericErrorDetails": {
    "message": "Man öj jikïl chi rij ri xk'ulwachitäj. ¿La nawajo' natojtob'ej chik o nachäp ruwachib'al jun chik ruxaq?"
  },
  "tourBodyOne": {
    "message": "Ke'achapa', ke'ayaka', chuqa' ke'akomonij chapoj taq wachib'äl rik'in man yatel ta el pa Firefox."
  },
  "tourHeaderTwo": {
    "message": "Tachapa' ri Nawajo'"
  },
  "tourBodyTwo": {
    "message": "Tapitz'a' chuqa' taqirirej richin nacha' xa jun peraj ruxaq. Chuqa' yatikïr yaq'axaj richin nipe retal ri acha'oj."
  },
  "tourHeaderThree": {
    "message": "Chapoj Tzuwäch o Tz'aqät taq Ruxaq"
  },
  "tourBodyThree": {
    "message": "Ke'acha' ri ikim ajkiq'a' taq pitz'b'äl richin nachäp ri tz'etel ruk'ojlem tzuwäch o richin nachäp jun tz'aqät ruxaq."
  },
  "tourHeaderFour": {
    "message": "Achi'el Niqa Chawäch"
  },
  "tourBodyFour": {
    "message": "Ke'ayaka' ri qupin taq awachib'al pa ajk'amaya'l richin man k'ayew ta ye'akomonij o ye'aqasaj pan akematz'ib'. Chuqa' yatikïr napïtz ri Taq Nuwachib'al richin ye'awïl konojel ri taq wachib'al e'elesan."
  },
  "tourSkip": {
    "message": "SKIP"
  },
  "tourNext": {
    "message": "Jun chik Q'axewäch"
  },
  "tourPrevious": {
    "message": "Jun kan Q'axewäch"
  },
  "tourDone": {
    "message": "Xb'an"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Rik'in rokisaxik ri Firefox Chapoj Wachib'äl, nawoqaj $TERMSANDPRIVACYNOTICETERMSLINK$ chuqa' $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Taq ojqanem"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Rutzijol Ichinanem"
  }
}PK
!<hU?``&webextension/_locales/cs/messages.json{
  "addonDescription": {
    "message": "Pořizujte snímky webových stránek a ukládejte je dočasně nebo natrvalo."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Pořídit snímek stránky"
  },
  "myShotsLink": {
    "message": "Mé snímky"
  },
  "screenshotInstructions": {
    "message": "Oblast vyberete kliknutím nebo tahem myší. Pro zrušení stiskněte ESC."
  },
  "saveScreenshotSelectedArea": {
    "message": "Uložit"
  },
  "saveScreenshotVisibleArea": {
    "message": "Uložit viditelnou oblast"
  },
  "saveScreenshotFullPage": {
    "message": "Uložit celou stránku"
  },
  "cancelScreenshot": {
    "message": "Zrušit"
  },
  "downloadScreenshot": {
    "message": "Stáhnout"
  },
  "notificationLinkCopiedTitle": {
    "message": "Odkaz zkopírován"
  },
  "notificationLinkCopiedDetails": {
    "message": "Odkaz na váš snímek byl zkopírován do schránky. Pro vložení stiskněte $META_KEY$-V.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Mimo provoz."
  },
  "requestErrorDetails": {
    "message": "Je nám líto, ale nemohli jsme vás snímek uložit. Zkuste to prosím znovu později."
  },
  "connectionErrorTitle": {
    "message": "Nedaří se nám připojit k vašim snímkům."
  },
  "connectionErrorDetails": {
    "message": "Zkontrolujte prosím připojení k internetu. Pokud vám připojení funguje, mohlo dojít k dočasnému problému s naší službou Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Nemohli jsme uložit váš snímek, protože došlo k problému se službou Firefox Screenshots. Zkuste to prosím znovu později."
  },
  "unshootablePageErrorTitle": {
    "message": "Snímek této stránky nelze pořídit."
  },
  "unshootablePageErrorDetails": {
    "message": "Toto není běžná webová stránka, a proto z ní nelze pořizovat žádné snímky."
  },
  "selfScreenshotErrorTitle": {
    "message": "Nelze pořizovat snímek stránky Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Vybraná oblast je moc malá"
  },
  "privateWindowErrorTitle": {
    "message": "Služba Firefox Screenshots je v anonymním prohlížení vypnutá"
  },
  "privateWindowErrorDetails": {
    "message": "Omlouváme se za nepříjemnosti. Na této funkci pracujeme pro některé příští vydání."
  },
  "genericErrorTitle": {
    "message": "Jejda! Služba Firefox Screenshots přestala pracovat."
  },
  "genericErrorDetails": {
    "message": "Nejsme si jistí, co se právě stalo. Chcete to zkusit znovu, nebo zkusíte pořídit snímek na jiné stránce?"
  },
  "tourBodyOne": {
    "message": "Pořizujte, ukládejte a sdílejte snímky webových stránek bez opuštění Firefoxu."
  },
  "tourHeaderTwo": {
    "message": "Zachyťte, cokoliv chcete"
  },
  "tourBodyTwo": {
    "message": "Stiskem tlačítka myši a tahem můžete vybrat oblast stránky. Výběr můžete provést také najetím myši na prvek stránky."
  },
  "tourHeaderThree": {
    "message": "Pořizujte snímky jen částí nebo i celých stránek"
  },
  "tourBodyThree": {
    "message": "Pomocí tlačítek vpravo nahoře můžete pořídit snímek jen viditelné části nebo úplně celé stránky."
  },
  "tourHeaderFour": {
    "message": "Jak sami chcete"
  },
  "tourBodyFour": {
    "message": "Uložte si oříznutý snímek stránky na web pro rychlejší sdílení, nebo si ho stáhněte do počítače. Pro zobrazení všech snímků stačí klepnout na tlačítko Mé snímky."
  },
  "tourSkip": {
    "message": "Přeskočit"
  },
  "tourNext": {
    "message": "Další snímek"
  },
  "tourPrevious": {
    "message": "Předchozí snímek"
  },
  "tourDone": {
    "message": "Hotovo"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Používáním služby Firefox Screenshots souhlasíte s $TERMSANDPRIVACYNOTICETERMSLINK$ a $TERMSANDPRIVACYNOTICEPRIVACYLINK$ Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "podmínkami"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "zásadami ochrany osobních údajů"
  }
}PK
!<y>]uu&webextension/_locales/cy/messages.json{
  "addonDescription": {
    "message": "Cymrwch clipiau a lluniau sgrin o'r We a'u cadw dros dro neu'n barhaol."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Cymryd Llun Sgrin Screenshot"
  },
  "myShotsLink": {
    "message": "Fy Lluniau Sgrin"
  },
  "screenshotInstructions": {
    "message": "Llusgwch neu glicio ar y dudalen i ddewis adran. Pwyso ESC i ddiddymu."
  },
  "saveScreenshotSelectedArea": {
    "message": "Cadw"
  },
  "saveScreenshotVisibleArea": {
    "message": "Cadw'r gweladwy"
  },
  "saveScreenshotFullPage": {
    "message": "Cadw tudalen lawn"
  },
  "cancelScreenshot": {
    "message": "Diddymu"
  },
  "downloadScreenshot": {
    "message": "Llwytho i Lawr"
  },
  "notificationLinkCopiedTitle": {
    "message": "Dolen wedi ei Chadw"
  },
  "notificationLinkCopiedDetails": {
    "message": "Mae'r ddolen i'ch llun wedi ei gopïo i'r clipfwrdd. Pwyswch $META_KEY$-V i'w ludo.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Ddim yn gweithio."
  },
  "requestErrorDetails": {
    "message": "Ymddiheuriadau! Nid oedd modd cadw eich llun. Ceisiwch eto'n hwyrach."
  },
  "connectionErrorTitle": {
    "message": "Nid oes modd i ni gysylltu a'ch lluniau sgrin."
  },
  "connectionErrorDetails": {
    "message": "Gwiriwch eich cysylltiad Rhyngrwyd. Os ydych yn gallu cysylltu â'r Rhyngrwyd, efallai bod anhawster dros dro gyda gwasanaeth lluniau sgrin, Firefox Screnshots."
  },
  "loginErrorDetails": {
    "message": "Nid oedd modd i ni gadw eich llun gan fod yna anhawster gyda gwasanaeth Firefox Screenshots. Ceisiwch eto'n hwyrach."
  },
  "unshootablePageErrorTitle": {
    "message": "Nid oes modd tynnu llun sgrin o'r dudalen."
  },
  "unshootablePageErrorDetails": {
    "message": "Nid yw hwn yn dudalen Gwe safonol, felly does dim modd tynnu llun sgrin ohono."
  },
  "selfScreenshotErrorTitle": {
    "message": "Nid oes modd cymryd llun o dudalen lluniau sgrin Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Mae eich dewis yn rhy fach"
  },
  "privateWindowErrorTitle": {
    "message": "Mae Screenshot wedi ei analluogi yn y Modd Pori Preifat"
  },
  "privateWindowErrorDetails": {
    "message": "Ymddiheuriadau am yr anhwylustod. Rydym yn gweithio ar y nodwedd hwn ar gyfer fersiynau'r dyfodol."
  },
  "genericErrorTitle": {
    "message": "Www! Mae Firefox Screenshots wedi mynd yn hurt."
  },
  "genericErrorDetails": {
    "message": "Nid ydym yn gwybod beth sydd wedi ddigwydd. Ceisiwch eto neu dynnu llun o dudalen wahanol?"
  },
  "tourBodyOne": {
    "message": "Cymryd, cadw a rhannu lluniau sgrin heb adael Firefox."
  },
  "tourHeaderTwo": {
    "message": "Cipio Dim ond Beth Rydych ei Angen"
  },
  "tourBodyTwo": {
    "message": "Cliciwch a llusgo i gipio rhan o dudalen. Gallwch hofran i amlygu eich dewis."
  },
  "tourHeaderThree": {
    "message": "Cipio Ffenestri neu Dudalennau Cyfan"
  },
  "tourBodyThree": {
    "message": "Dewiswch y botymau ar y dde uchod i gipio ardal gweladwy mewn ffenestr neu i gipio tudalen gyfan."
  },
  "tourHeaderFour": {
    "message": "Yn Ôl eich Dewis"
  },
  "tourBodyFour": {
    "message": "Cadwch eich lluniau wedi eu golygu i'r We ar gyfer rhannu haws, neu eu llwytho i lawr i'ch cyfrifiadur. Gallwch hefyd glicio ar Fy Lluniau i weld pob llun sydd gennych."
  },
  "tourSkip": {
    "message": "SKIP"
  },
  "tourNext": {
    "message": "Sleid Nesaf"
  },
  "tourPrevious": {
    "message": "Sleid Flaenorol"
  },
  "tourDone": {
    "message": "Gorffen"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Drwy ddefnyddio Firefox Screenshots, rydych yn cytuno i Firefox Cloud Services $TERMSANDPRIVACYNOTICETERMSLINK$ a $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Telerau"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Hysbysiad Preifatrwydd"
  }
}PK
!<?E00&webextension/_locales/da/messages.json{
  "addonDescription": {
    "message": "Tag udklip og skærmbilleder fra nettet og gem dem midlertidigt eller permanent."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Tag et skærmbillede"
  },
  "myShotsLink": {
    "message": "Mine skærmbilleder"
  },
  "screenshotInstructions": {
    "message": "Træk eller klik på siden for at vælge et område. Tryk på ESC for at fortryde."
  },
  "saveScreenshotSelectedArea": {
    "message": "Gem"
  },
  "saveScreenshotVisibleArea": {
    "message": "Gem synligt område"
  },
  "saveScreenshotFullPage": {
    "message": "Gem hele siden"
  },
  "cancelScreenshot": {
    "message": "Fortryd"
  },
  "downloadScreenshot": {
    "message": "Hent"
  },
  "notificationLinkCopiedTitle": {
    "message": "Link kopieret"
  },
  "notificationLinkCopiedDetails": {
    "message": "Linket til dit skærmbillede er blevet gemt i udklipsholderen. Tryk på $META_KEY$-V for at sætte ind.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Ude af funktion"
  },
  "requestErrorDetails": {
    "message": "Vi kunne desværre ikke gemme dit skærmbillede. Prøv igen senere."
  },
  "connectionErrorTitle": {
    "message": "Vi kan ikke oprette forbindelse til dine skærmbilleder."
  },
  "connectionErrorDetails": {
    "message": "Kontroller din internet-forbindelse. Hvis du ikke kan oprette forbindelse til internettet, kan der være et midlertidigt teknisk problem med Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Vi kunne ikke gemme dit skærmbillede, fordi der er et teknisk problem med Firefox Screenshots. Prøv igen senere."
  },
  "unshootablePageErrorTitle": {
    "message": "Vi kan ikke tage et skærmbillede af denne side."
  },
  "unshootablePageErrorDetails": {
    "message": "Dette er ikke en almindelig webside, så du kan ikke tage skærmbilleder af den."
  },
  "selfScreenshotErrorTitle": {
    "message": "Du kan ikke tage skærmbilleder af en side i Firefox Screenshots."
  },
  "emptySelectionErrorTitle": {
    "message": "Din markering er for lille"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots er deaktiveret i privat browsing-tilstand"
  },
  "privateWindowErrorDetails": {
    "message": "Vi beklager ulejligheden. Vi arbejder på at få funktionen til at virke i fremtidige udgivelser."
  },
  "genericErrorTitle": {
    "message": "Hov! Noget gik helt galt med Firefox Screenshots."
  },
  "genericErrorDetails": {
    "message": "Vi er ikke sikre på, hvad der lige skete. Vil du prøve igen - eller vil du tage et skærmbillede af en anden side?"
  },
  "tourBodyOne": {
    "message": "Tag, gem og del skærmbilleder uden at forlade Firefox."
  },
  "tourHeaderTwo": {
    "message": "Gem lige hvad du vil."
  },
  "tourBodyTwo": {
    "message": "Klik og træk for at tage et udklip af en del af en side. Du kan også holde markøren over for at fremhæve din markering."
  },
  "tourHeaderThree": {
    "message": "Tag skærmbilleder af vinduer eller hele sider."
  },
  "tourBodyThree": {
    "message": "Brug knapperne øverst til højre for at tage et skærmbillede af det synlige område i vinduet eller for at tage et skærmbillede af hele siden."
  },
  "tourHeaderFour": {
    "message": "Som du vil have det."
  },
  "tourBodyFour": {
    "message": "Gem dine beskårne skærmbilleder på nettet for nemmere at dele dem - eller hent dem ned på din computer. Du kan også klikke på knappen \"Mine skærmbilleder\" for at finde de skærmbilleder, du har taget."
  },
  "tourSkip": {
    "message": "SPRING OVER"
  },
  "tourNext": {
    "message": "Næste side"
  },
  "tourPrevious": {
    "message": "Forrige side"
  },
  "tourDone": {
    "message": "Færdig"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Ved at anvende Firefox Screenshots godkender du $TERMSANDPRIVACYNOTICETERMSLINK$ og $TERMSANDPRIVACYNOTICEPRIVACYLINK$ for Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "vilkår"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "privatlivspolitik"
  }
}PK
!<&webextension/_locales/de/messages.json{
  "addonDescription": {
    "message": "Erstellen Sie Bildschirmfotos von vollständigen Webseiten oder Ausschnitten und speichern Sie diese temporär oder dauerhaft."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Bildschirmfoto aufnehmen"
  },
  "myShotsLink": {
    "message": "Meine Bildschirmfotos"
  },
  "screenshotInstructions": {
    "message": "Ziehen oder klicken Sie auf der Seite, um einen Bereich auszuwählen. Drücken Sie ESC zum Abbrechen."
  },
  "saveScreenshotSelectedArea": {
    "message": "Speichern"
  },
  "saveScreenshotVisibleArea": {
    "message": "Sichtbaren Bereich speichern"
  },
  "saveScreenshotFullPage": {
    "message": "Gesamte Seite speichern"
  },
  "cancelScreenshot": {
    "message": "Abbrechen"
  },
  "downloadScreenshot": {
    "message": "Herunterladen"
  },
  "notificationLinkCopiedTitle": {
    "message": "Link kopiert"
  },
  "notificationLinkCopiedDetails": {
    "message": "Der Link zu Ihrem Bildschirmfoto wurde in die Zwischenablage kopiert. Drücken Sie $META_KEY$-V zum Einfügen.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Außer Betrieb."
  },
  "requestErrorDetails": {
    "message": "Wir konnten Ihr Bildschirmfoto leider nicht speichern. Bitte versuchen Sie es später erneut."
  },
  "connectionErrorTitle": {
    "message": "Es war keine Verbindung zu Ihren Bildschirmfotos möglich."
  },
  "connectionErrorDetails": {
    "message": "Bitte überprüfen Sie Ihre Internetverbindung. Wenn diese funktioniert, gibt es eventuell ein temporäres Problem mit dem Dienst von Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Ihr Bildschirmfoto konnte nicht gespeichert werden, weil ein Problem mit dem Dienst Firefox Screenshots aufgetreten ist. Bitte versuchen Sie es später erneut."
  },
  "unshootablePageErrorTitle": {
    "message": "Ein Bildschirmfoto dieser Seite ist nicht möglich."
  },
  "unshootablePageErrorDetails": {
    "message": "Dies ist keine Standard-Webseite, deshalb sind keine Bildschirmfotos von ihr möglich."
  },
  "selfScreenshotErrorTitle": {
    "message": "Sie können kein Bildschirmfoto einer Firefox-Screenshots-Seite machen!"
  },
  "emptySelectionErrorTitle": {
    "message": "Ihr Auswahlbereich ist zu klein"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots ist im Privaten Modus deaktiviert"
  },
  "privateWindowErrorDetails": {
    "message": "Wir bitten um Entschuldigung für diese Unannehmlichkeiten. Wir arbeiten daran, diese Funktion in zukünftigen Versionen zur Verfügung zu stellen."
  },
  "genericErrorTitle": {
    "message": "Firefox Screenshots funktioniert nicht richtig."
  },
  "genericErrorDetails": {
    "message": "Wir wissen auch nicht, was gerade passiert ist. Könnten Sie das Bildschirmfoto erneut oder auf einer anderen Seite aufnehmen?"
  },
  "tourBodyOne": {
    "message": "Bildschirmfotos aufnehmen, speichern und teilen, ohne Firefox zu verlassen."
  },
  "tourHeaderTwo": {
    "message": "Nehmen Sie auf, was Sie möchten"
  },
  "tourBodyTwo": {
    "message": "Klicken und ziehen Sie, um nur einen Teil einer Seite aufzunehmen. Sie können den Mauszeiger auch darüber bewegen, um Ihre Auswahl hervorzuheben."
  },
  "tourHeaderThree": {
    "message": "Fenster oder ganze Seiten speichern"
  },
  "tourBodyThree": {
    "message": "Nutzen Sie die Schaltflächen rechts oben, um den sichtbaren Bereich im Fenster oder eine ganze Seite zu speichern."
  },
  "tourHeaderFour": {
    "message": "Wie Sie möchten"
  },
  "tourBodyFour": {
    "message": "Speichern Sie Ihre zugeschnittenen Bildschirmfotos im Internet, sodass sie leicht zu teilen sind, oder laden Sie sie auf Ihren Computer herunter. Sie können auch auf die Schaltfläche „Meine Bildschirmfotos“ klicken, um alle Ihre Bildschirmfotos zu finden."
  },
  "tourSkip": {
    "message": "Überspringen"
  },
  "tourNext": {
    "message": "Nächste Folie"
  },
  "tourPrevious": {
    "message": "Vorherige Folie"
  },
  "tourDone": {
    "message": "Fertig"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Durch die Verwendung von Firefox Screenshots stimmen Sie den $TERMSANDPRIVACYNOTICETERMSLINK$ und dem $TERMSANDPRIVACYNOTICEPRIVACYLINK$ von Firefox Cloud Services zu.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Nutzungsbedingungen"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Datenschutzhinweis"
  }
}PK
!<'webextension/_locales/dsb/messages.json{
  "addonDescription": {
    "message": "Wzejśo klipy a fota wobrazowki z weba a składujśo je nachylu abo na pśecej."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Foto wobrazowki gótowaś"
  },
  "myShotsLink": {
    "message": "Móje fota wobrazowki"
  },
  "screenshotInstructions": {
    "message": "Śěgniśo abo klikniśo na bok, aby wobcerk wubrał. Tłocćo na ESC, aby pśetergnuł."
  },
  "saveScreenshotSelectedArea": {
    "message": "Składowaś"
  },
  "saveScreenshotVisibleArea": {
    "message": "Widobny wobcerk składowaś"
  },
  "saveScreenshotFullPage": {
    "message": "Ceły bok składowaś"
  },
  "cancelScreenshot": {
    "message": "Pśetergnuś"
  },
  "downloadScreenshot": {
    "message": "Ześěgnuś"
  },
  "notificationLinkCopiedTitle": {
    "message": "Wótkaz kopěrowany"
  },
  "notificationLinkCopiedDetails": {
    "message": "Wótkaz k wašomu fotoju wobrazowki jo se do mjazywótkłada kopěrował. Tłocćo $META_KEY$-V, aby jen zasajźił.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Njeźěła."
  },
  "requestErrorDetails": {
    "message": "Bóžko njejsmy mógli wašo foto wobrazowki składowaś. Pšosym wopytajśo pózdźej hyšći raz."
  },
  "connectionErrorTitle": {
    "message": "Njamóžomy z wašymi fotami wobrazowki zwězaś."
  },
  "connectionErrorDetails": {
    "message": "Pšosym pśekontrolěrujśo swój internetny zwisk. Jolic móžośo z internetom zwězaś, dajo snaź nachylny problem ze słužbu Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Njesjmy mógli swójo foto wobrazowki składowaś, dokulaž dajo problem ze słužbu Firefox Screenshots. Pšosym wopytajśo pózdźej hyšći raz."
  },
  "unshootablePageErrorTitle": {
    "message": "Foto wobrazowki toś togo boka njejo móžne."
  },
  "unshootablePageErrorDetails": {
    "message": "To njejo standardny webbok, togodla foto wobrazowki wót njeje njejo móžne."
  },
  "selfScreenshotErrorTitle": {
    "message": "Njamóžośo wobrazowku boka Firefox Screenshots fotografěrowaś!"
  },
  "emptySelectionErrorTitle": {
    "message": "Waš wuběrk jo pśemały"
  },
  "privateWindowErrorTitle": {
    "message": "Firefox Screenshots jo w priwatnem modusu znjemóžnjony"
  },
  "privateWindowErrorDetails": {
    "message": "Wódajśo pšosym wobuznosći. Źěłamy na toś tej funkciji za pśichodne wersije."
  },
  "genericErrorTitle": {
    "message": "Hopla! Firefox Screenshots njeźěła."
  },
  "genericErrorDetails": {
    "message": "Njejsmy se wěste, což jo se stało. Cośo hyšći raz wopytaś abo cośo drugi bok fotografěrowaś?"
  },
  "tourBodyOne": {
    "message": "Gótujśo, składujśo a źělśo fota wobrazowki mimo až Firefox spušćaśo."
  },
  "tourHeaderTwo": {
    "message": "Fotografěrujśo jadnorje, což cośo"
  },
  "tourBodyTwo": {
    "message": "Klikniśo a ześěgniśo, aby źěl boka fotografěrował. Móžośo teke špěrku myški nad nim gibaś, aby swój wuběr wuzwignuł."
  },
  "tourHeaderThree": {
    "message": "Wokna abo cełe boki składowaś"
  },
  "tourBodyThree": {
    "message": "Wubjeŕśo tłocašk górjejce napšawo, aby widobny wobcerk we woknje abo ceły bok fotografěrowaś."
  },
  "tourHeaderFour": {
    "message": "Tak, kaž se wam spódoba"
  },
  "tourBodyFour": {
    "message": "Składujśo swóje pśirězane fota wobrazowki w interneśe, aby je lažcej źělił, abo ześěgniśo je na swójo licadło. Móžośo teke na tłocašk „Móje fota wobrazowki“ kliknuś, abye wšě fota wobrazowki namakał, kótarež sćo gótował."
  },
  "tourSkip": {
    "message": "Pśeskócyś"
  },
  "tourNext": {
    "message": "Pśiduce foto"
  },
  "tourPrevious": {
    "message": "Pjerwjejšne foto"
  },
  "tourDone": {
    "message": "Gótowo"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Pśez wužywanje Firefox ScreenShots, zwolijośo do $TERMSANDPRIVACYNOTICETERMSLINK$ a $TERMSANDPRIVACYNOTICEPRIVACYLINK$ Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Wuměnjenja"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Powěźeńka priwatnosći"
  }
}PK
!<tSS&webextension/_locales/el/messages.json{
  "addonDescription": {
    "message": "Πραγματοποιήστε λήψη στιγμιοτύπων από το Διαδίκτυο και αποθηκεύστε τα προσωρινά ή μόνιμα."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Λήψη στιγμιότυπου"
  },
  "myShotsLink": {
    "message": "Οι λήψεις μου"
  },
  "screenshotInstructions": {
    "message": "Σύρετε ή κάντε κλικ στη σελίδα για να επιλέξετε μια περιοχή. Για ακύρωση πιέστε το πλήκτρο ESC."
  },
  "saveScreenshotSelectedArea": {
    "message": "Αποθήκευση"
  },
  "saveScreenshotVisibleArea": {
    "message": "Αποθήκευση ορατής περιοχής"
  },
  "saveScreenshotFullPage": {
    "message": "Αποθήκευση ολόκληρης σελίδας"
  },
  "cancelScreenshot": {
    "message": "Ακύρωση"
  },
  "downloadScreenshot": {
    "message": "Λήψη"
  },
  "notificationLinkCopiedTitle": {
    "message": "Ο σύνδεσμος αντιγράφηκε"
  },
  "notificationLinkCopiedDetails": {
    "message": "Ο σύνδεσμος προς την λήψη σας αντιγράφηκε στο πρόχειρο. Πατήστε $META_KEY$-V για επικόλληση.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Εκτός λειτουργίας."
  },
  "requestErrorDetails": {
    "message": "Συγνώμη! Δεν μπορέσαμε να αποθηκεύουμε την λήψη σας. Προσπαθήστε ξανά αργότερα."
  },
  "connectionErrorTitle": {
    "message": "Δεν μπορούμε να συνδεθούμε στις λήψεις σας."
  },
  "connectionErrorDetails": {
    "message": "Ελέγξτε τη σύνδεσή σας στο Internet. Εάν είστε σε θέση να συνδεθείτε στο Internet, ίσως υπάρχει ένα προσωρινό πρόβλημα με την υπηρεσία Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Δεν μπορέσαμε να αποθηκεύσουμε την λήψη σας γιατί υπάρχει κάποιο πρόβλημα με την υπηρεσία Firefox Screenshots. Προσπαθήστε ξανά αργότερα."
  },
  "unshootablePageErrorTitle": {
    "message": "Δεν μπορούμε να λάβουμε στιγμιότυπο αυτής της σελίδας."
  },
  "unshootablePageErrorDetails": {
    "message": "Δεν μπορεί να γίνει λήψη στιγμιότυπου καθώς αυτή δεν είναι μια τυπική σελίδα του Διαδικτύου."
  },
  "selfScreenshotErrorTitle": {
    "message": "Δεν μπορεί να γίνει λήψη ενός στιγμιότυπου της σελίδας Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Η επιλογή σας είναι πολύ μικρή"
  },
  "privateWindowErrorTitle": {
    "message": "Το Screenshots είναι απενεργοποιημένο στη λειτουργία ιδιωτικής περιήγησης"
  },
  "privateWindowErrorDetails": {
    "message": "Λυπούμαστε για την ταλαιπωρία. Εργαζόμαστε πάνω σε αυτό το χαρακτηριστικό για μελλοντικές εκδόσεις."
  },
  "genericErrorTitle": {
    "message": "Ωχ! Κάτι πήγε στραβά στην υπηρεσία Firefox Screenshots."
  },
  "genericErrorDetails": {
    "message": "Δεν είμαστε σίγουροι για το τι ακριβώς συνέβη. Προσπαθήστε ξανά ή κάντε λήψη σε μια άλλη σελίδα."
  },
  "tourBodyOne": {
    "message": "Λήψη, αποθήκευση και διαμοιρασμός στιγμιοτύπων μέσα από το Firefox."
  },
  "tourHeaderTwo": {
    "message": "Καταγράψτε αυτό που εσείς επιθυμείτε"
  },
  "tourBodyTwo": {
    "message": "Κάντε κλικ και σύρετε για την καταγραφή ενός τμήματος της σελίδας. Μπορείτε να επισημάνετε την επιλογή σας μετακινώντας τον ποντίκι σας επάνω της."
  },
  "tourHeaderThree": {
    "message": "Λήψη παραθύρων ή ολόκληρων σελίδων"
  },
  "tourBodyThree": {
    "message": "Επιλέξτε τα κουμπιά επάνω δεξιά για να καταγράψετε την ορατή περιοχή του παραθύρου ή να καταγράψετε μια ολόκληρη σελίδα."
  },
  "tourHeaderFour": {
    "message": "Ακριβώς όπως το θέλετε"
  },
  "tourBodyFour": {
    "message": "Αποθηκεύστε της λήψεις σας στο Διαδίκτυο για ευκολότερο διαμοιρασμό, η λήψη τους στον υπολογιστή σας. Μπορείτε να βρείτε όλες τις λήψεις σας πατώντας στο κουμπί «Οι λήψεις μου»."
  },
  "tourSkip": {
    "message": "Παράβλεψη"
  },
  "tourNext": {
    "message": "Επόμενη διαφάνεια"
  },
  "tourPrevious": {
    "message": "Προηγούμενη διαφάνεια"
  },
  "tourDone": {
    "message": "Τέλος"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Χρησιμοποιώντας το Firefox Screenshots, συμφωνείτε με τους $TERMSANDPRIVACYNOTICETERMSLINK$ και την $TERMSANDPRIVACYNOTICEPRIVACYLINK$ των Υπηρεσιών Cloud του Firefox.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Όρους"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Σημείωση απορρήτου"
  }
}PK
!<Sb1)webextension/_locales/en_GB/messages.json{
  "addonDescription": {
    "message": "Take clips and screenshots from the Web and save them temporarily or permanently."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Take a Screenshot"
  },
  "myShotsLink": {
    "message": "My Shots"
  },
  "screenshotInstructions": {
    "message": "Drag or click on the page to select a region. Press ESC to cancel."
  },
  "saveScreenshotSelectedArea": {
    "message": "Save"
  },
  "saveScreenshotVisibleArea": {
    "message": "Save visible"
  },
  "saveScreenshotFullPage": {
    "message": "Save full page"
  },
  "cancelScreenshot": {
    "message": "Cancel"
  },
  "downloadScreenshot": {
    "message": "Download"
  },
  "notificationLinkCopiedTitle": {
    "message": "Link Copied"
  },
  "notificationLinkCopiedDetails": {
    "message": "The link to your shot has been copied to the clipboard. Press $META_KEY$-V to paste.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Out of order."
  },
  "requestErrorDetails": {
    "message": "Sorry! We couldn’t save your shot. Please try again later."
  },
  "connectionErrorTitle": {
    "message": "We can’t connect to your screenshots."
  },
  "connectionErrorDetails": {
    "message": "Please check your Internet connection. If you are able to connect to the Internet, there may be a temporary problem with the Firefox Screenshots service."
  },
  "loginErrorDetails": {
    "message": "We couldn’t save your shot because there is a problem with the Firefox Screenshots service. Please try again later."
  },
  "unshootablePageErrorTitle": {
    "message": "We can’t screenshot this page."
  },
  "unshootablePageErrorDetails": {
    "message": "This isn’t a standard Web page, so you can’t take a screenshot of it."
  },
  "selfScreenshotErrorTitle": {
    "message": "You can’t take a shot of a Firefox Screenshots page!"
  },
  "genericErrorTitle": {
    "message": "Whoa! Firefox Screenshots went haywire."
  },
  "genericErrorDetails": {
    "message": "We’re not sure what just happened. Care to try again or take a shot of a different page?"
  },
  "tourBodyOne": {
    "message": "Take, save, and share screenshots without leaving Firefox."
  },
  "tourHeaderTwo": {
    "message": "Capture Just What You Want"
  },
  "tourBodyTwo": {
    "message": "Click and drag to capture just a portion of a page. You can also hover to highlight your selection."
  },
  "tourHeaderThree": {
    "message": "Capture Windows or Entire Pages"
  },
  "tourBodyThree": {
    "message": "Select the buttons in the upper right to capture the visible area in the window or to capture an entire page."
  },
  "tourHeaderFour": {
    "message": "As You Like It"
  },
  "tourBodyFour": {
    "message": "Save your cropped shots to the web for easier sharing, or download them to your computer. You also can click on the My Shots button to find all the shots you’ve taken."
  },
  "tourSkip": {
    "message": "SKIP"
  },
  "tourNext": {
    "message": "Next Slide"
  },
  "tourPrevious": {
    "message": "Previous Slide"
  },
  "tourDone": {
    "message": "Done"
  }
}PK
!<sZ)webextension/_locales/en_US/messages.json{
  "addonDescription": {
    "message": "Take clips and screenshots from the Web and save them temporarily or permanently."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Take a Screenshot"
  },
  "myShotsLink": {
    "message": "My Shots"
  },
  "screenshotInstructions": {
    "message": "Drag or click on the page to select a region. Press ESC to cancel."
  },
  "saveScreenshotSelectedArea": {
    "message": "Save"
  },
  "saveScreenshotVisibleArea": {
    "message": "Save visible"
  },
  "saveScreenshotFullPage": {
    "message": "Save full page"
  },
  "cancelScreenshot": {
    "message": "Cancel"
  },
  "downloadScreenshot": {
    "message": "Download"
  },
  "notificationLinkCopiedTitle": {
    "message": "Link Copied"
  },
  "notificationLinkCopiedDetails": {
    "message": "The link to your shot has been copied to the clipboard. Press $META_KEY$-V to paste.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Out of order."
  },
  "requestErrorDetails": {
    "message": "Sorry! We couldn’t save your shot. Please try again later."
  },
  "connectionErrorTitle": {
    "message": "We can’t connect to your screenshots."
  },
  "connectionErrorDetails": {
    "message": "Please check your Internet connection. If you are able to connect to the Internet, there may be a temporary problem with the Firefox Screenshots service."
  },
  "loginErrorDetails": {
    "message": "We couldn’t save your shot because there is a problem with the Firefox Screenshots service. Please try again later."
  },
  "unshootablePageErrorTitle": {
    "message": "We can’t screenshot this page."
  },
  "unshootablePageErrorDetails": {
    "message": "This isn’t a standard Web page, so you can’t take a screenshot of it."
  },
  "selfScreenshotErrorTitle": {
    "message": "You can’t take a shot of a Firefox Screenshots page!"
  },
  "emptySelectionErrorTitle": {
    "message": "Your selection is too small"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots is disabled in Private Browsing Mode"
  },
  "privateWindowErrorDetails": {
    "message": "Sorry for the inconvenience. We are working on this feature for future releases."
  },
  "genericErrorTitle": {
    "message": "Whoa! Firefox Screenshots went haywire."
  },
  "genericErrorDetails": {
    "message": "We’re not sure what just happened. Care to try again or take a shot of a different page?"
  },
  "tourBodyOne": {
    "message": "Take, save, and share screenshots without leaving Firefox."
  },
  "tourHeaderTwo": {
    "message": "Capture Just What You Want"
  },
  "tourBodyTwo": {
    "message": "Click and drag to capture just a portion of a page. You can also hover to highlight your selection."
  },
  "tourHeaderThree": {
    "message": "Capture Windows or Entire Pages"
  },
  "tourBodyThree": {
    "message": "Select the buttons in the upper right to capture the visible area in the window or to capture an entire page."
  },
  "tourHeaderFour": {
    "message": "As You Like It"
  },
  "tourBodyFour": {
    "message": "Save your cropped shots to the web for easier sharing, or download them to your computer. You also can click on the My Shots button to find all the shots you’ve taken."
  },
  "tourSkip": {
    "message": "SKIP"
  },
  "tourNext": {
    "message": "Next Slide"
  },
  "tourPrevious": {
    "message": "Previous Slide"
  },
  "tourDone": {
    "message": "Done"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "By using Firefox Screenshots, you agree to our $TERMSANDPRIVACYNOTICETERMSLINK$ and $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Terms"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Privacy Notice"
  }
}PK
!<-&webextension/_locales/eo/messages.json{
  "addonDescription": {
    "message": "Prenu eltondaĵon aŭ faru ekrankopiojn de retpaĝoj kaj konservu ilin ĉu daŭre ĉu provizore."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Fari ekrankopion"
  },
  "myShotsLink": {
    "message": "Miaj ekrankopioj"
  },
  "screenshotInstructions": {
    "message": "Trenu aŭ alklaku sur la paĝo por elekti areon. Premu ESK por nuligi."
  },
  "saveScreenshotSelectedArea": {
    "message": "Konservi"
  },
  "saveScreenshotVisibleArea": {
    "message": "Konservi tion, kio videblas"
  },
  "saveScreenshotFullPage": {
    "message": "Konservi tutan paĝon"
  },
  "cancelScreenshot": {
    "message": "Nuligi"
  },
  "downloadScreenshot": {
    "message": "Elŝuti"
  },
  "notificationLinkCopiedTitle": {
    "message": "Ligilo kopiita"
  },
  "notificationLinkCopiedDetails": {
    "message": "La ligilo al via ekrankopio estis kopiita al la tondujo. Premu $META_KEY$-V por alglui.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Ne funkcianta."
  },
  "requestErrorDetails": {
    "message": "Bedaŭrinde ni ne povis konservi vian ekrankopion. Bonvolu klopodi denove poste."
  },
  "connectionErrorTitle": {
    "message": "Ni ne povas konektiĝi al viaj ekrankopioj."
  },
  "connectionErrorDetails": {
    "message": "Bonvolu kontroli vian retaliron. Se vi povas konektiĝi al la reto, eble estas provizora problemo kun la servo de Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Ni ne povis konservi vian ekrankopion ĉar estis problemo kun la servo de Firefox Screenshots. Bonvolu klopodi denove poste."
  },
  "unshootablePageErrorTitle": {
    "message": "Ni ne povas fari ekrankopion de tiu ĉi paĝo."
  },
  "unshootablePageErrorDetails": {
    "message": "Tiu ĉi ne estas norma retpaĝo, do vi ne povas fari ekrankopion de ĝi."
  },
  "selfScreenshotErrorTitle": {
    "message": "Vi ne povas fari ekrankopion de paĝo de Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Via elektita areo estas tro eta"
  },
  "privateWindowErrorTitle": {
    "message": "Ekrankopioj estas malaktivaj en la reĝimo de privata retumo"
  },
  "privateWindowErrorDetails": {
    "message": "Bonvolu pardoni la ĝenon. Ni prilaboras tiun ĉi trajton por venontaj eldonoj."
  },
  "genericErrorTitle": {
    "message": "Ŭoo! Firefox Screenshots tute frenezis."
  },
  "genericErrorDetails": {
    "message": "Ni ne tro certas, kio ĵus okazis. Ĉu vi povus klopodi denove aŭ fari ekrankopion de alia paĝo?"
  },
  "tourBodyOne": {
    "message": "Faru, konservu kaj dividu ekrankopiojn sen forlasi Firefox."
  },
  "tourHeaderTwo": {
    "message": "Kopiu nur tion, kion vi volas."
  },
  "tourBodyTwo": {
    "message": "Alklaku kaj trenu por kopii nur parton de paĝo. Vi povas ankaŭ ŝvebi por elstarigi vian elekton."
  },
  "tourHeaderThree": {
    "message": "Kapti fenestrojn aŭ tutaj paĝojn"
  },
  "tourBodyThree": {
    "message": "Elektu la butonojn supre kaj dekstre por kapti la videblan areon en la fenestro aŭ por kapti tutan paĝon."
  },
  "tourHeaderFour": {
    "message": "Kiel vi volas"
  },
  "tourBodyFour": {
    "message": "Konservu vian eltonditajn ekrankopiojn en la reto, por pli facile dividi ilin, aŭ elŝutu ilin al via komputilo. Vi ankaŭ povas alklaki la butonon 'Miaj ekrankopioj' por trovi ĉiujn ekrankopiojn faritajn de vi."
  },
  "tourSkip": {
    "message": "Pretersalti"
  },
  "tourNext": {
    "message": "Venonta ekrano"
  },
  "tourPrevious": {
    "message": "Antaŭa ekrano"
  },
  "tourDone": {
    "message": "Farita"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Se vi uzas Firefox Screenshots, vi akceptas nian $TERMSANDPRIVACYNOTICETERMSLINK$ kaj $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "kondiĉojn"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "rimarkon pri privateco"
  }
}PK
!<H7)webextension/_locales/es_AR/messages.json{
  "addonDescription": {
    "message": "Tomá imágenes y capturas de la web y guardalos temporal o permanentemente."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Hacer captura de pantalla"
  },
  "myShotsLink": {
    "message": "Mis capturas"
  },
  "screenshotInstructions": {
    "message": "Arrastrá o hacé clic en la página para seleccionar una región. Presioná ESC para cancelar."
  },
  "saveScreenshotSelectedArea": {
    "message": "Guardar"
  },
  "saveScreenshotVisibleArea": {
    "message": "Guardar visible"
  },
  "saveScreenshotFullPage": {
    "message": "Guardar página completa"
  },
  "cancelScreenshot": {
    "message": "Cancelar"
  },
  "downloadScreenshot": {
    "message": "Descargar"
  },
  "notificationLinkCopiedTitle": {
    "message": "Enlace copiado"
  },
  "notificationLinkCopiedDetails": {
    "message": "El enlace a la captura ha sido copiado al portapapeles. Presioná $META_KEY$-V para pegar.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "No funciona."
  },
  "requestErrorDetails": {
    "message": "¡Perdón! No pudimos guardar la captura. Intentá más tarde."
  },
  "connectionErrorTitle": {
    "message": "No podemos conectar a las capturas de pantalla."
  },
  "connectionErrorDetails": {
    "message": "Verificá la conexión a Internet. Si te podés conectar a Internet, hay un problema temporal con el servicio de Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "No pudimos guardar la captura porque hay un problema con el servicio de Firefox Screenshots. Intentá más tarde."
  },
  "unshootablePageErrorTitle": {
    "message": "No podemos capturar esta página."
  },
  "unshootablePageErrorDetails": {
    "message": "Esta no es una página web estándar, así que no podemos guardar una captura."
  },
  "selfScreenshotErrorTitle": {
    "message": "¡No se puede hacer una captura de la página de Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "La selección es demasiado chica"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots está deshabilitado en el modo de navegación privada"
  },
  "privateWindowErrorDetails": {
    "message": "Lamentamos el inconveniente. Estamos trabajando en esta característica para versiones futuras."
  },
  "genericErrorTitle": {
    "message": "¡Apa! Firefox Screenshots se volvió loco."
  },
  "genericErrorDetails": {
    "message": "No estamos seguros de lo que pasó. ¿Querés intenar de nuevo o tomar una captura de una página diferente?"
  },
  "tourBodyOne": {
    "message": "Hacer, guardar y compartir capturas de pantalla sin dejar Firefox."
  },
  "tourHeaderTwo": {
    "message": "Capturar sólo lo que querés"
  },
  "tourBodyTwo": {
    "message": "Hacé clic y arrastrá para capturar una porción de la página. También podés pasar por encima para resaltar la selección."
  },
  "tourHeaderThree": {
    "message": "Capturar ventanas o páginas enteras"
  },
  "tourBodyThree": {
    "message": "Seleccioná los botones arriba a la derecha para capturar el área visible en la ventana o la página completa."
  },
  "tourHeaderFour": {
    "message": "Como te guste"
  },
  "tourBodyFour": {
    "message": "Guardá tus capturas recortadas a la web para compartir o descargarlas más fácilmente a tu computadora. También podés hacer clic en el botón Mis capturas para encontrar todas las capturas hechas."
  },
  "tourSkip": {
    "message": "SALTEAR"
  },
  "tourNext": {
    "message": "Próxima diapositiva"
  },
  "tourPrevious": {
    "message": "Diapositiva anterior"
  },
  "tourDone": {
    "message": "Listo"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Al usar Firefox Screenshots, aceptás los $TERMSANDPRIVACYNOTICETERMSLINK$ y $TERMSANDPRIVACYNOTICEPRIVACYLINK$ de los servicios en la nube de Firefox.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Términos"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Nota de privacidad"
  }
}PK
!<LivHH)webextension/_locales/es_CL/messages.json{
  "addonDescription": {
    "message": "Toma capturas de un sitio Web para guardarlas de forma temporal o permanentemente."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Toma una captura de pantalla"
  },
  "myShotsLink": {
    "message": "Mis capturas"
  },
  "screenshotInstructions": {
    "message": "Arrastra o haz clic en la página para seleccionar una región. Presiona ESC para cancelar."
  },
  "saveScreenshotSelectedArea": {
    "message": "Guardar"
  },
  "saveScreenshotVisibleArea": {
    "message": "Guardar lo visible"
  },
  "saveScreenshotFullPage": {
    "message": "Guardar la página completa"
  },
  "cancelScreenshot": {
    "message": "Cancelar"
  },
  "downloadScreenshot": {
    "message": "Descargar"
  },
  "notificationLinkCopiedTitle": {
    "message": "Enlace copiado"
  },
  "notificationLinkCopiedDetails": {
    "message": "El enlace a tu captura ha sido copiado al portapapeles. Presiona $META_KEY$-V para pegarla.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Fuera de orden."
  },
  "requestErrorDetails": {
    "message": "¡Lo sentimos! No pudimos guardar tu captura. Por favor, vuelve a intentarlo más tarde."
  },
  "connectionErrorTitle": {
    "message": "No podemos conectar a tus capturas."
  },
  "connectionErrorDetails": {
    "message": "Por favor, revisa tu conexión a Internet. Si eres capaz de conectarte a Internet, puede que haya un problema temporal con el servicio de Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "No pudimos guardar tu captura porque hay un problema con el servicio de Firefox Screenshots. Por favor, vuelve a intentarlo más tarde."
  },
  "unshootablePageErrorTitle": {
    "message": "No podemos capturar esta página."
  },
  "unshootablePageErrorDetails": {
    "message": "Esta no es una página Web estándar, por lo que no puedes tomar una captura de ella."
  },
  "selfScreenshotErrorTitle": {
    "message": "¡No puedes tomar una captura de una página de Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Tu selección es muy pequeña"
  },
  "privateWindowErrorTitle": {
    "message": "Firefox Screenshots está desactivado en el modo de navegación privada"
  },
  "privateWindowErrorDetails": {
    "message": "Disculpa las molestias. Estamos trabajando en esta función para una futura versión."
  },
  "genericErrorTitle": {
    "message": "¡Guau! Firefox Screenshots se copetió."
  },
  "genericErrorDetails": {
    "message": "No estamos seguros de lo que sucedió. ¿Te importaría volver a intentarlo o tomar una captura de una página diferente?"
  },
  "tourBodyOne": {
    "message": "Toma, guarda y comparte capturas sin salir de Firefox."
  },
  "tourHeaderTwo": {
    "message": "Captura lo que necesitas"
  },
  "tourBodyTwo": {
    "message": "Haz clic y arrastra para captura justo una parte de la página. También puedes colocarte sobre una parte para destacar tu selección."
  },
  "tourHeaderThree": {
    "message": "Captura ventanas o páginas completas"
  },
  "tourBodyThree": {
    "message": "Selecciona los botones en la parte superior derecha para capturar el área visible ne la ventana o para capturar una página completa."
  },
  "tourHeaderFour": {
    "message": "Como tu quieras"
  },
  "tourBodyFour": {
    "message": "Guarda tus capturas recortadas en la Web para compartirlas fácilmente o descargarlas a tu computador. También puedes hacer clic en el botón Mis capturas para encontrar todas las que hayas tomado."
  },
  "tourSkip": {
    "message": "SALTAR"
  },
  "tourNext": {
    "message": "Siguiente diapositiva"
  },
  "tourPrevious": {
    "message": "Diapositiva anterior"
  },
  "tourDone": {
    "message": "Hecho"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Al usar Firefox Screenshots, aceptas los $TERMSANDPRIVACYNOTICETERMSLINK$ y el $TERMSANDPRIVACYNOTICEPRIVACYLINK$ de Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Términos"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Aviso de privacidad"
  }
}PK
!<2_)webextension/_locales/es_ES/messages.json{
  "addonDescription": {
    "message": "Haz capturas y recortes de la web y guárdalos temporal o permanentemente."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Hacer una captura de pantalla"
  },
  "myShotsLink": {
    "message": "Mis capturas"
  },
  "screenshotInstructions": {
    "message": "Arrastra o haz clic en la página para seleccionar una región. Pulsa ESC para cancelar."
  },
  "saveScreenshotSelectedArea": {
    "message": "Guardar"
  },
  "saveScreenshotVisibleArea": {
    "message": "Guardar visible"
  },
  "saveScreenshotFullPage": {
    "message": "Guardar página completa"
  },
  "cancelScreenshot": {
    "message": "Cancelar"
  },
  "downloadScreenshot": {
    "message": "Descargar"
  },
  "notificationLinkCopiedTitle": {
    "message": "Enlace copiado"
  },
  "notificationLinkCopiedDetails": {
    "message": "Se ha copiado el enlace a la captura en el portapapeles. Pulsa $META_KEY$-V para pegar.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "No funciona."
  },
  "requestErrorDetails": {
    "message": "¡Lo sentimos! No hemos podido guardar tu captura. Inténtalo más tarde."
  },
  "connectionErrorTitle": {
    "message": "No podemos acceder a tus capturas de pantalla."
  },
  "connectionErrorDetails": {
    "message": "Comprueba tu conexión a Internet. Si puedes conectarte, puede que haya un problema temporal con el servicio de capturas de pantalla de Firefox."
  },
  "loginErrorDetails": {
    "message": "No se pudo guardar la captura porque hay un problema con el servicio Firefox Screenshots. Inténtalo más tarde."
  },
  "unshootablePageErrorTitle": {
    "message": "No podemos hacer una captura de esta página."
  },
  "unshootablePageErrorDetails": {
    "message": "No es una página web común, por lo que no podemos hacer captura de pantalla."
  },
  "selfScreenshotErrorTitle": {
    "message": "¡No puedes hacer una captura de la página de Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Tu selección es demasiado pequeña"
  },
  "privateWindowErrorTitle": {
    "message": "Firefox Screenshots está desactivado en el modo de navegación privada"
  },
  "privateWindowErrorDetails": {
    "message": "Sentimos las molestias. Estamos trabajando en esta característica para próximos lanzamientos."
  },
  "genericErrorTitle": {
    "message": "¡Vaya! Firefox Screenshots se ha vuelto loco."
  },
  "genericErrorDetails": {
    "message": "No estamos seguros de lo que acaba de pasar. ¿Te importa volver a intentarlo o hacer una captura de otra página?"
  },
  "tourBodyOne": {
    "message": "Hacer, guardar y compartir capturas de pantalla sin salir de Firefox."
  },
  "tourHeaderTwo": {
    "message": "Haz capturas solo de lo que tú quieras"
  },
  "tourBodyTwo": {
    "message": "Haz clic y arrastra para capturar solo una parte de la página. También puedes pasar por encima para resaltar tu selección."
  },
  "tourHeaderThree": {
    "message": "Haz capturas de Windows o páginas completas"
  },
  "tourBodyThree": {
    "message": "Selecciona los botones de la parte superior derecha para capturar el área visible en Windows o la página completa."
  },
  "tourHeaderFour": {
    "message": "Como más te guste"
  },
  "tourBodyFour": {
    "message": "Guarda las capturas de la Web recortadas para compartirlas mejor o descárgalas en tu ordenador. También puedes hacer clic en Mis capturas para ver todas las capturas que has hecho."
  },
  "tourSkip": {
    "message": "Saltar"
  },
  "tourNext": {
    "message": "Diapositiva siguiente"
  },
  "tourPrevious": {
    "message": "Diapositiva anterior"
  },
  "tourDone": {
    "message": "Hecho"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Al usar Firefox Screenshots, aceptas los $TERMSANDPRIVACYNOTICETERMSLINK$ y el $TERMSANDPRIVACYNOTICEPRIVACYLINK$ de Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Términos"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Aviso de privacidad"
  }
}PK
!<%T)webextension/_locales/es_MX/messages.json{
  "addonDescription": {
    "message": "Tomar clips y capturas de pantalla de la web y guardarlos temporalmente o permanentemente."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Tomar captura de pantalla"
  },
  "myShotsLink": {
    "message": "Mis capturas"
  },
  "screenshotInstructions": {
    "message": "Arrastra o haz clic en la página para seleccionar la región. Presiona ESC para cancelar."
  },
  "saveScreenshotSelectedArea": {
    "message": "Guardar"
  },
  "saveScreenshotVisibleArea": {
    "message": "Guardar visible"
  },
  "saveScreenshotFullPage": {
    "message": "Guardar página completa"
  },
  "cancelScreenshot": {
    "message": "Cancelar"
  },
  "downloadScreenshot": {
    "message": "Descarga"
  },
  "notificationLinkCopiedTitle": {
    "message": "Enlace copiado"
  },
  "notificationLinkCopiedDetails": {
    "message": "El enlace que has capturado ha sido copiado al portapapeles. Presiona $META_KEY$-V para pegar.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Fuera de orden."
  },
  "requestErrorDetails": {
    "message": "¡Lo sentimos! No pudimos guardar tu captura. Por favor, intenta de nuevo más tarde."
  },
  "connectionErrorTitle": {
    "message": "No podemos conectar a tus capturas de pantalla."
  },
  "connectionErrorDetails": {
    "message": "Por favor, revisa tu conexión a Internet. Si eres capaz de conectarte a Internet, puede ser que exista un error temporal con el servicio de capturas de pantalla de Firefox."
  },
  "loginErrorDetails": {
    "message": "No pudimos guardar tu captura porque hay un problema con el servicio de capturas de pantalla de Firefox. Por favor, intenta de nuevo más tarde."
  },
  "unshootablePageErrorTitle": {
    "message": "No podemos realizar una captura de pantalla a esta página."
  },
  "unshootablePageErrorDetails": {
    "message": "Esta no es una página web estándar, por lo tanto no podemos tomar una captura de pantalla de ella."
  },
  "selfScreenshotErrorTitle": {
    "message": "¡No puedes tomar una captura de la página de capturas de pantalla de Firefox!"
  },
  "emptySelectionErrorTitle": {
    "message": "Tu selección es demasiado pequeña"
  },
  "privateWindowErrorTitle": {
    "message": "La captura de pantalla está deshabilitada en el modo navegación privada"
  },
  "privateWindowErrorDetails": {
    "message": "Disculpen las molestias. Estamos trabajando en esta característica para las versiones futuras."
  },
  "genericErrorTitle": {
    "message": "¡Oye! Las capturas de pantalla de Firefox salieron mal."
  },
  "genericErrorDetails": {
    "message": "No estamos seguros qué pasó. ¿Te importaría intentarlo de nuevo o tomar una captura de una página diferente?"
  },
  "tourBodyOne": {
    "message": "Toma, guarda y comparte capturas de pantalla sin dejar Firefox."
  },
  "tourHeaderTwo": {
    "message": "Captura sólo lo que necesitas"
  },
  "tourBodyTwo": {
    "message": "Haz clic y arrastra para capturas sólo una parte de la página. También puedes desplazarte para resaltar tu selección."
  },
  "tourHeaderThree": {
    "message": "Captura ventanas o páginas enteras"
  },
  "tourBodyThree": {
    "message": "Selecciona los botones en la parte superior derecha para capturar el área visible en la ventana o para capturar una página completa."
  },
  "tourHeaderFour": {
    "message": "Como te gusta"
  },
  "tourBodyFour": {
    "message": "Guarda tus capturas recortadas en la Web para compartirlas más fácilmente o descárgalas en tu computadora. También puedes hacer clic en el botón Mis Capturas para encontrar todas las fotos que has tomado."
  },
  "tourSkip": {
    "message": "Ignorar"
  },
  "tourNext": {
    "message": "Siguiente diapositiva"
  },
  "tourPrevious": {
    "message": "Diapositiva anterior"
  },
  "tourDone": {
    "message": "Terminado"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Al usar Firefox Screenshots, estás de acuerdo con los servicios de Firefox Cloud $TERMSANDPRIVACYNOTICETERMSLINK$ y $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Términos"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Aviso de privacidad"
  }
}PK
!<OH%==&webextension/_locales/et/messages.json{
  "addonDescription": {
    "message": "Tee veebist klippe või ekraanipilte ning salvesta need ajutiselt või püsivalt."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Tee ekraanipilt"
  },
  "myShotsLink": {
    "message": "Minu pildid"
  },
  "screenshotInstructions": {
    "message": "Ala valimiseks klõpsavõi lohista lehel. Tühistamiseks vajuta ESC."
  },
  "saveScreenshotSelectedArea": {
    "message": "Salvesta"
  },
  "saveScreenshotVisibleArea": {
    "message": "Salvesta nähtav"
  },
  "saveScreenshotFullPage": {
    "message": "Salvesta terve leht"
  },
  "cancelScreenshot": {
    "message": "Tühista"
  },
  "downloadScreenshot": {
    "message": "Laadi alla"
  },
  "notificationLinkCopiedTitle": {
    "message": "Link kopeeriti"
  },
  "notificationLinkCopiedDetails": {
    "message": "Link sinu pildile kopeeriti lõikepuhvrisse. Asetamiseks vajuta $META_KEY$-V.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Tekkis viga."
  },
  "requestErrorDetails": {
    "message": "Vabandame! Me ei suutnud su pilti salvestada. Palun proovi hiljem uuesti."
  },
  "connectionErrorTitle": {
    "message": "Ühendumine sinu ekraanipiltidega ei õnnestunud."
  },
  "connectionErrorDetails": {
    "message": "Palun kontrolli internetiühenduse toimimist. Kui saad internetiga ühendust, siis võib tegemist olla Firefox Screenshots teenuse ajutise probleemiga."
  },
  "loginErrorDetails": {
    "message": "Ekraanipildi salvestamine ebaõnnestus Firefox Screenshots teenuse probleemi tõttu. Palun proovi hiljem uuesti."
  },
  "unshootablePageErrorTitle": {
    "message": "Sellest lehest ei saa ekraanipilti teha."
  },
  "unshootablePageErrorDetails": {
    "message": "Tegemist pole standardse veebilehega, seetõttu ei saa sellest ekraanipilti teha."
  },
  "selfScreenshotErrorTitle": {
    "message": "Firefox Screenshots lehest ei saa ekraanipilti teha!"
  },
  "emptySelectionErrorTitle": {
    "message": "Valik on liiga väike"
  },
  "privateWindowErrorTitle": {
    "message": "Ekraanipilte ei saa privaatsel veebilehitsemisel teha"
  },
  "privateWindowErrorDetails": {
    "message": "Vabandame tüli tekitamise pärast. Töötame selle võimaluse lisamiseks tulevikus."
  },
  "genericErrorTitle": {
    "message": "Oi-oi! Firefox Screenshots läks sassi."
  },
  "genericErrorDetails": {
    "message": "Me pole kindlad, mis just juhtus. Proovid ehk uuesti või teed ekraanipildi mõnest teisest lehest?"
  },
  "tourBodyOne": {
    "message": "Tee, salvesta ja jaga ekraanipilte Firefoxist lahkumata."
  },
  "tourHeaderTwo": {
    "message": "Salvesta just seda, mida soovid"
  },
  "tourBodyTwo": {
    "message": "Klõpsa ja lohista lehe osa valimiseks. Samuti võid valiku esile toomiseks kursorit selle kohal hoida."
  },
  "tourHeaderThree": {
    "message": "Salvesta aknaid või terveid lehti"
  },
  "tourBodyThree": {
    "message": "Kasuta nuppe ülal paremal aknas nähtava ala või terve lehe salvestamiseks."
  },
  "tourHeaderFour": {
    "message": "Nii, kuidas sulle meeldib"
  },
  "tourBodyFour": {
    "message": "Salvesta kärbitud pilte lihtsamaks jagamiseks veebi või laadi need alla enda arvutisse. Võid ka klõpsata Minu pildid nupul kõigi tehtud piltide vaatamiseks."
  },
  "tourSkip": {
    "message": "Jäta vahele"
  },
  "tourNext": {
    "message": "Järgmine slaid"
  },
  "tourPrevious": {
    "message": "Eelmine slaid"
  },
  "tourDone": {
    "message": "Valmis"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Firefox Screenshots kasutamisel nõustud Firefox Cloud Services $TERMSANDPRIVACYNOTICETERMSLINK$ ja $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "kasutustingimuste"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "privaatsuspoliitikaga"
  }
}PK
!<ɂ&webextension/_locales/fa/messages.json{
  "addonDescription": {
    "message": "از وب عکس بگیرید و کلیپ بسازید و به صورت موقت یا دایمی ذخیره کنید."
  },
  "addonAuthorsList": {
    "message": "موزیلا <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "از صفحه عکس بگیرید"
  },
  "myShotsLink": {
    "message": "عکس‌های من"
  },
  "screenshotInstructions": {
    "message": "با کشیدن یا کلیک کردن روی صفحه یک منطقه را انتخاب کنید. برای لغو، ESC را فشار دهید."
  },
  "saveScreenshotSelectedArea": {
    "message": "ذخیره"
  },
  "saveScreenshotVisibleArea": {
    "message": "ذخیره ناحیه قابل مشاهده"
  },
  "saveScreenshotFullPage": {
    "message": "ذخیره صفحه کامل"
  },
  "cancelScreenshot": {
    "message": "لغو"
  },
  "downloadScreenshot": {
    "message": "دریافت"
  },
  "notificationLinkCopiedTitle": {
    "message": "پیوند کپی شد"
  },
  "notificationLinkCopiedDetails": {
    "message": "لینک عکس شما در کلیپ‌بورد رونوشت شد. $META_KEY$-V را برای جای‌گذاری فشار دهید.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "خارج از سرویس."
  },
  "requestErrorDetails": {
    "message": "متاسفم! نتوانستیم عکس شما را ذخیره کنیم. لطفاً بعدا دوباره تلاش کنید."
  },
  "connectionErrorTitle": {
    "message": "نمی‌توانیم به تصاویر صفحه شما متصل شویم."
  },
  "connectionErrorDetails": {
    "message": "لطفا اتصال اینترنت خود را بررسی کنید. اگر قادر به اتصال به اینترنت هستید، ممکن است مشکلی موقتی در سرویس تصاویر صفحهٔ فایرفاکس وجود داشته باشد."
  },
  "loginErrorDetails": {
    "message": "به علت وجود مشکل در سرویس تصاویر صفحه فایرفاکس نتوانستیم عکس شما را ذخیره کنیم. لطفاً بعدا دوباره تلاش کنید."
  },
  "unshootablePageErrorTitle": {
    "message": "نمی‌توانیم از این صفحه تصویر بگیریم."
  },
  "unshootablePageErrorDetails": {
    "message": "این یک صفحه استاندارد وب نیست، بنابراین شما نمی‌توانید از آن تصویر بگیرید."
  },
  "selfScreenshotErrorTitle": {
    "message": "نمی‌توانید از صفحهٔ تصاویرِ فایرفاکس عکس بگیرید!"
  },
  "emptySelectionErrorTitle": {
    "message": "انتخاب شما خیلی کوچک است"
  },
  "privateWindowErrorTitle": {
    "message": "در حالت مرور خصوصی تصاویرصفحه غیرفعال است"
  },
  "privateWindowErrorDetails": {
    "message": "به خاطر مزاحمت متاسفیم. ما در حال کار روی این ویژگی برای انتشار‌های آینده هستیم."
  },
  "genericErrorTitle": {
    "message": "اوه! سرویس تصاویر صفحه فایرفاکس قاطی کرده."
  },
  "genericErrorDetails": {
    "message": "مطمئن نیستیم چه اتفاقی افتاده است. می‌خواهید دوباره امتحان کنید یا از یک صفحهٔ دیگر عکس بگیرید؟"
  },
  "tourBodyOne": {
    "message": "بدون خارج شدن از فایرفاکس، عکس بگیرید، ذخیره کنید و به اشتراک بگذارید."
  },
  "tourHeaderTwo": {
    "message": "ضبط آنچه شما می‌خواهید"
  },
  "tourBodyTwo": {
    "message": "کلیک کنید و بکشید تا فقط از قسمتی از صفحه عکس بگیرید. می‌توانید برای برجسته کردن روی ناحیه انتخاب شده حرکت کنید."
  },
  "tourHeaderThree": {
    "message": "ضبط پنجره یا کل صفحه‌ها"
  },
  "tourBodyThree": {
    "message": "برای گرفتن عکس از ناحیه قابل مشاهده در پنجره یا تمام صفحه از دکمه‌های بالا سمت راست استفاده کنید."
  },
  "tourHeaderFour": {
    "message": "همانطور که می‌پسندید"
  },
  "tourBodyFour": {
    "message": "عکس‌های بریده شده خود را برای به اشتراک‌گذاری راحت‌تر روی وب ذخیره کنید، یا آن‌ها را روی رایانه خود دریافت کنید. همچنین برای دیدن همهٔ عکس‌هایی که گرفتید می‌توانید روی دکمه «عکس‌های من» کلیک کنید."
  },
  "tourSkip": {
    "message": "رد کردن"
  },
  "tourNext": {
    "message": "اسلاید بعدی"
  },
  "tourPrevious": {
    "message": "اسلاید قبلی"
  },
  "tourDone": {
    "message": "انجام شد"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "با استفاده از سرویس تصاویرِ صفحه فایرفاکس، شما با شرایط سرویس‌های ابری فایرفاکس $TERMSANDPRIVACYNOTICETERMSLINK$ و $TERMSANDPRIVACYNOTICEPRIVACYLINK$ موافقت می‌کنید.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "شرایط"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "نکات حریم‌خصوصی"
  }
}PK
!<EE&webextension/_locales/fi/messages.json{
  "addonDescription": {
    "message": "Ota leikkeitä ja kuvakaappauksia verkosta ja tallenna ne tilapäisesti tai pysyvästi."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Ota kuvakaappaus"
  },
  "myShotsLink": {
    "message": "Omat kaappaukset"
  },
  "screenshotInstructions": {
    "message": "Valitse alue vetämällä tai napsauttamalla sivua. Peruuta painamalla ESC."
  },
  "saveScreenshotSelectedArea": {
    "message": "Tallenna"
  },
  "saveScreenshotVisibleArea": {
    "message": "Tallenna näkyvä alue"
  },
  "saveScreenshotFullPage": {
    "message": "Tallenna koko sivu"
  },
  "cancelScreenshot": {
    "message": "Peruuta"
  },
  "downloadScreenshot": {
    "message": "Lataa"
  },
  "notificationLinkCopiedTitle": {
    "message": "Linkki kopioitu"
  },
  "notificationLinkCopiedDetails": {
    "message": "Linkki kuvaasi on kopioitu leikepöydälle. Voit liittää sen painamalla $META_KEY$-V.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Epäkunnossa."
  },
  "requestErrorDetails": {
    "message": "Kuvan tallentaminen epäonnistui. Yritä myöhemmin uudestaan."
  },
  "connectionErrorTitle": {
    "message": "Emme saa yhteyttä kuvakaappauksiisi."
  },
  "connectionErrorDetails": {
    "message": "Tarkista internetyhteytesi. Jos olet yhteydessä internetiin, Firefox Screenshots -palvelussa voi olla tilapäinen häiriö."
  },
  "loginErrorDetails": {
    "message": "Emme pystyneet tallentamaan kuvaasi, koska Firefox Screenshots -palvelussa on ongelma. Yritä myöhemmin uudestaan."
  },
  "unshootablePageErrorTitle": {
    "message": "Tästä sivusta ei voi ottaa kuvaa."
  },
  "unshootablePageErrorDetails": {
    "message": "Tämä ei ole tavallinen verkkosivu, joten et voi ottaa kuvaa siitä."
  },
  "selfScreenshotErrorTitle": {
    "message": "Et voi ottaa kuvaa Firefox Screenshots -sivusta!"
  },
  "emptySelectionErrorTitle": {
    "message": "Valinta on liian pieni"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots ei ole käytettävisssä yksityisen selauksen tilassa"
  },
  "privateWindowErrorDetails": {
    "message": "Anteeksi häiriö. Tämä ominaisuus on vielä työn alla."
  },
  "genericErrorTitle": {
    "message": "Oho! Firefox Screenshots meni päin prinkkalaa."
  },
  "genericErrorDetails": {
    "message": "Emme oikein tiedä, mitä tapahtui. Haluatko yrittää uudestaan tai ottaa kuvan eri sivusta?"
  },
  "tourBodyOne": {
    "message": "Ota, tallenna ja jaa kuvakaappaus poistumatta Firefoxista."
  },
  "tourHeaderTwo": {
    "message": "Kaappaa mitä haluat"
  },
  "tourBodyTwo": {
    "message": "Kaappaa vain osa sivusta napsauttamalla ja vetämällä. Voit myös korostaa valinnan pitämällä hiirtä sen päällä."
  },
  "tourHeaderThree": {
    "message": "Kaappaa näkyvä alue tai kokonainen sivu"
  },
  "tourBodyThree": {
    "message": "Valitse oikean yläkulman painikkeista joko ikkunassa näkyvän alueen tai koko sivun kaappaus."
  },
  "tourHeaderFour": {
    "message": "Haluamallasi tavalla"
  },
  "tourBodyFour": {
    "message": "Tallenna rajaamasi kuvat verkkoon helpompaa jakamista varten tai lataa ne tietokoneellesi. Voit myös napsauttaa Omat kaappaukset -painiketta ja nähdä kaikki ottamasi kuvat."
  },
  "tourSkip": {
    "message": "OHITA"
  },
  "tourNext": {
    "message": "Seuraava sivu"
  },
  "tourPrevious": {
    "message": "Edellinen sivu"
  },
  "tourDone": {
    "message": "Valmis"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Käyttämällä Firefox Screenshots –ominaisuutta hyväksyt Firefoxin pilvipalveluiden $TERMSANDPRIVACYNOTICETERMSLINK$ ja $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "käyttöehdot"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "tietosuojakäytännön"
  }
}PK
!<޳Kyy&webextension/_locales/fr/messages.json{
  "addonDescription": {
    "message": "Effectuez des captures d’écran sur le Web et sauvegardez-les de manière temporaire ou permanente."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Effectuer une capture d’écran"
  },
  "myShotsLink": {
    "message": "Mes captures d’écran"
  },
  "screenshotInstructions": {
    "message": "Sélectionnez une zone de la page par cliquer-glisser. Appuyez sur Échap pour annuler."
  },
  "saveScreenshotSelectedArea": {
    "message": "Enregistrer"
  },
  "saveScreenshotVisibleArea": {
    "message": "Capturer la zone visible"
  },
  "saveScreenshotFullPage": {
    "message": "Capturer la page complète"
  },
  "cancelScreenshot": {
    "message": "Annuler"
  },
  "downloadScreenshot": {
    "message": "Télécharger"
  },
  "notificationLinkCopiedTitle": {
    "message": "Lien copié"
  },
  "notificationLinkCopiedDetails": {
    "message": "Le lien de votre capture a été copié dans le presse-papiers. Appuyez sur $META_KEY$-V pour le coller.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Impossible d’effectuer cette action."
  },
  "requestErrorDetails": {
    "message": "Votre capture d’écran n’a pas pu être enregistrée. Veuillez réessayer plus tard."
  },
  "connectionErrorTitle": {
    "message": "Nous ne pouvons pas nous connecter à vos captures d’écran."
  },
  "connectionErrorDetails": {
    "message": "Veuillez vérifier votre connexion à Internet. Si celle-ci fonctionne normalement, il peut y avoir un problème temporaire avec le service de Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Nous n’avons pas pu enregistrer votre capture d’écran, car le service de Firefox Screenshot rencontre des difficultés. Veuillez réessayer plus tard."
  },
  "unshootablePageErrorTitle": {
    "message": "Impossible d’effectuer une capture de cette page."
  },
  "unshootablePageErrorDetails": {
    "message": "Impossible d’effectuer une capture d’écran, car cette page web n’est pas standard."
  },
  "selfScreenshotErrorTitle": {
    "message": "Vous ne pouvez pas effectuer une capture d’écran d’une page Firefox Screenshots."
  },
  "emptySelectionErrorTitle": {
    "message": "La zone sélectionnée est trop petite"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots est désactivé en mode de navigation privée"
  },
  "privateWindowErrorDetails": {
    "message": "Désolé pour la gêne occasionnée. Nous travaillons sur cette fonctionnalité pour de prochaines versions."
  },
  "genericErrorTitle": {
    "message": "Firefox Screenshots semble avoir un problème."
  },
  "genericErrorDetails": {
    "message": "Un problème non identifié est survenu. Vous pouvez réessayer ou effectuer une capture d’écran d’une autre page."
  },
  "tourBodyOne": {
    "message": "Effectuez des captures d’écran, enregistrez et partagez-les sans quitter Firefox."
  },
  "tourHeaderTwo": {
    "message": "Capturez ce que vous voulez"
  },
  "tourBodyTwo": {
    "message": "Cliquez et glissez pour capturer seulement une partie de la page. Vous pouvez aussi survoler une zone avec votre curseur pour surligner votre sélection."
  },
  "tourHeaderThree": {
    "message": "Effectuez des captures d’écran de fenêtres ou de pages entières"
  },
  "tourBodyThree": {
    "message": "Utilisez les boutons en haut à droite pour capturer au choix la zone visible dans la fenêtre ou la page entière."
  },
  "tourHeaderFour": {
    "message": "À votre guise"
  },
  "tourBodyFour": {
    "message": "Sauvegardez en ligne vos captures recadrées pour les partager plus facilement, ou téléchargez-les sur votre ordinateur. Vous pouvez aussi cliquer sur « Mes captures d’écran » pour retrouver toutes vos captures."
  },
  "tourSkip": {
    "message": "IGNORER"
  },
  "tourNext": {
    "message": "Écran suivant"
  },
  "tourPrevious": {
    "message": "Écran précédent"
  },
  "tourDone": {
    "message": "Terminé"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "En utilisant Firefox Screenshots, vous acceptez les $TERMSANDPRIVACYNOTICETERMSLINK$ et la $TERMSANDPRIVACYNOTICEPRIVACYLINK$ des services en ligne de Firefox.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "mentions légales"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "politique de confidentialité"
  }
}PK
!<qX!!)webextension/_locales/fy_NL/messages.json{
  "addonDescription": {
    "message": "Meitsje skermprintsjes of klips fan it web en bewarje se tydlik of permanint."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Meitsje in skermprintsje"
  },
  "myShotsLink": {
    "message": "Myn skermprintsjes"
  },
  "screenshotInstructions": {
    "message": "Sleep of klik op de side om in gebiet te selektearjen. Druk op ESC om te annulearjen."
  },
  "saveScreenshotSelectedArea": {
    "message": "Bewarje"
  },
  "saveScreenshotVisibleArea": {
    "message": "Sichtbere bewarje"
  },
  "saveScreenshotFullPage": {
    "message": "Folsleine side bewarje"
  },
  "cancelScreenshot": {
    "message": "Annulearje"
  },
  "downloadScreenshot": {
    "message": "Downloade"
  },
  "notificationLinkCopiedTitle": {
    "message": "Keppeling kopiearre"
  },
  "notificationLinkCopiedDetails": {
    "message": "De keppeling nei jo skermprintsje is nei it klamboerd kopiearre. Brûk $META_KEY$-V om te plakken.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Bûten tsjinst."
  },
  "requestErrorDetails": {
    "message": "Sorry! Wy koene jo skermprintsje net bewarje. Probearje it letter nochris."
  },
  "connectionErrorTitle": {
    "message": "Wy kinne net ferbine nei jo skermprintsjes."
  },
  "connectionErrorDetails": {
    "message": "Kontrolearje jo ynternetferbining. As jo wol ferbining meitsje kinne mei it ynternet, kin it wêze dat der tydlik in probleem is mei de tsjinst Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Wy koene jo skermprintsje net bewarje, omdat der in probleem is mei de tsjinst Firefox Screenshots. Probearje it letter nochris."
  },
  "unshootablePageErrorTitle": {
    "message": "It is net mooglik in skermprintsje fan dizze side te meitsjen."
  },
  "unshootablePageErrorDetails": {
    "message": "Dit is net in standert webside, dus jo kinne der net in skermprintsje fan meitsje."
  },
  "selfScreenshotErrorTitle": {
    "message": "Jo kinne net in skermprintsje meitsje fan in Firefox Screenshots-side!"
  },
  "emptySelectionErrorTitle": {
    "message": "Jo seleksje is te lyts"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots is útskeakele yn Priveenavigaasjemodus"
  },
  "privateWindowErrorDetails": {
    "message": "Sorry foar it ûngemak. Foar takomstige útjeften wurdt oan dizze funksje wurke."
  },
  "genericErrorTitle": {
    "message": "Oeps! Firefox Screenshots is yn 'e war."
  },
  "genericErrorDetails": {
    "message": "Wy binne net wis wat der krekt bard is. Wolle jo it nochris probearje of in skermprintsje fan in oare side meitsje?"
  },
  "tourBodyOne": {
    "message": "Meitsje, bewarje en diel skermprintsjes sûnder Firefox te ferlitten."
  },
  "tourHeaderTwo": {
    "message": "Fetsje wat jo wolle"
  },
  "tourBodyTwo": {
    "message": "Klik en sleep om in part fan in side te fetsjen. Jo kinne ek oer in gebiet gean om jo seleksje út te ljochtsjen."
  },
  "tourHeaderThree": {
    "message": "Fetsje finsters of folsleine websiden"
  },
  "tourBodyThree": {
    "message": "Selektearje knoppen rjochts boppe-oan om it sichtbere gebiet yn it finster te fetsjen, of fetsje in folsleine side."
  },
  "tourHeaderFour": {
    "message": "Nei jo winsk"
  },
  "tourBodyFour": {
    "message": "Bewarje jo byknippe skermprintsjes nei it web om se maklik te dielen, of download se nei jo kompjûter. Jo kinne ek op de knop Myn skermprintsjes klikke om al jo makke skermprintsjes te finen."
  },
  "tourSkip": {
    "message": "Oerslaan"
  },
  "tourNext": {
    "message": "Folgjende ôfbylding"
  },
  "tourPrevious": {
    "message": "Foarige ôfbylding"
  },
  "tourDone": {
    "message": "Dien"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Troch Firefox Screenshots te brûken, geane jo akkoard mei de $TERMSANDPRIVACYNOTICETERMSLINK$ en $TERMSANDPRIVACYNOTICEPRIVACYLINK$ fan Firefox-cloudtsjinsten.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Betingsten"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Privacyferklearring"
  }
}PK
!<-:)webextension/_locales/ga_IE/messages.json{
  "addonDescription": {
    "message": "Glac gearrthóga agus gabhálacha scáileáin ón Ghréasán agus sábháil iad, go sealadach nó go buan."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Glac Gabháil Scáileáin"
  },
  "myShotsLink": {
    "message": "Mo Chuid Gabhálacha"
  },
  "screenshotInstructions": {
    "message": "Tarraing nó cliceáil ar an leathanach chun réigiún a roghnú. Brúigh ESC le cealú."
  },
  "saveScreenshotSelectedArea": {
    "message": "Sábháil"
  },
  "saveScreenshotVisibleArea": {
    "message": "Sábháil an réigiún infheicthe"
  },
  "saveScreenshotFullPage": {
    "message": "Sábháil an leathanach iomlán"
  },
  "cancelScreenshot": {
    "message": "Cealaigh"
  },
  "downloadScreenshot": {
    "message": "Íoslódáil"
  },
  "notificationLinkCopiedTitle": {
    "message": "Cóipeáladh an Nasc"
  },
  "notificationLinkCopiedDetails": {
    "message": "Cóipeáladh nasc leis an ngabháil go dtí an ghearrthaisce. Brúigh $META_KEY$-V lena ghreamú.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Tá rud éigin as alt."
  },
  "requestErrorDetails": {
    "message": "Ár leithscéal! Theip orainn an ghabháil a shábháil. Bain triail eile as ar ball."
  },
  "connectionErrorTitle": {
    "message": "Ní féidir linn ceangal le do chuid gabhálacha."
  },
  "connectionErrorDetails": {
    "message": "Deimhnigh go bhfuil tú ceangailte leis an Idirlíon. Mura bhfuil tú ceangailte, ní bheidh tú in ann úsáid a bhaint as seirbhís Gabhálacha Scáileáin Firefox."
  },
  "loginErrorDetails": {
    "message": "Níorbh fhéidir linn an ghabháil scáileáin a shábháil toisc gur tharla earráid le seirbhís Gabhálacha Scáileáin Firefox. Bain triail eile as ar ball."
  },
  "unshootablePageErrorTitle": {
    "message": "Ní féidir linn gabháil scáileáin a ghlacadh ar an leathanach seo."
  },
  "unshootablePageErrorDetails": {
    "message": "Ní féidir gabháil scáileáin a ghlacadh toisc nach gnáthleathanach Gréasáin é seo."
  },
  "selfScreenshotErrorTitle": {
    "message": "Ní féidir leat gabháil scáileáin a ghlacadh ar leathanach Gabhálacha Scáileáin Firefox!"
  },
  "emptySelectionErrorTitle": {
    "message": "Roghnaigh tú réigiún róbheag"
  },
  "genericErrorTitle": {
    "message": "Úps! Tá Gabhálacha Scáileáin Firefox imithe sa fhraoch."
  },
  "genericErrorDetails": {
    "message": "Nílimid cinnte cad a tharla. An bhfuil fonn ort triail eile a bhaint as, nó gabháil scáileáin eile a ghlacadh?"
  },
  "tourBodyOne": {
    "message": "Glac, sábháil, agus comhroinn gabhálacha scáileáin gan Firefox a fhágáil."
  },
  "tourHeaderTwo": {
    "message": "An rud atá uait a ghabháil"
  },
  "tourBodyTwo": {
    "message": "Cliceáil agus tarraing le cuid de leathanach a ghabháil. Nó is féidir leat an luch a chur os cionn an réigiúin le gabháil."
  },
  "tourHeaderThree": {
    "message": "Fuinneoga nó leathanaigh iomlána a ghabháil"
  },
  "tourBodyThree": {
    "message": "Úsáid na cnaipí ag barr na fuinneoige ar dheis chun an réigiún infheicthe san fhuinneog a ghabháil, nó an leathanach iomlán."
  },
  "tourHeaderFour": {
    "message": "Go díreach mar is áil leat"
  },
  "tourBodyFour": {
    "message": "Is féidir leat gabhálacha a bhearradh agus a shábháil ar an nGréasán, nó iad a íoslódáil ar do ríomhaire. Is féidir teacht orthu go léir leis an gcnaipe Mo Chuid Gabhálacha."
  },
  "tourSkip": {
    "message": "NÁ BAC LEIS"
  },
  "tourNext": {
    "message": "An chéad sleamhnán eile"
  },
  "tourPrevious": {
    "message": "An sleamhnán roimhe seo"
  },
  "tourDone": {
    "message": "Críochnaithe"
  },
  "termsAndPrivacyNotice2": {
    "message": "Má úsáideann tú Gabhálacha Scáileáin Firefox, glacann tú leis na {termsAndPrivacyNoticeTermsLink} agus leis an {termsAndPrivacyNoticePrivacyLink}."
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Téarmaí"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "bhFógra Príobháideachais"
  }
}PK
!<}l)webextension/_locales/gu_IN/messages.json{
  "addonDescription": {
    "message": "વેબમાંથી ક્લિપ્સ અને સ્ક્રીનશૉટ્સ લો અને તેમને કામચલાઉ અથવા કાયમી રીતે સાચવો."
  },
  "addonAuthorsList": {
    "message": "Mozilla<screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "સ્ક્રીનશૉટ લેવા"
  },
  "myShotsLink": {
    "message": "મારા શોટ્સ"
  },
  "screenshotInstructions": {
    "message": "ખેંચો અથવા એક પ્રદેશ પસંદ કરવા માટે પાનાં પર ક્લિક કરો. રદ કરવા માટે ESC દબાવો."
  },
  "saveScreenshotSelectedArea": {
    "message": "સાચવો"
  },
  "saveScreenshotVisibleArea": {
    "message": "દૃશ્યમાન સાચવો"
  },
  "saveScreenshotFullPage": {
    "message": "સંપૂર્ણ પૃષ્ઠ સાચવો"
  },
  "cancelScreenshot": {
    "message": "રદ"
  },
  "downloadScreenshot": {
    "message": "ડાઉનલોડ"
  },
  "notificationLinkCopiedTitle": {
    "message": "લિંક કૉપિ"
  },
  "notificationLinkCopiedDetails": {
    "message": "તમારા શોટ માટે લિંક ક્લિપબોર્ડ પર કૉપિ કરવામાં આવ્યું છે. પ્રેસ $META_KEY$ -V પેસ્ટ કરવા માટે.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "હુકમ બહાર."
  },
  "requestErrorDetails": {
    "message": "માફ કરશો! અમે તમારા શોટ સાચવી શક્યા નથી. પછીથી ફરી પ્રયત્ન કરો."
  },
  "connectionErrorTitle": {
    "message": "અમે તમારા સ્ક્રીનશૉટ્સ ને કનેક્ટ થઈ શકતા નથી."
  },
  "connectionErrorDetails": {
    "message": "તમારું ઇન્ટરનેટ કનેક્શન તપાસો. તમે ઇન્ટરનેટથી કનેક્ટ કરવા માટે સક્ષમ છો, તો ત્યાં ફાયરફોક્સ સ્ક્રીનશોટ્સ સેવા સાથે એક અસ્થાયી સમસ્યા હોઈ શકે છે."
  },
  "loginErrorDetails": {
    "message": "અમે તમારા શોટ સાચવી શક્યા નથી કારણ કે Firefox સ્ક્રીનશોટ્સ સેવા સાથે એક સમસ્યા છે. પછીથી ફરી પ્રયત્ન કરો."
  },
  "unshootablePageErrorTitle": {
    "message": "અમે આ પૃષ્ઠ સ્ક્રીનશૉટ ન કરી શકીએ."
  },
  "unshootablePageErrorDetails": {
    "message": "આ એક પ્રમાણભૂત વેબ પૃષ્ઠ, જેથી તમે તેને એક સ્ક્રીનશૉટ ન લઈ શકો."
  },
  "selfScreenshotErrorTitle": {
    "message": "તમે પૃષ્ઠના Firefox સ્ક્રીનશોટ્સ શોટ લઇ શકો નહિ!"
  },
  "emptySelectionErrorTitle": {
    "message": "તમારી પસંદગી ખૂબ નાની છે"
  },
  "privateWindowErrorTitle": {
    "message": "ખાનગી બ્રાઉઝિંગ મોડમાં સ્ક્રીનશોટ અક્ષમ કરેલ છે"
  },
  "privateWindowErrorDetails": {
    "message": "અસુવીધી બદલ માફી. અમે ભવિષ્યના પ્રકાશનો માટે આ સુવિધા પર કામ કરી રહ્યા છીએ."
  },
  "genericErrorTitle": {
    "message": "થોભો! Firefox સ્ક્રીનશોટ્સ અવ્યવસ્થિત થઈ ગયા."
  },
  "genericErrorDetails": {
    "message": "અમે ખાતરી નથીકે શું માત્ર થયું છે . ફરી પ્રયાસ કરો અથવા એક અલગ પૃષ્ઠ એક શોટ લેવા માટે કાળજી કરો?"
  },
  "tourBodyOne": {
    "message": "લેવા, સાચવેલા, અને વહેંચાયેલ સ્ક્રીનશૉટ્સ Firefox છોડ્યાં વિના."
  },
  "tourHeaderTwo": {
    "message": "કેદ કરો તમને જોઈએ તે"
  },
  "tourBodyTwo": {
    "message": "પાનાંના માત્ર એક ભાગ મેળવવા માટે ક્લિક કરો અને ખેંચો. તમે પણ તમારી પસંદગી પ્રકાશિત કરવા માટે હૉવર કરી શકો છો."
  },
  "tourHeaderThree": {
    "message": "વિન્ડોઝ અથવા સમગ્ર પાના કેદ કરો"
  },
  "tourBodyThree": {
    "message": "ઉપર જમણા બટનો પસંદ કરો વિન્ડોમાં દૃશ્યમાન વિસ્તાર મેળવવા માટે અથવા આખુ પાનું કેપ્ચર કરવા માટે."
  },
  "tourHeaderFour": {
    "message": "તમને જે ગમે"
  },
  "tourBodyFour": {
    "message": "સરળ શેરિંગ માટે વેબ પર તમારા કપાઈ શોટ સાચવો, અથવા તેમને તમારા કમ્પ્યુટર પર ડાઉનલોડ કરો. તમે બધા શોટ મેળવવા માટે મારું શોટ્સ બટન પર ક્લિક કરી પણ શકો છો બધા શોટ તમે લીધેલા શોધવા માટે."
  },
  "tourSkip": {
    "message": "છોડવા"
  },
  "tourNext": {
    "message": "આગલી સ્લાઇડ"
  },
  "tourPrevious": {
    "message": "પહેલાની સ્લાઇડ"
  },
  "tourDone": {
    "message": "થઈ ગયું"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Firefox સ્ક્રીનશોટ્સ વાપરીને, તમે Firefox Cloud સેવાઓ સાથે સંમત થાઓ છો $TERMSANDPRIVACYNOTICETERMSLINK$ અને $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "શરતો"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "ખાનગી સૂચના"
  }
}PK
!<jI55&webextension/_locales/he/messages.json{
  "addonDescription": {
    "message": "יצירת צילומי מסך של דפי אינטרנט ושמירה שלהם באופן זמני או קבוע."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "צילום מסך"
  },
  "myShotsLink": {
    "message": "צילומי המסך שלי"
  },
  "screenshotInstructions": {
    "message": "נא לגרור או ללחוץ על הדף כדי לבחור תחום או על ESC לביטול."
  },
  "saveScreenshotSelectedArea": {
    "message": "שמירה"
  },
  "saveScreenshotVisibleArea": {
    "message": "שמירת התחום המוצג"
  },
  "saveScreenshotFullPage": {
    "message": "שמירת הדף במלואו"
  },
  "cancelScreenshot": {
    "message": "ביטול"
  },
  "downloadScreenshot": {
    "message": "הורדה"
  },
  "notificationLinkCopiedTitle": {
    "message": "הקישור הועתק"
  },
  "notificationLinkCopiedDetails": {
    "message": "הקישור לתמונה שלך הועתק ללוח. נא ללחוץ על $META_KEY$-V כדי להדביק.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "לא תקין."
  },
  "requestErrorDetails": {
    "message": "אנו מצטערים, אך לא ניתן היה לשמור את התמונה. נא לנסות שוב מאוחר יותר."
  },
  "connectionErrorTitle": {
    "message": "לא ניתן היה להתחבר אל מאגר צילומי המסך שלך."
  },
  "connectionErrorDetails": {
    "message": "נא לבדוק את החיבור לאינטרנט. אם הצלחת להתחבר לאינטרנט כנראה שקיימת תקלה זמנית עם שירות Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "אין אפשרות לשמור את צילום המסך שלך כיוון שישנה תקלה עם שירות Firefox Screenshots. נא לנסות שוב מאוחר יותר."
  },
  "unshootablePageErrorTitle": {
    "message": "לא ניתן לצלם דף זה."
  },
  "unshootablePageErrorDetails": {
    "message": "דף זה אינו דף אינטרנט תקני, ולכן לא ניתן היה לצלם אותו."
  },
  "selfScreenshotErrorTitle": {
    "message": "לא ניתן לצלם את הדף של Firefox Screenshot עצמו!"
  },
  "emptySelectionErrorTitle": {
    "message": "הבחירה שלך קטנה מידי"
  },
  "genericErrorTitle": {
    "message": "אויש! Firefox Screenshots ירד מהפסים."
  },
  "genericErrorDetails": {
    "message": "אנחנו לא בטוחים מה קרה פה הרגע. אכפת לך לנסות שוב או לצלם דף אחר?"
  },
  "tourBodyOne": {
    "message": "צילום, שמירה ושיתוף של צילומי מסך מבלי לעזוב את Firefox."
  },
  "tourHeaderTwo": {
    "message": "לצלם רק את מה שנחוץ לך"
  },
  "tourBodyTwo": {
    "message": "ניתן ללחוץ ולגרור כדי לצלם רק מקטע מהעמוד. ניתן גם לרחף מעל כדי לסמן את הבחירה שלך."
  },
  "tourHeaderThree": {
    "message": "לצלם חלונות או דפים שלמים"
  },
  "tourBodyThree": {
    "message": "בחרו בכפתורים שבחלק העליון כדי לצלם את האזור הגלוי בחלון או כדי לצלם את הדף כולו."
  },
  "tourHeaderFour": {
    "message": "לפי טעמך"
  },
  "tourBodyFour": {
    "message": "שמירת הצילומים החתוכים שלך לאחסון מקוון לצורך שיתוף פשוט יותר, או להוריד אותם למחשב שלך. ניתן גם ללחוץ על כפתור הצילומים שלי כדי למצוא את כל הצילומים שצילמת."
  },
  "tourSkip": {
    "message": "דילוג"
  },
  "tourNext": {
    "message": "השקופית הבאה"
  },
  "tourPrevious": {
    "message": "השקופית הקודמת"
  },
  "tourDone": {
    "message": "סיום"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "מעצם השימוש ב־Firefox Screenshots הכללים של שירותי הענן של Firefox‏ $TERMSANDPRIVACYNOTICETERMSLINK$ ו$TERMSANDPRIVACYNOTICEPRIVACYLINK$ מוסכמים עליך.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "תנאים"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "הצהרת פרטיות"
  }
}PK
!<
ii)webextension/_locales/hi_IN/messages.json{
  "addonDescription": {
    "message": "वेब से फ़ोटो और स्क्रीनशॉट लें और उन्हें अस्थायी या स्थायी रूप से सहेजें."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "स्क्रीनशॉट लें"
  },
  "myShotsLink": {
    "message": "मेरे चित्र"
  },
  "screenshotInstructions": {
    "message": "किसी क्षेत्र को चुनने के लिए पृष्ठ पर खींचें या क्लिक करें. रद्द करने के लिए ESC दबाएँ."
  },
  "saveScreenshotSelectedArea": {
    "message": "सहेजें"
  },
  "saveScreenshotVisibleArea": {
    "message": "दृश्यमान सहेजें"
  },
  "saveScreenshotFullPage": {
    "message": "पूर्ण पृष्ठ सहेजें"
  },
  "cancelScreenshot": {
    "message": "रद्द करें"
  },
  "downloadScreenshot": {
    "message": "डाउनलोड करें"
  },
  "notificationLinkCopiedTitle": {
    "message": "लिंक की नक़ल की गयी"
  },
  "notificationLinkCopiedDetails": {
    "message": "आपके शॉट के लिंक क्लिपबोर्ड पर कॉपी किए गए हैं. पेस्ट करने के लिए $META_KEY$-V दबाएँ.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "कार्यरत नहीं है."
  },
  "requestErrorDetails": {
    "message": "क्षमा करें! हम आपके शॉट को सहेज़ नहीं सके. कृपया बाद में पुन: प्रयास करें."
  },
  "connectionErrorTitle": {
    "message": "हम आपके स्क्रीनशॉट से जुड़ नहीं सकते हैं."
  },
  "connectionErrorDetails": {
    "message": "कृपया अपने इंटरनेट संपर्क की जाँच करें. यदि आप इंटरनेट से जुड़ने में सक्षम हैं, तो Firefox स्क्रीनशॉट सेवा के साथ एक अस्थायी समस्या हो सकती है."
  },
  "loginErrorDetails": {
    "message": "हम आपका शॉट सहेज नहीं सके क्योंकि Firefox स्क्रीनशॉट सेवा में कोई समस्या है. कृपया बाद में पुन: प्रयास करें."
  },
  "unshootablePageErrorTitle": {
    "message": "हम इस पृष्ठ का स्क्रीनशॉट नहीं ले सकते."
  },
  "unshootablePageErrorDetails": {
    "message": "यह एक मानक वेब पेज नहीं है, इसलिए आप इसका स्क्रीनशॉट नहीं ले सकते."
  },
  "selfScreenshotErrorTitle": {
    "message": "आप एक Firefox स्क्रीनशॉट पृष्ठ का शॉट नहीं ले सकते!"
  },
  "emptySelectionErrorTitle": {
    "message": "आपका चयन बहुत छोटा है"
  },
  "privateWindowErrorTitle": {
    "message": "निजी ब्राउज़िंग मोड में स्क्रीनशॉट निष्क्रिय कर दिया गया हैं"
  },
  "privateWindowErrorDetails": {
    "message": "असुविधा के लिए खेद हैं. हमलोग भविष्य संस्करण के लिए इस सुविधा पर काम कर रहे हैं."
  },
  "genericErrorTitle": {
    "message": "ओह! Firefox स्क्रीनशॉट बिगड़ गया."
  },
  "genericErrorDetails": {
    "message": "हम सुनिश्चित नहीं हैं कि अभी क्या हुआ. पुन: प्रयास या एक भिन्न पृष्ठ का एक शॉट लेना चाहते हैं?"
  },
  "tourBodyOne": {
    "message": "Firefox छोड़े बिना स्क्रीनशॉट लें, सहेजें, और साझा करें."
  },
  "tourHeaderTwo": {
    "message": "जो आप चाहते हैं उसे कैद करें"
  },
  "tourBodyTwo": {
    "message": "पृष्ठ के बस एक हिस्से को कैद करने के लिए क्लिक करें और खींचें. आप अपने चयन को हाइलाइट करने के लिए भी जा सकते हैं."
  },
  "tourHeaderThree": {
    "message": "विंडोज़ या संपूर्ण पृष्ठों को कैद करें"
  },
  "tourBodyThree": {
    "message": "विंडो में दिखाई देने वाले क्षेत्र या एक पूरे पृष्ठ को कैद करने के लिए ऊपर में दाहिनी तरफ़ के बटन का चयन करें."
  },
  "tourHeaderFour": {
    "message": "जैसा आप इसे चाहते हैं"
  },
  "tourBodyFour": {
    "message": "आसानी से साझा करने या उन्हें अपने कंप्यूटर पर डाउनलोड करने के लिए अपने क्रॉप किये गये शॉट को वेब पर सहेजें. आपके द्वारा लिए गये सभी शॉट्स को ढूंढने के लिए आप मेरे शॉट्स बटन पर भी क्लिक कर सकते हैं."
  },
  "tourSkip": {
    "message": "SKIP"
  },
  "tourNext": {
    "message": "अगली स्लाइड"
  },
  "tourPrevious": {
    "message": "पिछली स्लाइड"
  },
  "tourDone": {
    "message": "पूर्ण"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Firefox स्क्रीनशॉट का उपयोग करके, आप Firefox क्लाउड सेवाओं $TERMSANDPRIVACYNOTICETERMSLINK$ और $TERMSANDPRIVACYNOTICEPRIVACYLINK$ के लिए सहमत हैं.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "शर्तें"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "गोपनीयता सूचना"
  }
}PK
!<CC&webextension/_locales/hr/messages.json{
  "addonDescription": {
    "message": "Snimite ili slikajte stvari s Weba te ih spremite privremeno ili trajno."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.org>"
  },
  "contextMenuLabel": {
    "message": "Snimi zaslon"
  },
  "myShotsLink": {
    "message": "Moje snimke"
  },
  "screenshotInstructions": {
    "message": "Povucite ili kliknite na stranicu kako biste izabrali područje. Pritisnite ESC za otkazivanje radnje."
  },
  "saveScreenshotSelectedArea": {
    "message": "Spremi"
  },
  "saveScreenshotVisibleArea": {
    "message": "Spremi vidljivo"
  },
  "saveScreenshotFullPage": {
    "message": "Spremi cijelu stranicu"
  },
  "cancelScreenshot": {
    "message": "Otkaži"
  },
  "downloadScreenshot": {
    "message": "Preuzmi"
  },
  "notificationLinkCopiedTitle": {
    "message": "Poveznica je kopirana"
  },
  "notificationLinkCopiedDetails": {
    "message": "Poveznica do vaše snimke je kopirana u međuspremnik. Pristinite $META_KEY$-V da ju zalijepite.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Ne radi."
  },
  "requestErrorDetails": {
    "message": "Ups! Nismo uspjeli spremiti vašu snimku. Molimo pokušajte ponovo kasnije."
  },
  "connectionErrorTitle": {
    "message": "Ne možemo se spojiti s vašim snimkama."
  },
  "connectionErrorDetails": {
    "message": "Molimo provjerite vašu internet vezu. Ako ste uspješno povezani s internetom, možda postoji privremeni problem sa uslugama Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Nismo uspjeli spremiti vaš snimak zbog toga što postoji problem sa uslugama Firefox Screenshots. Molimo pokušajte kasnije."
  },
  "unshootablePageErrorTitle": {
    "message": "Ovu stranicu ne možemo snimiti."
  },
  "unshootablePageErrorDetails": {
    "message": "Ovo nije standardna Web stranica stoga ju ne možete snimiti."
  },
  "selfScreenshotErrorTitle": {
    "message": "Ne možete snimiti Firefox Screenshots stranicu!"
  },
  "emptySelectionErrorTitle": {
    "message": "Vaš odabir je premalen"
  },
  "genericErrorTitle": {
    "message": "Uf! Firefox Screenshots se zbrkao."
  },
  "genericErrorDetails": {
    "message": "Nismo sigurno što se upravo dogodilo. Možete li pokušati ponovno ili snimiti drukčiju stranicu?"
  },
  "tourBodyOne": {
    "message": "Snimite, spremite i dijelite snimke bez da napuštate Firefox."
  },
  "tourHeaderTwo": {
    "message": "Snimite ono što želite"
  },
  "tourBodyTwo": {
    "message": "Kliknite i povucite ako želite snimiti samo dio stranice. Također možete označiti vaš odabir tako da preko njega stavite pokazivač miša."
  },
  "tourHeaderThree": {
    "message": "Baš kako vam se sviđa"
  },
  "tourBodyThree": {
    "message": "Spremite vaše odrezane snimke na Web kako biste ih jednostavnije dijelili, ili ih jednostavno skinite na vaše računalo. Također možete kliknuti gumb Moje snimke kako biste pronašli sve vaše dosadašnje snimke."
  },
  "tourHeaderFour": {
    "message": "Snimajte prozore ili cijele stranice"
  },
  "tourBodyFour": {
    "message": "Odaberite gumbove na gornjem desnom kutu kako biste snimili vidljivo područje u prozoru ili cijelu stranicu."
  },
  "tourSkip": {
    "message": "PRESKOČI"
  },
  "tourNext": {
    "message": "Sljedeći slajd"
  },
  "tourPrevious": {
    "message": "Prijašnji slajd"
  },
  "tourDone": {
    "message": "Gotovo"
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Uvjeti"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Pravila o privatnosti"
  }
}PK
!<R'webextension/_locales/hsb/messages.json{
  "addonDescription": {
    "message": "Wzmiće klipy a fota wobrazowki z weba a składujće je nachwilu abo na přeco."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Foto wobrazowki činić"
  },
  "myShotsLink": {
    "message": "Moje fota wobrazowki"
  },
  "screenshotInstructions": {
    "message": "Ćehńće abo klikńće na stronu, zo byšće wobwod wubrał. Tłóčće na ESC, zo byšće přetorhnył."
  },
  "saveScreenshotSelectedArea": {
    "message": "Składować"
  },
  "saveScreenshotVisibleArea": {
    "message": "Widźomny wobwod składować"
  },
  "saveScreenshotFullPage": {
    "message": "Cyłu stronu składować"
  },
  "cancelScreenshot": {
    "message": "Přetorhnyć"
  },
  "downloadScreenshot": {
    "message": "Sćahnyć"
  },
  "notificationLinkCopiedTitle": {
    "message": "Wotkaz kopěrowany"
  },
  "notificationLinkCopiedDetails": {
    "message": "Wotkaz k wašemu fotu wobrazowki je so do mjezyskłada kopěrował. Tłóčće $META_KEY$-V, zo byšće jón zasadźił.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Skóncowany."
  },
  "requestErrorDetails": {
    "message": "Bohužel njemóžachmy waše foto wobrazowki składować. Prošu spytajće pozdźišo hišće raz."
  },
  "connectionErrorTitle": {
    "message": "Njemóžemy z wašimi fotami wobrazowki zwjazać."
  },
  "connectionErrorDetails": {
    "message": "Prošu přepruwujće swój internetny zwisk. Jeli móžeće z internetom zwjazać, je snano nachwilny problem ze słužbu Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Njemóžachmy swoje foto wobrazowki składować, dokelž je problem ze słužbu Firefox Screenshots. Prošu spytajće pozdźišo hišće raz."
  },
  "unshootablePageErrorTitle": {
    "message": "Foto wobrazowki tuteje strony móžne njeje."
  },
  "unshootablePageErrorDetails": {
    "message": "To standardna webstrona njeje, tohodla foto wobrazowki wot njeje móžne njeje."
  },
  "selfScreenshotErrorTitle": {
    "message": "Njemóžeće wobrazowku strony Firefox Screenshots fotografować!"
  },
  "emptySelectionErrorTitle": {
    "message": "Waš wuběr je přemały"
  },
  "privateWindowErrorTitle": {
    "message": "Firefox Screenshots je w priwatnym modusu znjemóžnjeny"
  },
  "privateWindowErrorDetails": {
    "message": "Wodajće prošu njepřijomnosće. Dźěłamy na tutej funkciji za přichodne wersije."
  },
  "genericErrorTitle": {
    "message": "Hopla! Firefox Screenshots njefunguje."
  },
  "genericErrorDetails": {
    "message": "Njejsmy sej wěsći, štož je so stało. Chceće hišće raz spytać abo chceće druhu stronu fotografować?"
  },
  "tourBodyOne": {
    "message": "Čińće, składujće a dźělće fota wobrazowki bjez toho, zo byšće Firefox wopušćił."
  },
  "tourHeaderTwo": {
    "message": "Fotografujće prosće, štož chceće"
  },
  "tourBodyTwo": {
    "message": "Klikńće a ćehńće, zo byšće dźěl strony fotografował. Móžeće tež pokazowak myški nad nim pohibować, zo byšće swój wuběr wuzběhnył."
  },
  "tourHeaderThree": {
    "message": "Wokna abo cyłe strony składować"
  },
  "tourBodyThree": {
    "message": "Wubjerće tłóčatka horjeka naprawo, zo byšće widźomny wobwod we woknje abo cyłu stronu fotografować."
  },
  "tourHeaderFour": {
    "message": "Tak, kaž so wam spodoba"
  },
  "tourBodyFour": {
    "message": "Składujće swoje přitřihane fota wobrazowki w interneće, zo byšće je lóšo dźělił, abo sćehńće je na swój ličak. Móžeće tež na tłóčatko „Moje fota wobrazowki“ kliknyć, zo byšće wšě fota wobrazowki namakał, kotrež sće činił."
  },
  "tourSkip": {
    "message": "Přeskočić"
  },
  "tourNext": {
    "message": "Přichodne foto"
  },
  "tourPrevious": {
    "message": "Předchadne foto"
  },
  "tourDone": {
    "message": "Hotowo"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Přez wužiwanje Firefox ScreenShots, zwoliće do $TERMSANDPRIVACYNOTICETERMSLINK$ a $TERMSANDPRIVACYNOTICEPRIVACYLINK$ Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Wuměnjenja"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Pokaz priwatnosće"
  }
}PK
!</\\&webextension/_locales/hu/messages.json{
  "addonDescription": {
    "message": "Készítsen videoklipeket és képernyőképeket a webről, és mentse őket ideiglenesen vagy véglegesen."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Készítsen képernyőképet"
  },
  "myShotsLink": {
    "message": "Az Ön képei"
  },
  "screenshotInstructions": {
    "message": "Húzza, vagy kattintson a lapra a terület kiválasztásához. Nyomjon ESC-t a megszakításhoz."
  },
  "saveScreenshotSelectedArea": {
    "message": "Mentés"
  },
  "saveScreenshotVisibleArea": {
    "message": "Láthatóak mentése"
  },
  "saveScreenshotFullPage": {
    "message": "Teljes oldal mentése"
  },
  "cancelScreenshot": {
    "message": "Mégse"
  },
  "downloadScreenshot": {
    "message": "Letöltés"
  },
  "notificationLinkCopiedTitle": {
    "message": "Hivatkozás másolva"
  },
  "notificationLinkCopiedDetails": {
    "message": "A képernyőképre mutató hivatkozás a vágólapra lett másolva. Nyomjon $META_KEY$-V-t a beillesztéshez.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Nem működik."
  },
  "requestErrorDetails": {
    "message": "Bocsánat! Nem tudtuk menteni a képet. Próbálkozzon később."
  },
  "connectionErrorTitle": {
    "message": "Nem tudunk kapcsolódni a képernyőképekhez."
  },
  "connectionErrorDetails": {
    "message": "Ellenőrizze az internetkapcsolatot. Ha tud kapcsolódni az internetre, akkor lehet, hogy ideiglenes probléma van a Firefox képernyőképek szolgáltatással."
  },
  "loginErrorDetails": {
    "message": "Nem tudtuk elmenteni a képét, mert probléma lépett fel a Firefox képernyőképek szolgáltatással. Próbálja újra később."
  },
  "unshootablePageErrorTitle": {
    "message": "Nem lehet képet készíteni erről a lapról."
  },
  "unshootablePageErrorDetails": {
    "message": "Ez egy nem szabványos weblap, így nem készíthet róla képernyőképet."
  },
  "selfScreenshotErrorTitle": {
    "message": "Nem készíthet képet a Firefox Screenshots oldalról!"
  },
  "emptySelectionErrorTitle": {
    "message": "A kijelölés túl kicsi"
  },
  "privateWindowErrorTitle": {
    "message": "A képernyőképek le vannak tiltva Privát böngészésben"
  },
  "privateWindowErrorDetails": {
    "message": "Sajnáljuk a kényelmetlenséget. Dolgozunk ezen a funkción a jövőbeli kiadásokhoz."
  },
  "genericErrorTitle": {
    "message": "Húha! A Firefox Screenshots megkergült."
  },
  "genericErrorDetails": {
    "message": "Nem vagyunk benne biztosak, hogy mi történt. Próbálja újra, vagy készítsen képet egy másik oldalról."
  },
  "tourBodyOne": {
    "message": "Készítsen, mentsen és osszon meg képernyőképeket, anélkül, hogy elhagyná a Firefoxot."
  },
  "tourHeaderTwo": {
    "message": "Csak azt mentse, amit szeretne"
  },
  "tourBodyTwo": {
    "message": "Kattintson és húzzon, hogy csak a lap egy részét mentse el. Vagy csak rá is mutathat a kijelöléshez."
  },
  "tourHeaderThree": {
    "message": "Mentsen ablakokat vagy teljes lapokat"
  },
  "tourBodyThree": {
    "message": "Válassza a jobb felső sarokban lévő gombokat, hogy egy látható területet mentsen az ablakból, vagy elmentsen egy teljes oldalt."
  },
  "tourHeaderFour": {
    "message": "Ahogy tetszik"
  },
  "tourBodyFour": {
    "message": "Mentse a kivágott képeket a webre a könnyebb megosztáshoz, vagy töltse le a számítógépére. Rá is kattinthat a Képernyőképek gombra, hogy megtalálja az összes képét."
  },
  "tourSkip": {
    "message": "Kihagyás"
  },
  "tourNext": {
    "message": "Következő dia"
  },
  "tourPrevious": {
    "message": "Előző dia"
  },
  "tourDone": {
    "message": "Kész"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "A Firefox képernyőképek használatával beleegyezik a Firefox felhőszolgáltatások $TERMSANDPRIVACYNOTICETERMSLINK$ és $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Feltételekbe"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Adatvédelmi nyilatkozatba"
  }
}PK
!<#)webextension/_locales/hy_AM/messages.json{
  "addonDescription": {
    "message": "Ստացեք հոլովակներ և էկրանի հանույթներ վեբից և պահպանեք դանք ժամանակավոր կամ մշտապես:"
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Ստանալ էկրանի պատկերը"
  },
  "myShotsLink": {
    "message": "Իմ պատկերները"
  },
  "screenshotInstructions": {
    "message": "Քաշեք և սեղմեք էջի վրա՝ ընտրելու տարածքը: Սեղմեք ESC՝ չեղարկելու համար:"
  },
  "saveScreenshotSelectedArea": {
    "message": "Պահպանել"
  },
  "saveScreenshotVisibleArea": {
    "message": "Պահպանելի տեսանելի"
  },
  "saveScreenshotFullPage": {
    "message": "Պահպանել ամբողջ էջը"
  },
  "cancelScreenshot": {
    "message": "Չեղարկել"
  },
  "downloadScreenshot": {
    "message": "Ներբեռնել"
  },
  "notificationLinkCopiedTitle": {
    "message": "Հղումը պատճենվել է"
  },
  "notificationLinkCopiedDetails": {
    "message": "Ձեր պատկերի հղումը պատճենվել է: Սեղմեք $META_KEY$-V՝ այն տեղադրելու համար:",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Անսարք:"
  },
  "requestErrorDetails": {
    "message": "Ցավոք մենք չենք կարող պահպանել պատկեր: Կրկին փորձեք ավելի ուշ:"
  },
  "connectionErrorTitle": {
    "message": "Հնարավոր չէ ապակցել էկրանի ձեր հանույթներին:"
  },
  "connectionErrorDetails": {
    "message": "Խնդրում ենք ստուգել համացանցային կապակցումը: Եթե մուտք չունեք համացանց՝ հնարավոր է՝ դա Firefox Screenshots ծառայության հետ կապված ժամանակավոր խնդիր է:"
  },
  "loginErrorDetails": {
    "message": "Մենք չենք կարող պահպանել ձեր պատկերը, քանի որ խնդիր կա Firefox Screenshots ծառայության հետ: Փորձեք ավելի ուշ:"
  },
  "unshootablePageErrorTitle": {
    "message": "Հնարավոր չէ ստանալ էկրանի պատկերը:"
  },
  "unshootablePageErrorDetails": {
    "message": "Սա ստանդարտ վեբ էջ չէ, ուստի դուք չեք կարող ստանալ դրա պատկերը:"
  },
  "selfScreenshotErrorTitle": {
    "message": "Դուք չեք կարող ստանալ Firefox Screenshots-ի էջի պատկերը:"
  },
  "emptySelectionErrorTitle": {
    "message": "Ընտրվածը քիչ է"
  },
  "genericErrorTitle": {
    "message": "Firefox Screenshots-ը գնաց գլխիվայր:"
  },
  "genericErrorDetails": {
    "message": "Մենք վստահ չենք, թե ինչ է տեղի ունեցնել: Կրկին փորձեք կամ փորձեք ստանալ մեկ այլ էջի պատկերը:"
  },
  "tourBodyOne": {
    "message": "Ստացեք, պահպանեք և համօգտագործեք էկրանի հանույթները՝ առանց Firefox-ը լքելու:"
  },
  "tourHeaderTwo": {
    "message": "Ստացեք միայն այն, ինչ Ձեզ պետք է:"
  },
  "tourBodyTwo": {
    "message": "Սեղմեք և քաշեք՝ ստանալու համար միայն էջի մի մասը: Նաև կարող եք վրայով անցկացնել՝ գունանշելու համար ընտրումը:"
  },
  "tourHeaderThree": {
    "message": "Ստանալ պատուհանը կամ ամբողջ էջեր"
  },
  "tourBodyThree": {
    "message": "Ընտրեք կոճակները վերևի աջ մասում՝ տեսանելի հատվածը ստանալու համար պատուհանում կամ ամբողջ էջը ստանալու համար:"
  },
  "tourHeaderFour": {
    "message": "Ինչպես որ հավանում եք այն"
  },
  "tourBodyFour": {
    "message": "Պահպանեք ձեր եզրատած որոշ պատկերներ վեբում՝ դրանք հեշտությամբ համօգտագործելու կամ ներբեռնելու համար ձեր համակարգչում: Նաև կարող եք սեղմել Իմ պատկերները՝ գտնելու ձեր բոլոր ֆայլերը:"
  },
  "tourSkip": {
    "message": "Բաց թողնել"
  },
  "tourNext": {
    "message": "Հաջորդ սահիկը"
  },
  "tourPrevious": {
    "message": "Նախորդ սահիկը"
  },
  "tourDone": {
    "message": "Պատրաստ է"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Օգտագործելով Firefox Screenshots-ը՝ դուք ընդունում եք Firefox Cloud ծառայությունների $TERMSANDPRIVACYNOTICETERMSLINK$ը և $TERMSANDPRIVACYNOTICEPRIVACYLINK$ը:",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Պայմաններ"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Գաղտնիության ծանուցում"
  }
}PK
!<&webextension/_locales/id/messages.json{
  "addonDescription": {
    "message": "Rekam klip dan tangkapan layar dari Web dan simpan untuk sementara atau secara permanen."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Buat Tangkapan layar"
  },
  "myShotsLink": {
    "message": "Gambar Saya"
  },
  "screenshotInstructions": {
    "message": "Seret atau klik pada laman untuk memilih area. Tekan ESC untuk membatalkan."
  },
  "saveScreenshotSelectedArea": {
    "message": "Simpan"
  },
  "saveScreenshotVisibleArea": {
    "message": "Simpan yang terlihat"
  },
  "saveScreenshotFullPage": {
    "message": "Simpan laman sepenuhnya"
  },
  "cancelScreenshot": {
    "message": "Batal"
  },
  "downloadScreenshot": {
    "message": "Unduh"
  },
  "notificationLinkCopiedTitle": {
    "message": "Tautan Disalin"
  },
  "notificationLinkCopiedDetails": {
    "message": "Tautan ke gambar Anda telah disalin ke papan klip. Tekan $META_KEY$-V untuk menempelkan.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Tak dapat digunakan."
  },
  "requestErrorDetails": {
    "message": "Maaf! Kami tidak dapat menyimpan gambar Anda. Silakan coba lagi."
  },
  "connectionErrorTitle": {
    "message": "Kami tidak dapat terhubung dengan tangkapan layar Anda."
  },
  "connectionErrorDetails": {
    "message": "Silakan periksa sambungan Internet Anda. Jika Anda dapat tersambung ke Internet, mungkin terjadi masalah sementara pada layanan Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Kami tidak dapat menyimpan gambar Anda karena ada masalah dengan layanan Firefox Screenshots. Silakan coba kembali nanti."
  },
  "unshootablePageErrorTitle": {
    "message": "Kami tidak dapat menangkap layar laman ini."
  },
  "unshootablePageErrorDetails": {
    "message": "Ini bukan laman Web yang standar, sehingga Anda tidak dapat membuat tangkapan dari layar ini."
  },
  "selfScreenshotErrorTitle": {
    "message": "Anda tidak dapat merekam gambar dari laman Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Seleksi Anda terlalu kecil"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots dinonaktifkan di Mode Penjelajahan Pribadi"
  },
  "privateWindowErrorDetails": {
    "message": "Maaf atas ketidaknyamanannya. Kami sedang mengerjakan fitur ini untuk peluncuran masa mendatang."
  },
  "genericErrorTitle": {
    "message": "Wah! Firefox Screenshots mendadak kacau."
  },
  "genericErrorDetails": {
    "message": "Kami tidak yakin akan apa yang terjadi. Ingin mencoba lagi atau merekam gambar dari laman yang berbeda?"
  },
  "tourBodyOne": {
    "message": "Ambil, simpan, dan bagikan tangkapan layar tanpa meninggalkan Firefox."
  },
  "tourHeaderTwo": {
    "message": "Rekam Bagian Yang Anda Inginkan"
  },
  "tourBodyTwo": {
    "message": "Klik dan seret untuk merekam sebagian area laman. Anda juga dapat menggeser kursor untuk menyoroti pilihan Anda."
  },
  "tourHeaderThree": {
    "message": "Rekam Jendela atau Seluruh Laman"
  },
  "tourBodyThree": {
    "message": "Pilih tombol di kanan atas untuk merekam area yang terlihat pada jendela atau rekam seluruh laman."
  },
  "tourHeaderFour": {
    "message": "Sesuka Anda"
  },
  "tourBodyFour": {
    "message": "Simpan potongan tangkapan Anda ke Web agar mudah dibagikan, atau unduh ke komputer. Anda pun dapat mengeklik pada tombol Gambar Saya untuk menemukan semua tangkapan yang pernah Anda rekam."
  },
  "tourSkip": {
    "message": "Lewati"
  },
  "tourNext": {
    "message": "Salindia Selanjutnya"
  },
  "tourPrevious": {
    "message": "Salindia Sebelumnya"
  },
  "tourDone": {
    "message": "Selesai"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Dengan menggunakan Firefox Screenshots, Anda setuju dengan $TERMSANDPRIVACYNOTICETERMSLINK$ dan $TERMSANDPRIVACYNOTICEPRIVACYLINK$ Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Ketentuan"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Kebijakan Privasi"
  }
}PK
!<[M.&webextension/_locales/it/messages.json{
  "addonDescription": {
    "message": "Crea screenshot di contenuti sul Web e salvali, solo per un periodo di tempo o in modo permanente."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Cattura screenshot"
  },
  "myShotsLink": {
    "message": "I miei screenshot"
  },
  "screenshotInstructions": {
    "message": "Trascina o fai clic su una pagina per selezionare una regione. Premi ESC per annullare."
  },
  "saveScreenshotSelectedArea": {
    "message": "Salva"
  },
  "saveScreenshotVisibleArea": {
    "message": "Salva l’area visibile"
  },
  "saveScreenshotFullPage": {
    "message": "Salva l’intera schermata"
  },
  "cancelScreenshot": {
    "message": "Annulla"
  },
  "downloadScreenshot": {
    "message": "Scarica"
  },
  "notificationLinkCopiedTitle": {
    "message": "Link copiato"
  },
  "notificationLinkCopiedDetails": {
    "message": "Il link all’immagine è stato copiato negli appunti. Utilizza $META_KEY$-V per incollarlo.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Fuori servizio"
  },
  "requestErrorDetails": {
    "message": "Siamo spiacenti, non è stato possibile salvare l’immagine. Riprova più tardi."
  },
  "connectionErrorTitle": {
    "message": "Non è possibile accedere agli screenshot salvati."
  },
  "connectionErrorDetails": {
    "message": "Verifica che la connessione a Internet stia funzionando correttamente. Se è possibile accedere ad altri siti, potrebbe trattarsi di un problema temporaneo con il servizio Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Non è stato possibile salvare l’immagine in quanto si è verificato un problema con il servizio Firefox Screenshots. Riprova più tardi."
  },
  "unshootablePageErrorTitle": {
    "message": "Non è possibile salvare uno screenshot di questa pagina."
  },
  "unshootablePageErrorDetails": {
    "message": "Non è possibile salvare uno screenshot in quanto non si tratta di una normale pagina web."
  },
  "selfScreenshotErrorTitle": {
    "message": "Non è possibile salvare uno screenshot di una pagina di Firefox Screenshots"
  },
  "emptySelectionErrorTitle": {
    "message": "L’area selezionata è troppo piccola"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots è disattivato in navigazione anonima."
  },
  "privateWindowErrorDetails": {
    "message": "Ci dispiace per l’inconveniente. Stiamo lavorando a questa funzione per le prossime versioni."
  },
  "genericErrorTitle": {
    "message": "Wow! Firefox Screenshots è andato in tilt"
  },
  "genericErrorDetails": {
    "message": "Non sappiamo che cosa sia successo. Riprova, magari con una pagina diversa."
  },
  "tourBodyOne": {
    "message": "Cattura, salva e condividi screenshot senza mai uscire da Firefox."
  },
  "tourHeaderTwo": {
    "message": "Cattura solo ciò che ti serve"
  },
  "tourBodyTwo": {
    "message": "Fai clic e trascina per catturare solo una parte della pagina. Posiziona il mouse sopra all’area selezionata per evidenziarla."
  },
  "tourHeaderThree": {
    "message": "Cattura una finestra o una pagina intera"
  },
  "tourBodyThree": {
    "message": "Utilizza i pulsanti in alto a destra per catturare una parte della finestra o l’intera pagina."
  },
  "tourHeaderFour": {
    "message": "Come piace a te"
  },
  "tourBodyFour": {
    "message": "Cattura lo screenshot di una pagina web, ritaglialo e salvalo online per condividerlo in modo più veloce, oppure scaricalo sul tuo computer. Puoi anche utilizzare il pulsante “I miei screenshot” per ritrovare tutte le immagini che hai salvato."
  },
  "tourSkip": {
    "message": "Ignora"
  },
  "tourNext": {
    "message": "Schermata successiva"
  },
  "tourPrevious": {
    "message": "Schermata precedente"
  },
  "tourDone": {
    "message": "Fine"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Utilizzando Firefox Screenshots si accettano le $TERMSANDPRIVACYNOTICETERMSLINK$ e l’$TERMSANDPRIVACYNOTICEPRIVACYLINK$ di Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "condizioni di utilizzo"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "informativa sulla privacy"
  }
}PK
!<gj&webextension/_locales/ja/messages.json{
  "addonDescription": {
    "message": "ウェブからスクリーンショットを撮って、一時的または永久にそれを保存しましょう。"
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "スクリーンショットを撮る"
  },
  "myShotsLink": {
    "message": "自分のショット"
  },
  "screenshotInstructions": {
    "message": "ページをドラッグまたはクリックして範囲を選択してください。ESC キーを押すとキャンセルできます。"
  },
  "saveScreenshotSelectedArea": {
    "message": "保存"
  },
  "saveScreenshotVisibleArea": {
    "message": "表示範囲を保存"
  },
  "saveScreenshotFullPage": {
    "message": "ページ全体を保存"
  },
  "cancelScreenshot": {
    "message": "キャンセル"
  },
  "downloadScreenshot": {
    "message": "ダウンロード"
  },
  "notificationLinkCopiedTitle": {
    "message": "リンクをコピーしました"
  },
  "notificationLinkCopiedDetails": {
    "message": "ショットへのリンクがクリップボードへコピーされました。$META_KEY$+V キーで貼り付けられます。",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "問題が発生しました。"
  },
  "requestErrorDetails": {
    "message": "申し訳ありませんが、ショットを保存できませんでした。また後で試してください。"
  },
  "connectionErrorTitle": {
    "message": "Screenshots ライブラリへ接続できません。"
  },
  "connectionErrorDetails": {
    "message": "お使いのインターネット接続を確認してください。インターネットへ接続できる場合は、Firefox Screenshots サービスに一時的な問題が発生しているものと思われます。"
  },
  "loginErrorDetails": {
    "message": "Firefox Screenshots サービスに問題があるため、ショットを保存できませんでした。また後で試してください。"
  },
  "unshootablePageErrorTitle": {
    "message": "このページはスクリーンショットを撮れません。"
  },
  "unshootablePageErrorDetails": {
    "message": "これは通常のウェブページでないため、スクリーンショットを撮ることができません。"
  },
  "selfScreenshotErrorTitle": {
    "message": "Firefox Screenshots ページのショットは撮れません。"
  },
  "emptySelectionErrorTitle": {
    "message": "選択範囲が小さすぎます"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots はプライベートブラウジングモードでは使用できません"
  },
  "privateWindowErrorDetails": {
    "message": "ご不便をおかけして申し訳ありません。今後のリリースでこの機能を提供できるよう取り組んでいます。"
  },
  "genericErrorTitle": {
    "message": "Firefox Screenshots に問題が発生しました。"
  },
  "genericErrorDetails": {
    "message": "何か問題が発生したようです。再度試すか、別のページのショットを撮ってみてください。"
  },
  "tourBodyOne": {
    "message": "Firefox を離れることなく、スクリーンショットを撮影、保存、共有。"
  },
  "tourHeaderTwo": {
    "message": "必要な部分だけをキャプチャ"
  },
  "tourBodyTwo": {
    "message": "クリック&ドラッグでページの一部だけをキャプチャできます。また、マウスを当てれば選択範囲が強調表示されます。"
  },
  "tourHeaderThree": {
    "message": "ウィンドウもしくはページ全体をキャプチャ"
  },
  "tourBodyThree": {
    "message": "右上のボタンを選択して、ウィンドウ内の表示範囲もしくはページ全体をキャプチャしましょう。"
  },
  "tourHeaderFour": {
    "message": "お好きなように"
  },
  "tourBodyFour": {
    "message": "切り取ったショットを簡単に共有できるようウェブ上に保存したり、手元へダウンロードしたり。また「自分のショット」ボタンをクリックすれば、これまでに撮ったすべてのショットを見られます。"
  },
  "tourSkip": {
    "message": "スキップ"
  },
  "tourNext": {
    "message": "次のスライド"
  },
  "tourPrevious": {
    "message": "前のスライド"
  },
  "tourDone": {
    "message": "完了"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Firefox Screenshots を使うことで、あなたは Firefox Cloud Services の $TERMSANDPRIVACYNOTICETERMSLINK$ と $TERMSANDPRIVACYNOTICEPRIVACYLINK$ に同意したことになります。",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "利用規約"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "プライバシー通知"
  }
}PK
!<@88&webextension/_locales/ka/messages.json{
  "addonDescription": {
    "message": "გადაუღეთ ვიდეოები ან სურათები ვებ-გვერდებს და შეინახეთ დროებით ან მუდმივად."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "ეკრანისთვის სურათის გადაღება"
  },
  "myShotsLink": {
    "message": "ჩემი გადაღებულები"
  },
  "screenshotInstructions": {
    "message": "გადაადგილეთ ან დააწკაპეთ გვერდზე არეალის მოსანიშნად. გასაუქმებლად დააჭირეთ ESC-ს."
  },
  "saveScreenshotSelectedArea": {
    "message": "შენახვა"
  },
  "saveScreenshotVisibleArea": {
    "message": "ხილული ნაწილის შენახვა"
  },
  "saveScreenshotFullPage": {
    "message": "მთლიანი გვერდის შენახვა"
  },
  "cancelScreenshot": {
    "message": "გაუქმება"
  },
  "downloadScreenshot": {
    "message": "ჩამოტვირთვა"
  },
  "notificationLinkCopiedTitle": {
    "message": "ბმული დაკოპირებულია"
  },
  "notificationLinkCopiedDetails": {
    "message": "თქვენი სურათის ბმული დაკოპირებულია. ჩასმისთვის დააწექით $META_KEY$-V.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "გაფუჭებულია."
  },
  "requestErrorDetails": {
    "message": "ვწუხვარ! გადაღებული სურათის შენახვა ვერ ხერხდება. მოგვიანებით სცადეთ."
  },
  "connectionErrorTitle": {
    "message": "თქვენს გადაღებულ სურათებთან კავშირი ვერ ხერხდება."
  },
  "connectionErrorDetails": {
    "message": "გთხოვთ შეამოწმოთ ქსელთან კავშირი. თუ ინტერნეტში თავისუფლად გადიხართ, ე.ი. Firefox Screenshot-ის მომსახურებას აქვს დროებითი პრობლემა."
  },
  "loginErrorDetails": {
    "message": "თქვენი სურათის შენახვა ვერ ხერხდება, რადგან შეფერხებაა Firefox Screenshots მომსახურებასთან დაკავშირებით. გთხოვთ, სცადოთ მოგვიანებით."
  },
  "unshootablePageErrorTitle": {
    "message": "ამ გვერდისთვის სურათის გადაღება ვერ ხერხდება."
  },
  "unshootablePageErrorDetails": {
    "message": "ეს არ არის ჩვეულებრივი ვებ-გვერდი, ამიტომაც შეუძლებელია სურათის გადაღება."
  },
  "selfScreenshotErrorTitle": {
    "message": "Firefox Screenshots-ის გვერდისთვის სურათის გადაღება არ შეგიძლიათ!"
  },
  "emptySelectionErrorTitle": {
    "message": "შერჩეული არეალი ძალიან პატარაა"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots გათიშულია პირადი თვალიერების რეჟიმისას"
  },
  "privateWindowErrorDetails": {
    "message": "ბოდიშს გიხდით გაუგებრობის გამო. ჩვენ ვმუშაობთ ამ შესაძლებლობის დამატებაზე, სამომავლო ვერსიებში."
  },
  "genericErrorTitle": {
    "message": "ვაი! Firefox Screenshots მწყობრიდან გამოვიდა."
  },
  "genericErrorDetails": {
    "message": "გაუგებარია რა მოხდა. ისევ ცდით ხელახლა თუ სხვა ვებ-გვერდს გადაუღებთ სურათს?"
  },
  "tourBodyOne": {
    "message": "გადაიღეთ, შეინახეთ და გააზიარეთ ეკრანის სურათები Firefox-იდან გაუსვლელად."
  },
  "tourHeaderTwo": {
    "message": "გადაუღეთ სურათი რასაც გინდათ"
  },
  "tourBodyTwo": {
    "message": "გადაადგილეთ ან დააწკაპეთ გვერდზე გადასაღები ნაწილის შესარჩევად. ასევე, კურსორის გადატარებით შეგიძლიათ მონიშნოთ სასურველი არეალი."
  },
  "tourHeaderThree": {
    "message": "გადაუღეთ სურათები ფანჯრებს ან მთლიან ვებ-გვერდებს"
  },
  "tourBodyThree": {
    "message": "მარჯვენა ზედა კუთხეში არსებული ღილაკების საშუალებით, შეგიძლიათ გადაუღოთ სურათი ხილულ ნაწილს, ან მთლიან გვერდს."
  },
  "tourHeaderFour": {
    "message": "როგორც გენებოთ"
  },
  "tourBodyFour": {
    "message": "ამოჭრილი სურათების შენახვა შეგიძლიათ ინტერნეტში, მარტივად გასაზიარებლად, ან შეგიძლიათ კომპიუტერში ჩამოტვირთვა. ასევე, ღილაკზე \"ჩემი გადაღებულები\" დაწკაპებით, იხილავთ თქვენს მიერ გადაღებულ ყველა სურათს."
  },
  "tourSkip": {
    "message": "გამოტოვება"
  },
  "tourNext": {
    "message": "შემდეგი"
  },
  "tourPrevious": {
    "message": "წინა"
  },
  "tourDone": {
    "message": "მზადაა"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Firefox Screenshots-ის გამოყენებით, თქვენ ეთანხმებით $TERMSANDPRIVACYNOTICETERMSLINK$ და $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "პირობებს"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "პირადი მონაცემების შესახებ განცხადებას"
  }
}PK
!<`*
'webextension/_locales/kab/messages.json{
  "addonDescription": {
    "message": "Ṭṭef imrayen akked igdilen si Web sakin sekles-iten s wudem askudan neγ s wudem yezgan."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Ṭṭef agdil"
  },
  "myShotsLink": {
    "message": "Tuṭṭfiwin-iw"
  },
  "screenshotInstructions": {
    "message": "Zuγer sakin sit γef af usebter akken ad tferneḍ tamnaṭ. Senned γef ESC akken ad tesfesxeḍ."
  },
  "saveScreenshotSelectedArea": {
    "message": "Sekles"
  },
  "saveScreenshotVisibleArea": {
    "message": "Sekles ayen ibanen"
  },
  "saveScreenshotFullPage": {
    "message": "Sekles asebter meṛṛa"
  },
  "cancelScreenshot": {
    "message": "Sefsex"
  },
  "downloadScreenshot": {
    "message": "Sider"
  },
  "notificationLinkCopiedTitle": {
    "message": "Aseγwen yettwanγel"
  },
  "notificationLinkCopiedDetails": {
    "message": "Aseγwen ar tuṭṭfa-ik yettwanγel yef afus. Senned yef $META_KEY$-V akken ad tsenṭḍeḍ.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Yeffeγ i talast."
  },
  "requestErrorDetails": {
    "message": "Suref-aγ! Ur nezmir ara ad nsekles tuṭṭfa-ik. Ɛreḍ tikelt-nniḍen."
  },
  "connectionErrorTitle": {
    "message": "Ur nezmir ara ad neqqen ar tuṭṭfiwin-ik n ugdil."
  },
  "connectionErrorDetails": {
    "message": "Senqed tuqqna-ik Internet. Ma yella tzemred ad teqqneḍ ar Internet, ahat d ugur kan meẓẓiyen deg umeẓlu Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "UR nseklas ara tuṭṭfa-ik acku yella ugur akked umezlu Firefox Screenshots. Ma ulac aɣilif ɛreḍ tikelt-nniḍen."
  },
  "unshootablePageErrorTitle": {
    "message": "Ur nezmir ara ad neṭṭef agdil n usebter-agi."
  },
  "unshootablePageErrorDetails": {
    "message": "Mačči d asebter Web am iyaḍ, ur tizmireḍ ara ad s-teṭṭfeḍ agdil."
  },
  "selfScreenshotErrorTitle": {
    "message": "Ur tezmireḍ ar ad teṭṭfeḍ agdil n usebter Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Tafrant inek wezzil-t aṭas"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots yensa deg uskar uslig"
  },
  "privateWindowErrorDetails": {
    "message": "Suref-aɣ ɣef aya. Aqlaɣ nxeddem ɣef tmahilt i yileqman d-iteddun."
  },
  "genericErrorTitle": {
    "message": "Ihuh! Firefox Screenshots ur iteddu ara."
  },
  "genericErrorDetails": {
    "message": "Ur neẓri ara acu yeḍran. Ɛreḍ tikelt-nniḍen neɣ ṭṭef agdil n usebter-nniḍen?"
  },
  "tourBodyOne": {
    "message": "Ṭṭef, sekles, bḍu igdilen war ma teffɣeḍ si Firefox."
  },
  "tourHeaderTwo": {
    "message": "Ṭṭef kan ayen tebγiḍ"
  },
  "tourBodyTwo": {
    "message": "Sit sakin zuɣer akken ad teṭṭfeḍ aḥric seg usebter. Tzemreḍ daɣen ad tesrifgeḍ akken ad tsebṛuṛqeḍ afran-ik."
  },
  "tourHeaderThree": {
    "message": "Ṭṭef isfuyla neγ isebtar meṛṛa"
  },
  "tourBodyThree": {
    "message": "Fren tiqeffalin s afella ayeffus akken ad teṭṭfeḍ tamnaṭ yettbanen deg usfaylu neɣ asebter i meṛṛa."
  },
  "tourHeaderFour": {
    "message": "Akken tebγiḍ"
  },
  "tourBodyFour": {
    "message": "Sekles tuṭṭfiwin-ik ar Web i beṭṭu fessusen, neɣ sider-itent-id ar uselkim-ik. Tzemr€d daɣen ad tiseḍ ɣef tqeffalt Tiṭṭfiwin-iw akken ad tafeḍ akk tuṭṭfiwin n ugdil i teggid."
  },
  "tourSkip": {
    "message": "Zgel"
  },
  "tourNext": {
    "message": "Tigri n zdat"
  },
  "tourPrevious": {
    "message": "Tigri n deffir"
  },
  "tourDone": {
    "message": "Immed"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "S useqdec n Firefox Screenshots, ad tqebleḍ tiwuriwin n usigna Firefox $TERMSANDPRIVACYNOTICETERMSLINK$ akked $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Tiwtilin"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Tasertit n tbaḍnit"
  }
}PK
!<&webextension/_locales/kk/messages.json{
  "addonDescription": {
    "message": "Интернеттен скриншоттарды түсіріп, оларды уақытша немесе тұрақты түрде сақтаңыз."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Скриншотты түсіру"
  },
  "myShotsLink": {
    "message": "Менің скриншоттарым"
  },
  "screenshotInstructions": {
    "message": "Аймақты таңдау үшін бетте шертіңіз. Бас тарту үшін ESC басыңыз."
  },
  "saveScreenshotSelectedArea": {
    "message": "Сақтау"
  },
  "saveScreenshotVisibleArea": {
    "message": "Көрінетінді сақтау"
  },
  "saveScreenshotFullPage": {
    "message": "Толық парақты сақтау"
  },
  "cancelScreenshot": {
    "message": "Бас тарту"
  },
  "downloadScreenshot": {
    "message": "Жүктеп алу"
  },
  "notificationLinkCopiedTitle": {
    "message": "Сілтеме көшірілді"
  },
  "notificationLinkCopiedDetails": {
    "message": "Сіздің скриншотыңызға сілтеме алмасу буферіне көшірілді. Кірістіру үшін $META_KEY$-V басыңыз.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Жұмыс істемейді."
  },
  "requestErrorDetails": {
    "message": "Кешіріңіз! Сіздің скриншотыңызды сақтай алмадық. Кейінірек қайталап көріңіз."
  },
  "connectionErrorTitle": {
    "message": "Скриншоттарыңызға байланыса алмадық."
  },
  "connectionErrorDetails": {
    "message": "Интернетпен байланысыңызды тексеріңіз. Егер сізде интернетпен байланыс бар болса, онда Firefox скриншоттары қызметімен уақытша мәселелер болуы мүмкін."
  },
  "loginErrorDetails": {
    "message": "Скриншотыңызды сақтай алмадық, өйткені Firefox скриншоттары қызметімен мәселе бар болып тұр. Кейінірек қайталап көріңіз."
  },
  "unshootablePageErrorTitle": {
    "message": "Бұл беттің скриншотын түсіре алмаймыз."
  },
  "unshootablePageErrorDetails": {
    "message": "Бұл қалыпты веб беті емес, сондықтан оның скриншотын түсіру мүмкін емес."
  },
  "selfScreenshotErrorTitle": {
    "message": "Firefox скриншоттары бетінің скриншотын түсіру мүмкін емес!"
  },
  "emptySelectionErrorTitle": {
    "message": "Сіздің таңдауыңыз тым кішкентай"
  },
  "privateWindowErrorTitle": {
    "message": "Скриншоттар жекелік шолу режимінде сөнідірілген"
  },
  "privateWindowErrorDetails": {
    "message": "Қолайсыздық үшін кешірім сұраймыз. Бұл мүмкіндікті болашақ шығарылымдарда іске асыруға жұмысты жасаймыз."
  },
  "genericErrorTitle": {
    "message": "Қап! Firefox скриншоттары жасамай қалған сияқты."
  },
  "genericErrorDetails": {
    "message": "Не болғанын білмейміз. Қайталап көресіз бе, немесе басқа парақтың скриншотын түсіріп көресіз бе?"
  },
  "tourBodyOne": {
    "message": "Firefox ішінен скриншоттарды түсіру, сақтау және олармен бөлісу."
  },
  "tourHeaderTwo": {
    "message": "Тек керек нәрсені түсіріңіз"
  },
  "tourBodyTwo": {
    "message": "Беттің тек бір бөлігін түсіру үшін тышқанды шертіп, тартыңыз. Таңдауыңызды түспен ерекшелеу үшін үстінен өткізсеңіз болады."
  },
  "tourHeaderThree": {
    "message": "Терезелер немесе толық беттерді түсіріңіз"
  },
  "tourBodyThree": {
    "message": "Жоғарғы оң жақта орналасқан батырмаларды терезенің көрінетін аймағын, немесе толық бетті түсіру үшін қолданыңыз."
  },
  "tourHeaderFour": {
    "message": "Өзіңізге керек түрде"
  },
  "tourBodyFour": {
    "message": "Қиылған скриншоттарыңыздбен оңай бөлісу үшін оларды интернетте сақтаңыз, немесе өз компьютеріңізге жүктеп алыңыз. Сонымен қатар, сіз жасаған барлық скриншоттарды табу үшін Менің скриншоттарым батырмасына шерте аласыз."
  },
  "tourSkip": {
    "message": "Аттап кету"
  },
  "tourNext": {
    "message": "Келесі слайд"
  },
  "tourPrevious": {
    "message": "Алдыңғы слайд"
  },
  "tourDone": {
    "message": "Дайын"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Firefox скриншоттарын қолдану арқылы, сіз Firefox бұлттық қызметтерінің $TERMSANDPRIVACYNOTICETERMSLINK$ және $TERMSANDPRIVACYNOTICEPRIVACYLINK$ келісесіз.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Қолдану шарттары"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Жекелік ескертуі"
  }
}PK
!<حJVV&webextension/_locales/km/messages.json{
  "saveScreenshotSelectedArea": {
    "message": "រក្សា​ទុក"
  }
}PK
!<O&webextension/_locales/ko/messages.json{
  "addonDescription": {
    "message": "웹 페이지를 찍거나 영상으로 만들어 임시로, 혹은 영구히 보관하세요."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "스크린샷 찍기"
  },
  "myShotsLink": {
    "message": "내 스크린샷"
  },
  "screenshotInstructions": {
    "message": "캡처 할 범위를 드래그하거나 클릭하세요. ESC를 누르면 취소됩니다."
  },
  "saveScreenshotSelectedArea": {
    "message": "저장"
  },
  "saveScreenshotVisibleArea": {
    "message": "보이는 내용 저장"
  },
  "saveScreenshotFullPage": {
    "message": "전체 페이지 저장"
  },
  "cancelScreenshot": {
    "message": "취소"
  },
  "downloadScreenshot": {
    "message": "다운로드"
  },
  "notificationLinkCopiedTitle": {
    "message": "링크 복사됨"
  },
  "notificationLinkCopiedDetails": {
    "message": "방금 찍은 스냅샷의 링크가 클립보드에 저장됐습니다. 붙여넣으려면 $META_KEY$-V를 누르세요.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "문제가 발생했습니다."
  },
  "requestErrorDetails": {
    "message": "죄송합니다. 스크린샷을 저장하지 못했습니다. 잠시 후에 다시 시도해주세요."
  },
  "connectionErrorTitle": {
    "message": "스크린샷에 접속할 수 없습니다."
  },
  "connectionErrorDetails": {
    "message": "인터넷 연결 상태를 확인해주세요. 만약 인터넷이 연결돼있다면, Firefox Screenshots 서비스에 잠깐 문제가 있을 수도 있습니다."
  },
  "loginErrorDetails": {
    "message": "Firefox Screenshots 서비스에 잠시 문제가 있어 저장에 실패했습니다. 잠시 후에 다시 시도해주세요."
  },
  "unshootablePageErrorTitle": {
    "message": "이 페이지를 캡처할 수 없습니다."
  },
  "unshootablePageErrorDetails": {
    "message": "표준 웹 페이지가 아니어서 스크린샷을 찍을 수 없습니다."
  },
  "selfScreenshotErrorTitle": {
    "message": "Firefox Screenshots 페이지는 캡처할 수 없어요!"
  },
  "emptySelectionErrorTitle": {
    "message": "선택영역이 너무 작음"
  },
  "privateWindowErrorTitle": {
    "message": "개인정보 보호 모드에서는 Screenshots이 비활성화 됨"
  },
  "privateWindowErrorDetails": {
    "message": "불편을 끼쳐 드려서 죄송합니다. 다음 출시에 넣을 수 있도록 기능을 개선중입니다."
  },
  "genericErrorTitle": {
    "message": "와우! Firefox Screenshots이 망가졌네요."
  },
  "genericErrorDetails": {
    "message": "무슨 일이 있었는지 모르겠네요. 다시 시도하시거나 다른 페이지 스크린샷을 찍어 보시겠어요?"
  },
  "tourBodyOne": {
    "message": "Firefox를 떠나지 않은 채로 찍고, 저장하고, 공유하세요."
  },
  "tourHeaderTwo": {
    "message": "원하는 것을 캡춰하세요"
  },
  "tourBodyTwo": {
    "message": "캡춰할 페이지의 부분을 클릭해서 드래그 해 보세요. 마우스를 올려서 선택한 부분을 확인할 수 있습니다."
  },
  "tourHeaderThree": {
    "message": "창이나 페이지 전체를 캡춰할 수 있습니다"
  },
  "tourBodyThree": {
    "message": "우측 위에 있는 버튼을 눌러 창을 캡처하거나 페이지 전체를 캡처할 수 있습니다."
  },
  "tourHeaderFour": {
    "message": "내가 원하는 대로"
  },
  "tourBodyFour": {
    "message": "스크린샷을 공유하거나, 컴퓨터로 다운로드할 수도 있습니다. 내 스크린샷 버튼을 눌러서 지금까지 찍었던 모든 스크린샷을 찾을 수도 있습니다."
  },
  "tourSkip": {
    "message": "건너뛰기"
  },
  "tourNext": {
    "message": "다음 슬라이드"
  },
  "tourPrevious": {
    "message": "이전 슬라이드"
  },
  "tourDone": {
    "message": "완료"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Firefox Screenshots을 사용함으로써, Firefox Cloud Services $TERMSANDPRIVACYNOTICETERMSLINK$과 $TERMSANDPRIVACYNOTICEPRIVACYLINK$에 동의하게 됩니다.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "이용약관"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "개인 정보 취급 방침"
  }
}PK
!<"#'webextension/_locales/lij/messages.json{
  "addonDescription": {
    "message": "Fanni de föto do schermo da-o Web e sarvale in mòddo tenporaneo ò cin mòddo che restan."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Fanni 'na föto do schermo"
  },
  "myShotsLink": {
    "message": "E mæ föto do schermo"
  },
  "screenshotInstructions": {
    "message": "Rebela ò sciacca in sciâ pagina pe seleçionâ 'na region. Sciacca ESC pe anulâ."
  },
  "saveScreenshotSelectedArea": {
    "message": "Sarva"
  },
  "saveScreenshotVisibleArea": {
    "message": "Sarva o vixibile"
  },
  "saveScreenshotFullPage": {
    "message": "Sarva tutta a pagina"
  },
  "cancelScreenshot": {
    "message": "Anulla"
  },
  "downloadScreenshot": {
    "message": "Descarega"
  },
  "notificationLinkCopiedTitle": {
    "message": "Colegamento copiou inti aponti"
  },
  "notificationLinkCopiedDetails": {
    "message": "O colegamento a l'inmagine o l'é stæto copiou inti aponti. Sciacca$META_KEY$-V pe incolalo.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Feua serviçio."
  },
  "requestErrorDetails": {
    "message": "Ne spiaxe! No poemmo sarvâ l'inmagine. Pe piaxei preuva torna dòppo."
  },
  "connectionErrorTitle": {
    "message": "No poemmo conetise a-e teu föto do schermo."
  },
  "connectionErrorDetails": {
    "message": "Pe piaxei contròlla a teu conescion a l'Internet. Se ti riesci a conetite a l'Internet, ghe poeiva ese 'n problema tenporaneo co-o serviçio de Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "No poemmo sarvâ a teu inmagine perché gh'é 'n problema co-o serviçio de Firefox Screenshot. Pe piaxei preuva torna dòppo."
  },
  "unshootablePageErrorTitle": {
    "message": "No poemmo fâ 'na föto do schermo de sta pagina."
  },
  "unshootablePageErrorDetails": {
    "message": "Sta chi a no l'é 'na pagina Web standard, coscì no peu faghe 'na föto do schermo."
  },
  "selfScreenshotErrorTitle": {
    "message": "No ti peu fâ 'na föto do schermo a 'na pagina de Firefox Screenshots!"
  },
  "genericErrorTitle": {
    "message": "Ahime mi! Firefox Screeshot o s'é ciantou."
  },
  "genericErrorDetails": {
    "message": "Niatri no emmo ben acapio cöse l'é sucesso. Ti peu miga preuvâ co-ina pagina dispægia?"
  },
  "tourBodyOne": {
    "message": "Fanni, sarva e condividdi föto do schermo sensa sciortî da Firefox."
  },
  "tourHeaderTwo": {
    "message": "Catua solo quello che t'eu"
  },
  "tourBodyTwo": {
    "message": "Sciacca e rebela pe catuâ solo 'na porçion de 'na pagina. Ti peu anche anâ co-o ratto sorvia l'area seleçionâ pe evidençiala."
  },
  "tourHeaderThree": {
    "message": "Catua 'n barcon ò 'na pagina intrega"
  },
  "tourBodyThree": {
    "message": "Seleçionn-a i pomelli de d'ato a drita pe catuâ l'area vixibile into barcon ò a pagina intrega."
  },
  "tourHeaderFour": {
    "message": "Comme te piaxe"
  },
  "tourBodyFour": {
    "message": "Sarva 'n ritaggio de 'na pagina Web pe condividila in mòddo ciù façile ò scaregala into teu computer. Ti peu anche sciacâ into pomello  “E mæ föto do schermo pe atrovâ” quello che t'æ za pigiou."
  },
  "tourSkip": {
    "message": "Ignòra"
  },
  "tourNext": {
    "message": "Pròscima schermâ"
  },
  "tourPrevious": {
    "message": "Schermâ de primma"
  },
  "tourDone": {
    "message": "Fæto"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Se ti deuvi Firefox Screenshots, ti e d'acordio con $TERMSANDPRIVACYNOTICETERMSLINK$ e $TERMSANDPRIVACYNOTICEPRIVACYLINK$ de Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Termini"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Informativa in sciâ privacy"
  }
}PK
!< H??&webextension/_locales/lo/messages.json{
  "addonDescription": {
    "message": "ຖ່າຍຄຣິບ ແລະ ພາບຫນ້າຈໍຈາກຫນ້າເວັບ ແລ້ວບັນທຶກໄວ້ຊົ່ວຄາວ ຫລື ຖາວອນ."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "ຖ່າຍພາບຫນ້າຈໍ"
  },
  "myShotsLink": {
    "message": "ພາບຂອງຂ້ອຍ"
  },
  "screenshotInstructions": {
    "message": "ລາກ ຫລື ຄິກໃສ່ຫນ້າເວັບເພື່ອເລືອກເອົາບ່ອນທີ່ຕ້ອງການ. ກົດ ESC ເພື່ອຍົກເລີກ."
  },
  "saveScreenshotSelectedArea": {
    "message": "ບັນທຶກ"
  },
  "saveScreenshotVisibleArea": {
    "message": "ບັນທຶກສ່ວນທີ່ເບິງເຫັນໄດ້"
  },
  "saveScreenshotFullPage": {
    "message": "ບັນທຶກຫມົດຫນ້າ"
  },
  "cancelScreenshot": {
    "message": "ຍົກເລີກ"
  },
  "downloadScreenshot": {
    "message": "ດາວໂຫລດ"
  },
  "notificationLinkCopiedTitle": {
    "message": "ໄດ້ສຳເນົາລີ້ງໄວ້ແລ້ວ"
  },
  "notificationLinkCopiedDetails": {
    "message": "ລີ້ງໄປຫາຮູບພາບຂອງທ່ານໄດ້ຖືກບັນທຶກໄວ້ໃນຄຣິບບອດ. ກົດ $META_KEY$-V ເພື່ອວາງ.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "ໃຊ້ວຽກບໍ່ໄດ້."
  },
  "requestErrorDetails": {
    "message": "ຂໍອະໄພ! ພວກເຮົາບໍ່ສາມາດບັນທຶກພາບຂອງທ່ານໄດ້. ກະລູນາລອງໃຫມ່ອີກຄັ້ງ."
  },
  "connectionErrorTitle": {
    "message": "ພວກເຮົາບໍ່ສາມາດເຊື່ອມຕໍ່ໄປຫາພາບຫນ້າຈໍຂອງທ່ານໄດ້."
  },
  "connectionErrorDetails": {
    "message": "ກະລູນາກວດເບິງການເຊື່ອມຕໍ່ກັບອິນເຕີເນັດຂອງທ່ານ. ຖ້າຫາກວ່າທ່ານສາມາດເຊື່ອມຕໍ່ກັບອິນເຕີເນັດໄດ້ແມ່ນ ບໍລິການພາບຖ່າຍຫນ້າຈໍຂອງ Firefox ອາດຈະເກີດມີບັນຫາຊົ່ວຄາວ."
  },
  "loginErrorDetails": {
    "message": "ພວກເຮົາບໍ່ສາມາດບັນທຶກພາບຖ່າຍຂອງທ່ານໄດ້ ເພາະວ່າບໍລິການພາບຖ່າຍຫນ້າຈໍຂອງ Firefox ໄດ້ເກີດມີບັນຫາ. ກະລູນາລອງໃຫມ່ອີກຄັ້ງ."
  },
  "unshootablePageErrorTitle": {
    "message": "ພວກເຮົາບໍ່ສາມາດຖ່າຍຮູບຫນ້າຈໍຂອງຫນ້ານີ້ໄດ້."
  },
  "unshootablePageErrorDetails": {
    "message": "ນີ້ບໍ່ແມ່ນຫນ້າເວັບມາດຕະຖານ, ສະນັ້ນທ່ານຈຶ່ງບໍ່ສາມາດຖ່າຍພາບຫນ້າຈໍໄດ້."
  },
  "selfScreenshotErrorTitle": {
    "message": "ທ່ານບໍ່ສາມາດຖ່າຍພາບຫນ້າຈໍຂອງ Firefox ໄດ້!"
  },
  "emptySelectionErrorTitle": {
    "message": "ການເລືອກຂອງທ່ານນ້ອຍເກີນໄປ"
  },
  "genericErrorTitle": {
    "message": "ໂອ! Firefox Screenshots ລວນ."
  },
  "genericErrorDetails": {
    "message": "ພວກເຮົາບໍ່ແນ່ໃຈວ່າມັນຫາກະເກີດຫຍັງຂື້ນ. ກະລຸນາລອງໃຫມ່ອີກຄັ້ງ ຫລື ຖ່າຍພາບຫນ້າຈໍອື່ນລອງເບິງ"
  },
  "tourBodyOne": {
    "message": "ຖ່າຍ, ບັນທຶກ ແລະ ແບ່ງປັນພາບຫນ້າຈໍໂດຍບໍ່ຕ້ອງອອກຈາກ Firefox."
  },
  "tourHeaderTwo": {
    "message": "ຖ່າຍພາບຕາມທີ່ທ່ານຕ້ອງການ"
  },
  "tourBodyTwo": {
    "message": "ຄິກ ຫລື ລາກເພື່ອຖ່າຍພາບສະເພາະບາງສ່ວນຂອງຫນ້າເວັບ. ພ້ອມດຽວກັນນັ້ນທ່ານຍັງສາມາດເລື່ອນມາເພື່ອເນັ້ນພາບທີ່ທ່ານເລືອກ."
  },
  "tourHeaderThree": {
    "message": "ຖ່າຍພາບວິນໂດ ຫລື ຫມົດທັ້ງຫນ້າ"
  },
  "tourBodyThree": {
    "message": "ເລືອກປຸ່ມກົດທີ່ຢູ່ເທິງເບື້ອງຂວາມືເພື່ອຈັບພາບໃນບໍລິເວນທີ່ເບິງເຫັນໄດ້ໃນວິນໂດ ຫລື ເພື່ອຈັບພາບທັງຫມົດໃນຫນ້າເວັບ."
  },
  "tourHeaderFour": {
    "message": "ຕາມທີ່ທ່ານມັກ"
  },
  "tourBodyFour": {
    "message": "ບັນທຶກຮູບພາບທີ່ທ່ານໄດ້ຄັອບເອົາໄວ້ລົງໄປໄວ້ໃນເວັບເພື່ອເຮັດໃຫ້ແບ່ງປັນໄດ້ງ່າຍ ຫລື ດາວໂຫລດໄປໄວ້ໃນຄອມພິວເຕີຂອງທ່ານ. ທ່ານຍັງສາມາດຄິກໃສ່ໃນປຸ່ມກົດ \"ຮູບພາບຂອງຂ້ອຍ\" ເພື່ອຊອກຫາຮູບພາບທັງຫມົດທີ່ທ່ານໄດ້ຖ່າຍເອົາໄວ້."
  },
  "tourSkip": {
    "message": "ຂ້າມໄປ"
  },
  "tourNext": {
    "message": "ສະໄລດ໌ຕໍ່ໄປ"
  },
  "tourPrevious": {
    "message": "ສະໄລດ໌ກ່ອນຫນ້ານີ້"
  },
  "tourDone": {
    "message": "ສຳເລັດ"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "ການນຳໃຊ້ Firefox Screenshots ແມ່ນທ່ານໄດ້ຍອມຮັບເງືອນໄຂການໃຫ້ບໍລິການຂອງ Firefox Cloud Services $TERMSANDPRIVACYNOTICETERMSLINK$ ແລະ $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "ຂໍ້ກຳນົດ"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "ຄຳເຕືອນກ່ຽວກັບຄວາມເປັນສ່ວນຕົວ"
  }
}PK
!<{	&webextension/_locales/lt/messages.json{
  "addonDescription": {
    "message": "Darykite iškarpas ir ekrano nuotraukos su interneto turiniu bei saugokite jas laikinai arba visąlaik."
  },
  "addonAuthorsList": {
    "message": "„Mozilla“ <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Padaryti ekrano nuotrauką"
  },
  "myShotsLink": {
    "message": "Mano kadrai"
  },
  "screenshotInstructions": {
    "message": "Tempkite arba spustelėkite tinklalapyje norėdami pasirinkti regioną. Spustelėkite „ESC“ norėdami atsisakyti."
  },
  "saveScreenshotSelectedArea": {
    "message": "Įrašyti"
  },
  "saveScreenshotVisibleArea": {
    "message": "Įrašyti matomą"
  },
  "saveScreenshotFullPage": {
    "message": "Įrašyti visą tinklalapį"
  },
  "cancelScreenshot": {
    "message": "Atsisakyti"
  },
  "downloadScreenshot": {
    "message": "Atsisiųsti"
  },
  "notificationLinkCopiedTitle": {
    "message": "Saitas nukopijuotas"
  },
  "notificationLinkCopiedDetails": {
    "message": "Jūsų nuotraukos saitas buvo nukopijuotas į iškarpinę. Spustelėkite „$META_KEY$-V“ norėdami įdėti.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Neveikia."
  },
  "requestErrorDetails": {
    "message": "Atsiprašome! Mums nepavyko įrašyti jūsų nuotraukos. Prašome pabandyti vėliau."
  },
  "connectionErrorTitle": {
    "message": "Mums nepavyko prisijungti prie jūsų ekrano nuotraukų."
  },
  "connectionErrorDetails": {
    "message": "Patikrinkite savo interneto ryšį. Jeigu galite prisijungti prie interneto, gali būti, kad yra laikina problema su „Firefox Screenshots“ paslauga."
  },
  "loginErrorDetails": {
    "message": "Mums nepavyko įrašyti jūsų nuotraukos, nes yra problema su „Firefox Screenshots“ paslauga. Prašome pabandyti vėliau."
  },
  "unshootablePageErrorTitle": {
    "message": "Mums nepavyko nufotografuoti šio tinklalapio."
  },
  "unshootablePageErrorDetails": {
    "message": "Tai nėra įprastas tinklalapis, tad negalite padaryti jo nuotraukos."
  },
  "selfScreenshotErrorTitle": {
    "message": "Negalite padaryti „Firefox Screenshots“ tinklalapio nuotraukos!"
  },
  "emptySelectionErrorTitle": {
    "message": "Jūsų pasirinkimas yra per mažas"
  },
  "privateWindowErrorTitle": {
    "message": "Ekrano nuotraukos privačiajame naršyme neveikia"
  },
  "privateWindowErrorDetails": {
    "message": "Atsiprašome už nepatogumą. Mes dirbame prie šio funkcionalumo vėlesnėms versijoms."
  },
  "genericErrorTitle": {
    "message": "Vau! „Firefox Screenshots“ sugedo."
  },
  "genericErrorDetails": {
    "message": "Mes nesame tikri, kas ką tik nutiko. Norite pabandyti dar kartą arba nufotografuoti kitą tinklalapį?"
  },
  "tourBodyOne": {
    "message": "Darykite, įrašykite ir dalinkitės ekrano nuotraukomis nepalikdami „Firefox“."
  },
  "tourHeaderTwo": {
    "message": "Užfiksuokite būtent tai, ką norite"
  },
  "tourBodyTwo": {
    "message": "Spustelėkite ir tempkite, kad užfiksuotumėte tik dalį tinklalapio. Taip pat galite užvesti pelę, norėdami paryškinti savo pasirinkimą."
  },
  "tourHeaderThree": {
    "message": "Fiksuokite langus arba ištisus tinklalapius"
  },
  "tourBodyThree": {
    "message": "Pasirinkite mygtukus aukščiau dešinėje, norėdami užfiksuoti matomą lango dalį arba visą tinklalapį."
  },
  "tourHeaderFour": {
    "message": "Kaip jums patogiau"
  },
  "tourBodyFour": {
    "message": "Įrašykite padarytas nuotraukas saityne patogesniam dalinimuisi, arba atsisiųskite jas į savo kompiuterį. Spustelėję mygtuką „Mano kadrai“, matysite visas savo padarytas nuotraukas."
  },
  "tourSkip": {
    "message": "SKIP"
  },
  "tourNext": {
    "message": "Kita skaidrė"
  },
  "tourPrevious": {
    "message": "Buvusi skaidrė"
  },
  "tourDone": {
    "message": "Baigta"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Naudodami „Firefox Screenshots“ sutinkate su „Firefox“ tinklo paslaugų $TERMSANDPRIVACYNOTICETERMSLINK$ bei $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "sąlygomis"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "privatumo nuostatais"
  }
}PK
!<*&webextension/_locales/mk/messages.json{
  "addonDescription": {
    "message": "Земете исечоци и слики од Интернет и зачувајте ги привремено или трајно."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Фатете слика"
  },
  "myShotsLink": {
    "message": "Мои слики"
  },
  "screenshotInstructions": {
    "message": "Влечете и кликнете на страницата за да означите регион. Притиснете ESC за да се откажете."
  },
  "saveScreenshotSelectedArea": {
    "message": "Сними"
  },
  "saveScreenshotVisibleArea": {
    "message": "Сними видлив дел"
  },
  "saveScreenshotFullPage": {
    "message": "Сними цела страница"
  },
  "cancelScreenshot": {
    "message": "Откажи"
  },
  "downloadScreenshot": {
    "message": "Преземи"
  },
  "notificationLinkCopiedTitle": {
    "message": "Врската е ископирана"
  },
  "notificationLinkCopiedDetails": {
    "message": "Врската до Вашата слика е ископирана во меморија. Притиснете $META_KEY$-V за да ја вметнете.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Не работи."
  },
  "requestErrorDetails": {
    "message": "Извинете! Не можевме да ја снимиме Вашата слика. Ве молиме обидете се повторно подоцна."
  },
  "connectionErrorTitle": {
    "message": "Не можеме да пристапиме до Вашите слики од екран."
  },
  "connectionErrorDetails": {
    "message": "Ве молиме проверете ја Вашата Интернет-врска. Ако можете да се поврзете на Интернет, тогаш можно е да има привремен проблем со сервисот Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Не можевме да ја зачуваме Вашата слика бидејќи има проблем со сервисот Firefox Screenshots. Ве молиме обидете се повторно подоцна."
  },
  "unshootablePageErrorTitle": {
    "message": "Не можеме да фатиме слика од оваа страница."
  },
  "unshootablePageErrorDetails": {
    "message": "Ова не е обична веб-страница, па не можете да фатите слика од неа."
  },
  "selfScreenshotErrorTitle": {
    "message": "Не можете да фатите слика од страницата на Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Делот што го избравте е премногу мал"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots е деактивиран во текот на Приватното прелистување"
  },
  "privateWindowErrorDetails": {
    "message": "Извинете за незгодата. Работиме на оваа функционалност за во идните верзии."
  },
  "genericErrorTitle": {
    "message": "Ајдее! Firefox Screenshots излезе од контрола."
  },
  "genericErrorDetails": {
    "message": "Не сме баш сигурни што се случи. Сакате да се обидете повторно или да направите слика од друга страница?"
  },
  "tourBodyOne": {
    "message": "Фаќајте, снимајте и споделувајте слики од екран без да го напуштите Firefox."
  },
  "tourHeaderTwo": {
    "message": "Фатете слика од тоа што сакате"
  },
  "tourBodyTwo": {
    "message": "Кликнете и влечете за да фатите само дел од страницата. Исто така можете да означите дел и со покажувачот."
  },
  "tourHeaderThree": {
    "message": "Фатете слика од прозорци или цели страници"
  },
  "tourBodyThree": {
    "message": "Кликнете на копчињата во горниот десен дел за да го снимите видливиот дел на прозорецот или пак, целата страница."
  },
  "tourHeaderFour": {
    "message": "Како што Вие сакате"
  },
  "tourBodyFour": {
    "message": "Снимете ги Вашите исечоци на Интернет за полесно споделување или преземете ги на Вашиот компјутер. Исто така можете да кликнете на копчето Мои слики за да ги најдете сите слики што ги имате направено."
  },
  "tourSkip": {
    "message": "ПРЕСКОКНИ"
  },
  "tourNext": {
    "message": "Следен слајд"
  },
  "tourPrevious": {
    "message": "Претходен слајд"
  },
  "tourDone": {
    "message": "Готово"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Со користење на Firefox Screenshots, се согласувате со нашите $TERMSANDPRIVACYNOTICETERMSLINK$ и $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Услови"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Известување за приватност"
  }
}PK
!<mnn&webextension/_locales/mr/messages.json{
  "addonDescription": {
    "message": "वेबवरून क्लिप आणि स्क्रीनशॉट घ्या आणि त्यांना तात्पुरते किंवा कायमचे जतन करा."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "स्क्रीनशॉट घ्या"
  },
  "myShotsLink": {
    "message": "माझे शॉट"
  },
  "screenshotInstructions": {
    "message": "प्रदेश निवडण्यासाठी पृष्ठावर ड्रॅग करा किंवा क्लिक करा. रद्द करण्यासाठी ESC दाबा."
  },
  "saveScreenshotSelectedArea": {
    "message": "साठवा"
  },
  "saveScreenshotVisibleArea": {
    "message": "दृश्यमय साठवा"
  },
  "saveScreenshotFullPage": {
    "message": "संपूर्ण पृष्ठ साठवा"
  },
  "cancelScreenshot": {
    "message": "रद्द करा"
  },
  "downloadScreenshot": {
    "message": "डाउनलोड करा"
  },
  "notificationLinkCopiedTitle": {
    "message": "दुवा कॉपी केला"
  },
  "notificationLinkCopiedDetails": {
    "message": "आपल्या शॉटचा दुवा क्लिपबोर्डवर कॉपी झाला आहे. चिटकवण्यासाठी $META_KEY$ -V दाबा.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "नादुरुस्त."
  },
  "requestErrorDetails": {
    "message": "क्षमस्व! आम्ही आपला शॉट साठवु शकलो नाही. कृपया नंतर प्रयत्न करा."
  },
  "connectionErrorTitle": {
    "message": "आम्ही आपल्या स्क्रीनशॉटशी जोडणी करु शकत नाही."
  },
  "connectionErrorDetails": {
    "message": "कृपया आपले इंटरनेट जोडणी तपासा. आपण इंटरनेटशी जुळण्यास अक्षम असल्यास, Firefox स्क्रीनशॉट सेवेमध्ये एक तात्पुरती समस्या असु शकते."
  },
  "loginErrorDetails": {
    "message": "Firefox स्क्रीनशॉट सेवेमध्ये समस्या असल्या कारणाने आम्ही आपला शॉट साठवु शकलो नाही. कृपया नंतर प्रयत्न करा."
  },
  "unshootablePageErrorTitle": {
    "message": "आम्ही हे पृष्ठ स्क्रीनशॉट करू शकत नाही."
  },
  "unshootablePageErrorDetails": {
    "message": "हे मानक वेब पृष्ठ नाही, म्हणून आपण त्याचा स्क्रीनशॉट घेऊ शकत नाही."
  },
  "selfScreenshotErrorTitle": {
    "message": "आपण Firefox स्क्रीनशॉट पृष्ठाचा शॉट घेऊ शकत नाही!"
  },
  "emptySelectionErrorTitle": {
    "message": "आपली निवड खूप लहान आहे"
  },
  "privateWindowErrorTitle": {
    "message": "खाजगी ब्राउझिंग पद्धतीमध्ये स्क्रीनशॉट्स निष्क्रिय केले आहेत"
  },
  "privateWindowErrorDetails": {
    "message": "गैरसोयीबद्दल क्षमस्व. आम्ही भविष्यातील प्रकाशनासाठी या वैशिष्ट्यांवर कार्यरत आहोत."
  },
  "genericErrorTitle": {
    "message": "हुअ! Firefox स्क्रीनशॉट अव्यवस्थित झाले आहे."
  },
  "genericErrorDetails": {
    "message": "काय घडले याची आम्हाला खात्री नाही. पुन्हा प्रयत्न करा किंवा भिन्न पृष्ठाचा शॉट घ्या?"
  },
  "tourBodyOne": {
    "message": "Firefox न सोडता स्क्रीनशॉट घ्या, जतन करा आणि सामायिक करा."
  },
  "tourHeaderTwo": {
    "message": "आपल्याला पाहिजे असलेल्या गोष्टी फक्त कॅप्चर करा"
  },
  "tourBodyTwo": {
    "message": "पृष्ठाचा फक्त एक भाग कॅप्चर करण्यासाठी क्लिक आणि ड्रॅग करा. आपण आपल्या निवडीवर ठळकपणे होव्हर देखील करू शकता."
  },
  "tourHeaderThree": {
    "message": "Windows किंवा संपूर्ण पृष्ठे कॅप्चर करा"
  },
  "tourBodyThree": {
    "message": "पटलामध्ये दृश्यमान क्षेत्र कॅप्चर करण्यासाठी किंवा संपूर्ण पृष्ठ कॅप्चर करण्यासाठी वरील उजवीकडील बटणे निवडा."
  },
  "tourHeaderFour": {
    "message": "जसे आपल्याला आवडते"
  },
  "tourBodyFour": {
    "message": "आपले क्रॉप केलेले शॉट्स वेबवर सुलभ सामायिक करण्यासाठी जतन करा, किंवा त्यांना आपल्या संगणकावर डाउनलोड करा. आपण घेतलेले सर्व शॉट्स शोधण्यासाठी आपण माझे शॉट्स बटणावर क्लिक करू शकता."
  },
  "tourSkip": {
    "message": "दुर्लक्षित करा"
  },
  "tourNext": {
    "message": "पुढील स्लाइड"
  },
  "tourPrevious": {
    "message": "मागची स्लाइड"
  },
  "tourDone": {
    "message": "झाले"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Firefox Screenshots वापरून, आपण आमच्या $TERMSANDPRIVACYNOTICETERMSLINK$आणि $TERMSANDPRIVACYNOTICEPRIVACYLINK$ शी सहमत आहात.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "अटी"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "गोपनीयता सूचना"
  }
}PK
!<"'&webextension/_locales/ms/messages.json{
  "addonDescription": {
    "message": "Ambil klip dan skrinsyot dari Web dan simpan untuk sementara waktu atau kekal."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Ambil skrinsyot"
  },
  "myShotsLink": {
    "message": "Syot Saya"
  },
  "screenshotInstructions": {
    "message": "Seret atau klik pada halaman untuk memilih kawasan. Tekan ESC untuk batalkan."
  },
  "saveScreenshotSelectedArea": {
    "message": "Simpan"
  },
  "saveScreenshotVisibleArea": {
    "message": "Simpan yang terpapar"
  },
  "saveScreenshotFullPage": {
    "message": "Simpan halaman penuh"
  },
  "cancelScreenshot": {
    "message": "Batal"
  },
  "downloadScreenshot": {
    "message": "Muat turun"
  },
  "notificationLinkCopiedTitle": {
    "message": "Pautan Disalin"
  },
  "notificationLinkCopiedDetails": {
    "message": "Pautan ke syot anda telah disalin ke klipbod. Tekan $META_KEY$-V untuk tampal.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Tidak berfungsi."
  },
  "requestErrorDetails": {
    "message": "Maaf! Kita tidak dapat menyimpan syot anda. Sila cuba lagi nanti."
  },
  "connectionErrorTitle": {
    "message": "Kami tidak dapat menyambungkan ke skrinsyot anda."
  },
  "connectionErrorDetails": {
    "message": "Sila semak sambungan Internet anda. Jika anda boleh dapat sambungan ke Internet, mungkin ada masalah sementara dengan perkhidmatan Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Kami tidak dapat menyimpan skrinsyot anda kerana ada masalah dengan perkhidmatan Firefox Screenshots. Sila cuba lagi nanti."
  },
  "unshootablePageErrorTitle": {
    "message": "Kami tidak boleh skrinsyot halaman ini."
  },
  "unshootablePageErrorDetails": {
    "message": "Ini bukan halaman Web piawai, jadi anda tidak boleh membuat skrinsyot."
  },
  "selfScreenshotErrorTitle": {
    "message": "Anda tidak boleh syot halaman Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Pilihan anda terlalu kecil"
  },
  "privateWindowErrorTitle": {
    "message": "Skrinsyot dinyahdayakan dalam Mod Pelayaran Peribadi"
  },
  "privateWindowErrorDetails": {
    "message": "Maaf atas sebarang kesulitan. Kami sedang berusaha untuk menyediakan ciri ini dalam keluaran akan datang."
  },
  "genericErrorTitle": {
    "message": "Oh tidak! Firefox Screenshots tidak berfungsi dengan betul."
  },
  "genericErrorDetails": {
    "message": "Kami tidak pasti apa yang baru berlaku. Anda mahu cuba lagi atau mengambil gambar halaman lain?"
  },
  "tourBodyOne": {
    "message": "Ambil, simpan, dan kongsi skrinsyot tanpa meninggalkan pelayar Firefox."
  },
  "tourHeaderTwo": {
    "message": "Ambil gambar hanya yang anda mahu"
  },
  "tourBodyTwo": {
    "message": "Klik dan seret untuk mengambil gambar sebahagian daripada halaman. Anda boleh juga serlahkan pilihan anda."
  },
  "tourHeaderThree": {
    "message": "Tangkap Tetingkap atau Keseluruhan Halaman"
  },
  "tourBodyThree": {
    "message": "Pilih butang di bahagian atas kanan untuk merakam kawasan paparan dalam tetingkap atau untuk merakamkan keseluruhan halaman."
  },
  "tourHeaderFour": {
    "message": "Seperti Yang Anda Suka"
  },
  "tourBodyFour": {
    "message": "Simpan rakaman yang dipotong ke Web, cara yang lebih mudah untuk berkongsi, atau memuat turun ke komputer anda. Anda juga boleh klik pada butang Syot Saya untuk mencari semua rakaman yang telah dibuat."
  },
  "tourSkip": {
    "message": "SKIP"
  },
  "tourNext": {
    "message": "Slaid Seterusnya"
  },
  "tourPrevious": {
    "message": "Slaid Sebelumnya"
  },
  "tourDone": {
    "message": "Selesai"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Dengan menggunakan Firefox Screenshots, anda bersetuju dengan $TERMSANDPRIVACYNOTICETERMSLINK$ dan $TERMSANDPRIVACYNOTICEPRIVACYLINK$ Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Terma"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Notis Privasi"
  }
}PK
!</&webextension/_locales/my/messages.json{
  "addonDescription": {
    "message": "ဝဘ်ထံမှ ဓါတ်ပုံများနှင့် မျက်နှာပြင်ပုံဖမ်းချက်များကို ရိုက်ယူပြီး ယာယီ သို့မဟုတ် အမြဲတမ်းသိုလှောင်ရာတွင် သိမ်းဆည်းပါ။"
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "မျက်နှာပြင်ပုံရိပ် ဖမ်းယူပါ"
  },
  "myShotsLink": {
    "message": "ရိုက်ကူးထားသော ပုံများ"
  },
  "saveScreenshotSelectedArea": {
    "message": "သိမ်းရန်"
  },
  "saveScreenshotVisibleArea": {
    "message": "မြင်ရသည်များကို သိမ်းပါ"
  },
  "saveScreenshotFullPage": {
    "message": "စာမျက်နှာတစ်ခုလုံးကို သိမ်းပါ"
  },
  "cancelScreenshot": {
    "message": "မဆောင်ရွက်တော့ပါ"
  },
  "downloadScreenshot": {
    "message": "ဆွဲယူရန်"
  },
  "notificationLinkCopiedTitle": {
    "message": "လင့်ခ်ကို ကူယူပြီး"
  },
  "requestErrorTitle": {
    "message": "ပျက်နေသည်"
  },
  "requestErrorDetails": {
    "message": "စိတ်မကောင်းပါ၊ သင်ရိုက်ကူးထားသော ပုံကို မသိမ်းနိုင်ပါ။ နောင်တွင် ပြန်စမ်းကြည့်ပါ။"
  },
  "connectionErrorTitle": {
    "message": "သင်ရိုက်ကူးထားသော မျက်နှာပြင်ပုံရိပ်များထံ မချိတ်ဆက်နိုင်ပါ။"
  },
  "unshootablePageErrorTitle": {
    "message": "ဒီစာမျက်နှာ၏ မျက်နှာပြင်ပုံရိပ်ကို မရိုက်ကူးနိုင်ပါ။"
  },
  "tourBodyOne": {
    "message": "Firefox ကနေ ထွက်ခွာရန် မလိုဘဲ မျက်နှာပြင်ပုံရိပ်များကို ရိုက်ကူး၊ သိမ်းဆည်း၊ မျှဝေပါ။"
  },
  "tourHeaderTwo": {
    "message": "ကိုယ်နှစ်သက်ရာ စာမျက်နှာများကို ဖမ်းယူပါ"
  },
  "tourHeaderThree": {
    "message": "ဝင်ဒိုးများ သို့မဟုတ် စာမျက်နှာတစ်ခုလုံးကို ဖမ်းယူပါ"
  },
  "tourHeaderFour": {
    "message": "နှစ်သက်သလို"
  },
  "tourSkip": {
    "message": "SKIP"
  },
  "tourNext": {
    "message": "နောက်ဆလိုက်"
  },
  "tourPrevious": {
    "message": "အရင်ကဆလိုက်"
  },
  "tourDone": {
    "message": "ပြီးပြီ"
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "စကားရပ်များ"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "ကိုယ်ရေးကာကွယ်မှု သတိပေးချက်"
  }
}PK
!<Jg()webextension/_locales/nb_NO/messages.json{
  "addonDescription": {
    "message": "Ta klipp og skjermbilder fra nettet og lagre de midlertidig eller permanent."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Ta et skjermbilde"
  },
  "myShotsLink": {
    "message": "Mine skjermbilder"
  },
  "screenshotInstructions": {
    "message": "Dra eller klikk på siden for å velge et område. Trykk på ESC for å avbryte."
  },
  "saveScreenshotSelectedArea": {
    "message": "Lagre"
  },
  "saveScreenshotVisibleArea": {
    "message": "Lagre synlig område"
  },
  "saveScreenshotFullPage": {
    "message": "Lagre hele siden"
  },
  "cancelScreenshot": {
    "message": "Avbryt"
  },
  "downloadScreenshot": {
    "message": "Last ned"
  },
  "notificationLinkCopiedTitle": {
    "message": "Lenke kopiert"
  },
  "notificationLinkCopiedDetails": {
    "message": "Lenken til skjermbildet ditt er kopiert til utklippstavlen. Trykk på $META_KEY$-V for å lime inn.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "I ustand."
  },
  "requestErrorDetails": {
    "message": "Beklager! Vi klarte ikke å lagre skjermbildet ditt. Prøv igjen senere."
  },
  "connectionErrorTitle": {
    "message": "Vi kan ikke koble til dine skjermbilder."
  },
  "connectionErrorDetails": {
    "message": "Kontroller din internett-tilkopling. Om du kan koble til internett, kan det være et midlertidig problem med tjenesten Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Vi klarte ikke å lagre skjermbildet ditt, fordi det er et problem med tjenesten Firefox Screenshots. Prøv igjen senere."
  },
  "unshootablePageErrorTitle": {
    "message": "Vi kan ikke ta skjermbilde av siden."
  },
  "unshootablePageErrorDetails": {
    "message": "Dette er ikke en vanlig nettside, og du kan ikke ta skjermbilde av den."
  },
  "selfScreenshotErrorTitle": {
    "message": "Du kan ikke ta skjermbilde av siden Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Det valgte området er for liten"
  },
  "privateWindowErrorTitle": {
    "message": "Skjermbildetaking er deaktivert i privat nettlesings-modus"
  },
  "privateWindowErrorDetails": {
    "message": "Beklager ulempen. Vi jobber med denne funksjonen for fremtidige utgivelser."
  },
  "genericErrorTitle": {
    "message": "Oi! Det ser ut til at Firefox Screenshots ikke fungerer korrekt."
  },
  "genericErrorDetails": {
    "message": "Vi er ikke sikre på hva som hendte. Kan du prøve igjen eller ta et bilde av en annen side?"
  },
  "tourBodyOne": {
    "message": "Ta, lagre og del skjermbilder uten å forlate Firefox."
  },
  "tourHeaderTwo": {
    "message": "Ta bilde av akkurat hva du vil"
  },
  "tourBodyTwo": {
    "message": "Klikk for å dra og ta skjermbilde av bare en del av siden. Du kan også føre musen over for å framheve merket område."
  },
  "tourHeaderThree": {
    "message": "Ta skjermbilde av vinduer eller hele sider."
  },
  "tourBodyThree": {
    "message": "Bruk knappene i det øvre høyre hjørnet for å ta skjermbilde av det synlige området i vinduet eller for å ta skjermbilde av en hel side."
  },
  "tourHeaderFour": {
    "message": "Som du vil ha det"
  },
  "tourBodyFour": {
    "message": "Lagre de beskjærte skjermbildene dine på nettet for enklere deling, eller last de ned til din datamaskin. Du kan også klikke på knappen Mine skjermbilde for å finne alle skjermbildene du har tatt."
  },
  "tourSkip": {
    "message": "Hopp over"
  },
  "tourNext": {
    "message": "Neste slide"
  },
  "tourPrevious": {
    "message": "Forrige slide"
  },
  "tourDone": {
    "message": "Ferdig"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Ved å bruke Firefox Screenshots, godtar du $TERMSANDPRIVACYNOTICETERMSLINK$ og $TERMSANDPRIVACYNOTICEPRIVACYLINK$ for Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "vilkår"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "personvernbestemmelser"
  }
}PK
!<(
kk&webextension/_locales/nl/messages.json{
  "addonDescription": {
    "message": "Maak clips en schermafbeeldingen van het web en sla deze tijdelijk of permanent op."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Een schermafbeelding maken"
  },
  "myShotsLink": {
    "message": "Mijn afbeeldingen"
  },
  "screenshotInstructions": {
    "message": "Sleep of klik op de pagina om een gebied te selecteren. Druk op ESC om te annuleren."
  },
  "saveScreenshotSelectedArea": {
    "message": "Opslaan"
  },
  "saveScreenshotVisibleArea": {
    "message": "Zichtbaar gebied opslaan"
  },
  "saveScreenshotFullPage": {
    "message": "Volledige pagina opslaan"
  },
  "cancelScreenshot": {
    "message": "Annuleren"
  },
  "downloadScreenshot": {
    "message": "Downloaden"
  },
  "notificationLinkCopiedTitle": {
    "message": "Koppeling gekopieerd"
  },
  "notificationLinkCopiedDetails": {
    "message": "De koppeling naar uw afbeelding is naar het klembord gekopieerd. Druk op $META_KEY$-V om te plakken.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Buiten werking."
  },
  "requestErrorDetails": {
    "message": "Sorry! Uw afbeelding kon niet worden opgeslagen. Probeer het later opnieuw."
  },
  "connectionErrorTitle": {
    "message": "We kunnen geen verbinding met uw schermafdrukken maken."
  },
  "connectionErrorDetails": {
    "message": "Controleer uw internetverbinding. Als u verbinding met het internet kunt maken, kan er sprake zijn van een tijdelijk probleem met de Firefox Screenshots-service."
  },
  "loginErrorDetails": {
    "message": "Uw afbeelding kon niet worden opgeslagen, omdat er een probleem is met de Firefox Screenshots-service. Probeer het later opnieuw."
  },
  "unshootablePageErrorTitle": {
    "message": "Van deze pagina kan geen schermafbeelding worden gemaakt."
  },
  "unshootablePageErrorDetails": {
    "message": "Dit is geen standaardwebpagina, dus u kunt er geen schermafbeelding van maken."
  },
  "selfScreenshotErrorTitle": {
    "message": "U kunt geen afbeelding van een Firefox Screenshots-pagina maken!"
  },
  "emptySelectionErrorTitle": {
    "message": "Uw selectie is te klein"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots is uitgeschakeld in Privénavigatiemodus"
  },
  "privateWindowErrorDetails": {
    "message": "Sorry voor het ongemak. Voor toekomstige releases wordt aan deze functie gewerkt."
  },
  "genericErrorTitle": {
    "message": "Ho! Er is iets mis met Firefox Screenshots."
  },
  "genericErrorDetails": {
    "message": "We weten niet precies wat er zonet is gebeurd. Wilt u het nogmaals proberen, of een schermafbeelding van een andere pagina maken?"
  },
  "tourBodyOne": {
    "message": "Maak, bewaar en deel schermafbeeldingen zonder Firefox te verlaten."
  },
  "tourHeaderTwo": {
    "message": "Leg alleen vast wat u wilt"
  },
  "tourBodyTwo": {
    "message": "Klik en sleep om alleen een gedeelte van een pagina vast te leggen. U kunt ook de muisaanwijzer boven een gebied houden om uw selectie te accentueren."
  },
  "tourHeaderThree": {
    "message": "Leg vensters of hele pagina’s vast"
  },
  "tourBodyThree": {
    "message": "Selecteer de knoppen rechtsboven om het zichtbare gebied in het venster vast te leggen, of om een hele pagina vast te leggen."
  },
  "tourHeaderFour": {
    "message": "Zoals u wilt"
  },
  "tourBodyFour": {
    "message": "Sla uw bijgesneden afbeeldingen op op het web voor makkelijker delen, of download ze naar uw computer. U kunt ook op de knop Mijn afbeeldingen klikken om al uw gemaakte afbeeldingen te vinden."
  },
  "tourSkip": {
    "message": "Overslaan"
  },
  "tourNext": {
    "message": "Volgende slide"
  },
  "tourPrevious": {
    "message": "Vorige slide"
  },
  "tourDone": {
    "message": "Gereed"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Door Firefox Screenshots te gebruiken, gaat u akkoord met de $TERMSANDPRIVACYNOTICETERMSLINK$ en $TERMSANDPRIVACYNOTICEPRIVACYLINK$ van Firefox-cloudservices.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Voorwaarden"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Privacyverklaring"
  }
}PK
!<)webextension/_locales/nn_NO/messages.json{
  "addonDescription": {
    "message": "Ta klipp og skjermbilde frå nettet og lagre dei mellombels eller permanent."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Ta eit skjermbilde"
  },
  "myShotsLink": {
    "message": "Mine skjermbilde"
  },
  "screenshotInstructions": {
    "message": "Drag eller klikk på sida for å velje eit område. Trykk på ESC for å avbryte."
  },
  "saveScreenshotSelectedArea": {
    "message": "Lagre"
  },
  "saveScreenshotVisibleArea": {
    "message": "Lagre synleg område"
  },
  "saveScreenshotFullPage": {
    "message": "Lagre heile sida"
  },
  "cancelScreenshot": {
    "message": "Avbryt"
  },
  "downloadScreenshot": {
    "message": "Last ned"
  },
  "notificationLinkCopiedTitle": {
    "message": "Lenke kopiert"
  },
  "notificationLinkCopiedDetails": {
    "message": "Lenka til skjermbildet ditt er kopiert til utklippstavla. Trykk på $META_KEY$-V for å lime inn.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "I ustand."
  },
  "requestErrorDetails": {
    "message": "Beklagar! Vi klarte ikkje å lagre skjermbiildet ditt. Prøv igjen seinare."
  },
  "connectionErrorTitle": {
    "message": "Vi kan ikkje kople til skjermbilda dine."
  },
  "connectionErrorDetails": {
    "message": "Kontroller internett-tilkoplinga di. Om du kan kople til internett, kan det vere eit mellombels problem med tenesta Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Vi klarte ikkje å lagre skjermbildet ditt, fordi det er eit problem med tenesta Firefox Screenshots. Prøv igjen seinare."
  },
  "unshootablePageErrorTitle": {
    "message": "Vi kan ikkje ta skjermbilde av sida."
  },
  "unshootablePageErrorDetails": {
    "message": "Dette er ikkje ei vanleg nettside, og du kan ikkje ta skjermbilde av henne."
  },
  "selfScreenshotErrorTitle": {
    "message": "Du kan ikkje ta skjermbilde av sida Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Markeringa di er for lita"
  },
  "privateWindowErrorTitle": {
    "message": "Skjermbildeknipsing er slått av i Privat nettlesings-modus"
  },
  "privateWindowErrorDetails": {
    "message": "Ein er lei for ulempa. Vi jobbar med denne funksjonen for framtidige versjonar."
  },
  "genericErrorTitle": {
    "message": "Oj! Det ser ut til at Firefox Screenshots ikkje fungerer korrekt."
  },
  "genericErrorDetails": {
    "message": "Vi er ikkje sikre på kva som hende. Kan du prøve igjen eller ta eit bilde på ei anna side?"
  },
  "tourBodyOne": {
    "message": "Ta, lagre og del skjermbilde utan å forlate Firefox."
  },
  "tourHeaderTwo": {
    "message": "Knips akkurat det du vil"
  },
  "tourBodyTwo": {
    "message": "Klikk for å drage og knipse berre ein del av sida. Du kan også føre musa over for å framheve merkt område."
  },
  "tourHeaderThree": {
    "message": "Knips vindauge eller heile sider"
  },
  "tourBodyThree": {
    "message": "Vel knappane i det øvre høgre hjørnet for å knipse det synlege området i vindauget eller for å knipse ei heil side."
  },
  "tourHeaderFour": {
    "message": "Som du vil ha det"
  },
  "tourBodyFour": {
    "message": "Lagre dei tilskjerte bilda dine på nettet for enklare deling, eller last dei ned til datamaskina di. Du kan også klikke på knappen Mine skjermbilde for å finne alle bilda du har tatt."
  },
  "tourSkip": {
    "message": "Hopp over"
  },
  "tourNext": {
    "message": "Neste slide"
  },
  "tourPrevious": {
    "message": "Føregåande slide"
  },
  "tourDone": {
    "message": "Ferdig"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Ved å bruke Firefox Screenshots, godtar du $TERMSANDPRIVACYNOTICETERMSLINK$ og $TERMSANDPRIVACYNOTICEPRIVACYLINK$ for Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Vilkår"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Personvernmerknad"
  }
}PK
!<+$$)webextension/_locales/pa_IN/messages.json{
  "addonAuthorsList": {
    "message": "ਮੌਜ਼ੀਲਾ <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "ਸਕਰੀਨ-ਸ਼ਾਟ ਲਵੋ"
  },
  "myShotsLink": {
    "message": "ਮੇਰੇ ਸ਼ਾਟ"
  },
  "screenshotInstructions": {
    "message": "ਖੇਤਰ ਨੂੰ ਚੁਣਨ ਵਾਸਤੇ ਖਿੱਚੋ ਜਾਂ ਕਲਿੱਕ ਕਰੋ। ਰੱਦ ਕਰਨ ਵਾਸਤੇ ESC ਦੱਬੋ।"
  },
  "saveScreenshotSelectedArea": {
    "message": "ਸੰਭਾਲੋ"
  },
  "saveScreenshotVisibleArea": {
    "message": "ਦਿੱਖ ਨੂੰ ਸੰਭਾਲੋ"
  },
  "saveScreenshotFullPage": {
    "message": "ਪੂਰੇ ਸਫ਼ੇ ਨੂੰ ਸੰਭਾਲੋ"
  },
  "cancelScreenshot": {
    "message": "ਰੱਦ ਕਰੋ"
  },
  "downloadScreenshot": {
    "message": "ਡਾਊਨਲੋਡ ਕਰੋ"
  },
  "notificationLinkCopiedTitle": {
    "message": "ਲਿੰਕ ਕਾਪੀ ਕੀਤਾ ਗਿਆ"
  },
  "requestErrorTitle": {
    "message": "ਖ਼ਰਾਬ ਹੈ।"
  },
  "tourSkip": {
    "message": "ਛੱਡੋ"
  },
  "tourNext": {
    "message": "ਅਗਲੀ ਸਲਾਈਡ"
  },
  "tourPrevious": {
    "message": "ਪਿਛਲੀ ਸਲਾਈਡ"
  },
  "tourDone": {
    "message": "ਮੁਕੰਮਲ"
  }
}PK
!<jǡ&webextension/_locales/pl/messages.json{
  "addonDescription": {
    "message": "Twórz wycinki i zrzuty stron internetowych i zapisuj je tymczasowo lub trwale."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Wykonaj zrzut ekranu"
  },
  "myShotsLink": {
    "message": "Moje zrzuty"
  },
  "screenshotInstructions": {
    "message": "Przeciągnij lub kliknij na stronie, aby wybrać obszar. Naciśnij klawisz Esc, aby anulować."
  },
  "saveScreenshotSelectedArea": {
    "message": "Zapisz"
  },
  "saveScreenshotVisibleArea": {
    "message": "Zapisz widoczne"
  },
  "saveScreenshotFullPage": {
    "message": "Zapisz całą stronę"
  },
  "cancelScreenshot": {
    "message": "Anuluj"
  },
  "downloadScreenshot": {
    "message": "Pobierz"
  },
  "notificationLinkCopiedTitle": {
    "message": "Skopiowano odnośnik"
  },
  "notificationLinkCopiedDetails": {
    "message": "Odnośnik do zrzutu został skopiowany do schowka. Naciśnij $META_KEY$-V, aby go wkleić.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Awaria."
  },
  "requestErrorDetails": {
    "message": "Nie można zapisać zrzutu. Spróbuj ponownie później."
  },
  "connectionErrorTitle": {
    "message": "Nie można połączyć się z zrzutami ekranu."
  },
  "connectionErrorDetails": {
    "message": "Sprawdź swoje połączenie z Internetem. Jeśli działa ono prawidłowo, to może występować tymczasowy problem z usługą Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Nie można zapisać zrzutu, ponieważ występuje problem z usługą Firefox Screenshots. Spróbuj ponownie później."
  },
  "unshootablePageErrorTitle": {
    "message": "Nie można wykonać zrzutu tej strony."
  },
  "unshootablePageErrorDetails": {
    "message": "To nie jest standardowa strona internetowa, więc nie można wykonać jej zrzutu."
  },
  "selfScreenshotErrorTitle": {
    "message": "Nie można wykonać zrzutu strony Firefox Screenshots."
  },
  "emptySelectionErrorTitle": {
    "message": "Zaznaczenie jest za małe"
  },
  "privateWindowErrorTitle": {
    "message": "Firefox Screenshots jest wyłączony w trybie prywatnym"
  },
  "privateWindowErrorDetails": {
    "message": "Przepraszamy za utrudnienia. Pracujemy nad dodaniem tej funkcji."
  },
  "genericErrorTitle": {
    "message": "Firefox Screenshots wymknęło się spod kontroli."
  },
  "genericErrorDetails": {
    "message": "Nie bardzo wiemy, co się wydarzyło. Spróbujesz ponownie lub wykonasz zrzut innej strony?"
  },
  "tourBodyOne": {
    "message": "Wykonuj, zapisuj i udostępniaj zrzuty ekranu bez wychodzenia z Firefoksa."
  },
  "tourHeaderTwo": {
    "message": "Zapisuj tylko to, co potrzebujesz"
  },
  "tourBodyTwo": {
    "message": "Kliknij i przeciągnij, aby zapisać tylko część strony. Możesz także najechać, aby wyróżnić zaznaczony obszar."
  },
  "tourHeaderThree": {
    "message": "Zapisuj zrzuty okien lub całych stron"
  },
  "tourBodyThree": {
    "message": "Kliknij przycisk w górnym prawym rogu, aby zapisać obszar widoczny w oknie lub całą stronę."
  },
  "tourHeaderFour": {
    "message": "Tak, jak lubisz"
  },
  "tourBodyFour": {
    "message": "Zapisuj przycięte zrzuty w Internecie, aby łatwiej je udostępniać, albo pobierz je na swój komputer. Możesz też kliknąć przycisk „Moje zrzuty”, aby przeglądać wszystkie wykonane zrzuty."
  },
  "tourSkip": {
    "message": "Pomiń"
  },
  "tourNext": {
    "message": "Dalej"
  },
  "tourPrevious": {
    "message": "Wstecz"
  },
  "tourDone": {
    "message": "Zamknij"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Używając Firefox Screenshots, zgadzasz się na $TERMSANDPRIVACYNOTICETERMSLINK$ i $TERMSANDPRIVACYNOTICEPRIVACYLINK$ usług Firefox Cloud.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "warunki korzystania"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "zasady ochrony prywatności"
  }
}PK
!<u9\YY)webextension/_locales/pt_BR/messages.json{
  "addonDescription": {
    "message": "Tire capturas de tela da Web e guarde-as temporariamente ou permanentemente."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Tirar uma captura de tela"
  },
  "myShotsLink": {
    "message": "Minhas capturas"
  },
  "screenshotInstructions": {
    "message": "Arraste ou clique na página para selecionar uma região. Pressione ESC para cancelar."
  },
  "saveScreenshotSelectedArea": {
    "message": "Salvar"
  },
  "saveScreenshotVisibleArea": {
    "message": "Salvar área visível"
  },
  "saveScreenshotFullPage": {
    "message": "Salvar página completa"
  },
  "cancelScreenshot": {
    "message": "Cancelar"
  },
  "downloadScreenshot": {
    "message": "Baixar"
  },
  "notificationLinkCopiedTitle": {
    "message": "Link copiado"
  },
  "notificationLinkCopiedDetails": {
    "message": "O link da sua captura foi copiado para a área de transferência. Pressione $META_KEY$-V para colar.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Oops! Fora do ar."
  },
  "requestErrorDetails": {
    "message": "Desculpe! Não conseguimos salvar a sua captura de tela. Por favor, tente novamente mais tarde."
  },
  "connectionErrorTitle": {
    "message": "Não conseguimos nos conectar às suas capturas de tela."
  },
  "connectionErrorDetails": {
    "message": "Por favor, verifique a sua conexão com a Internet. Se consegue conectar-se à Internet, pode haver um problema temporário com o serviço Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Não conseguimos salvar sua captura porque há um problema com o serviço Firefox Screenshots. Por favor, tente novamente mais tarde."
  },
  "unshootablePageErrorTitle": {
    "message": "Não conseguimos capturar a tela nesta página."
  },
  "unshootablePageErrorDetails": {
    "message": "Esta não é uma página web padrão, por isso não podemos capturar sua tela."
  },
  "selfScreenshotErrorTitle": {
    "message": "Você não pode capturar uma página do Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Sua seleção é muito pequena"
  },
  "privateWindowErrorTitle": {
    "message": "As capturas de tela estão desabilitadas no modo de navegação privativa"
  },
  "privateWindowErrorDetails": {
    "message": "Lamentamos o inconveniente. Estamos trabalhando neste recurso para lançamentos futuros."
  },
  "genericErrorTitle": {
    "message": "Uau! Algo correu mal com a capturas de tela do Firefox."
  },
  "genericErrorDetails": {
    "message": "Não temos certeza do que acabou de acontecer. Tentar novamente ou fazer uma captura de uma página diferente?"
  },
  "tourBodyOne": {
    "message": "Capture, salve e compartilhe telas sem sair do Firefox."
  },
  "tourHeaderTwo": {
    "message": "Capture apenas o que você quer"
  },
  "tourBodyTwo": {
    "message": "Clique e arraste para capturar apenas uma parte de uma página. Você também pode passar o mouse para realçar sua seleção."
  },
  "tourHeaderThree": {
    "message": "Capture janelas ou páginas inteiras"
  },
  "tourBodyThree": {
    "message": "Selecione os botões no canto superior direito para capturar a área visível na janela ou capturar uma página inteira."
  },
  "tourHeaderFour": {
    "message": "Como você quiser"
  },
  "tourBodyFour": {
    "message": "Salve as suas capturas na Web para compartilhar mais facilmente ou baixe-as no seu computador. Você também pode clicar no botão Minhas capturas para encontras todas as capturas que tirou."
  },
  "tourSkip": {
    "message": "Pular"
  },
  "tourNext": {
    "message": "Próximo slide"
  },
  "tourPrevious": {
    "message": "Slide anterior"
  },
  "tourDone": {
    "message": "Concluído"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Usando o Firefox Screenshots, você concorda com os $TERMSANDPRIVACYNOTICETERMSLINK$ e $TERMSANDPRIVACYNOTICEPRIVACYLINK$ dos serviços na nuvem do Firefox.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Termos"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Política de privacidade"
  }
}PK
!<$t՛)webextension/_locales/pt_PT/messages.json{
  "addonDescription": {
    "message": "Tire clipes e capturas de ecrã da Web e guarde-as temporariamente ou permanentemente."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Tirar uma captura de ecrã"
  },
  "myShotsLink": {
    "message": "Minhas capturas"
  },
  "screenshotInstructions": {
    "message": "Arraste ou clique na página para selecionar uma região. Pressione ESC para cancelar."
  },
  "saveScreenshotSelectedArea": {
    "message": "Guardar"
  },
  "saveScreenshotVisibleArea": {
    "message": "Guardar visível"
  },
  "saveScreenshotFullPage": {
    "message": "Guardar página inteira"
  },
  "cancelScreenshot": {
    "message": "Cancelar"
  },
  "downloadScreenshot": {
    "message": "Descarregar"
  },
  "notificationLinkCopiedTitle": {
    "message": "Ligação copiada"
  },
  "notificationLinkCopiedDetails": {
    "message": "A ligação para a sua captura foi copiada para a área de transferência. Pressione $META_KEY$-V para colar.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Fora de serviço."
  },
  "requestErrorDetails": {
    "message": "Desculpe! Não conseguimos guardar a sua captura. Por favor tente novamente mais tarde."
  },
  "connectionErrorTitle": {
    "message": "Não conseguimos ligar às suas capturas de ecrã."
  },
  "connectionErrorDetails": {
    "message": "Por favor verifique a sua ligação à Internet. Se consegue ligar-se à Internet, pode existir um problema temporário com o serviço Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Não conseguimos guardar a sua captura porque existe um problema com o serviço Firefox Screenshots. Por favor tente novamente mais tarde."
  },
  "unshootablePageErrorTitle": {
    "message": "Não conseguimos capturar o ecrã nesta página."
  },
  "unshootablePageErrorDetails": {
    "message": "Esta não é uma página Web padrão, por isso não podemos tirar uma captura de ecrã da mesma."
  },
  "selfScreenshotErrorTitle": {
    "message": "Não pode tirar uma captura de uma página Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "A sua seleção é demasiado pequena"
  },
  "privateWindowErrorTitle": {
    "message": "O Screenshots está desativado no modo de navegação privada"
  },
  "privateWindowErrorDetails": {
    "message": "Desculpe pela inconveniência. Estamos a trabalhar nesta funcionalidade para futuros lançamentos."
  },
  "genericErrorTitle": {
    "message": "Uau! Algo correu mal com o Firefox Screenshots."
  },
  "genericErrorDetails": {
    "message": "Não temos a certeza do que acabou de acontecer. Importa-se de tentar novamente ou tirar uma captura de uma página diferente?"
  },
  "tourBodyOne": {
    "message": "Tire, guarde, e partilhe capturas de ecrã sem sair do Firefox."
  },
  "tourHeaderTwo": {
    "message": "Capture aquilo mesmo que pretende"
  },
  "tourBodyTwo": {
    "message": "Clique e arraste para capturar apenas uma porção de uma página. Pode também pairar para destacar a sua seleção."
  },
  "tourHeaderThree": {
    "message": "Capture janelas ou páginas inteiras"
  },
  "tourBodyThree": {
    "message": "Selecione os botões no canto superior direito para capturar a área visível na janela ou para capturar uma página inteira."
  },
  "tourHeaderFour": {
    "message": "Como você gostar"
  },
  "tourBodyFour": {
    "message": "Guarde as suas capturas na Web para partilhar mais facilmente, ou descarregue-as para o seu computador. Pode também clicar no botão Minhas capturas para encontrar todas as capturas que tirou."
  },
  "tourSkip": {
    "message": "SALTAR"
  },
  "tourNext": {
    "message": "Diapositivo seguinte"
  },
  "tourPrevious": {
    "message": "Diapositivo anterior"
  },
  "tourDone": {
    "message": "Feito"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Ao utilizar o Firefox Screenshots, você concorda com os $TERMSANDPRIVACYNOTICETERMSLINK$ e com o $TERMSANDPRIVACYNOTICEPRIVACYLINK$ do Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Termos"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Aviso de privacidade"
  }
}PK
!<r&webextension/_locales/rm/messages.json{
  "addonDescription": {
    "message": "Fai maletgs da visur dal web ed als memorisescha temporarmain u permanentamain."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Far in maletg dal visur"
  },
  "myShotsLink": {
    "message": "Mes maletgs da visur"
  },
  "screenshotInstructions": {
    "message": "Tira u clicca sin la pagina per tscherner ina regiun. Smatga ESC per interrumper."
  },
  "saveScreenshotSelectedArea": {
    "message": "Memorisar"
  },
  "saveScreenshotVisibleArea": {
    "message": "Memorisar la regiun visibla"
  },
  "saveScreenshotFullPage": {
    "message": "Memorisar la pagina cumpletta"
  },
  "cancelScreenshot": {
    "message": "Interrumper"
  },
  "downloadScreenshot": {
    "message": "Telechargiar"
  },
  "notificationLinkCopiedTitle": {
    "message": "Copià la colliaziun"
  },
  "notificationLinkCopiedDetails": {
    "message": "La colliaziun tar tes maletg da visur è vegnida copiada en l'archiv provisoric. Smatga $META_KEY$-V per l'encollar.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Ord funcziun."
  },
  "requestErrorDetails": {
    "message": "Perstgisa! I è actualmain betg pussibel da memorisar tes maletg da visur. Emprova p.pl. pli tard anc ina giada."
  },
  "connectionErrorTitle": {
    "message": "Impussibel da connectar a tes maletgs da visur."
  },
  "connectionErrorDetails": {
    "message": "Controllescha tia connexiun a l'internet. Sche ti has access a l'internet ha il servetsch da Firefox Screenshots forsa temporarmain in problem."
  },
  "loginErrorDetails": {
    "message": "Impussibel da memorisar tes maletg da virus perquai ch'i dat in problem un il servetsch da Firefox Screenshots. Emprova p.pl. pli tard."
  },
  "unshootablePageErrorTitle": {
    "message": "Impussibel da far in maletg da visur da questa pagina."
  },
  "unshootablePageErrorDetails": {
    "message": "Quai n'è betg ina pagina web da standard, perquai n'èsi betg pussaivel da far in maletg da visur dad ella."
  },
  "selfScreenshotErrorTitle": {
    "message": "Impussibel da far in maletg da visur dad ina pagina da Firefox Screenshots."
  },
  "emptySelectionErrorTitle": {
    "message": "La zona selecziunada è memia pitschna"
  },
  "genericErrorTitle": {
    "message": "Oh dieu! Firefox Screenshots ha il singlut."
  },
  "genericErrorDetails": {
    "message": "Nus na savain betg tge ch'è gist capità. Vuls empruvar anc ina giada, forsa cun in'autra pagina?"
  },
  "tourBodyOne": {
    "message": "Far, memorisar e cundivider maletgs da visur senza bandunar Firefox."
  },
  "tourHeaderTwo": {
    "message": "Far maletgs da visur da tut che vi vuls"
  },
  "tourBodyTwo": {
    "message": "Clicca e tira per far in maletg da be ina part da la pagina. Ti pos posiziunar la mieur sur la selecziun per la relevar."
  },
  "tourHeaderThree": {
    "message": "Far maletgs da fanestras u paginas cumplettas"
  },
  "tourBodyThree": {
    "message": "Tscherna il buttun sura dretg per far in maletg da la part visibla en la fanestra u per far in maletg da la pagina cumpletta."
  },
  "tourHeaderFour": {
    "message": "Co che ti prefereschas"
  },
  "tourBodyFour": {
    "message": "Memorisescha ils maletgs da visur en il web per als pudair cundivider u telechargiar sin tes computer. Ti pos era cliccar sin il buttun «Mes maletgs da visur» per vesair tut ils maletgs dal visur che ti has fatg."
  },
  "tourSkip": {
    "message": "Sursiglir"
  },
  "tourNext": {
    "message": "Proxim pass"
  },
  "tourPrevious": {
    "message": "Ultim pass"
  },
  "tourDone": {
    "message": "Finì"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Cun utilisar Firefox Screenshots accepteschas ti $TERMSANDPRIVACYNOTICETERMSLINK$ e $TERMSANDPRIVACYNOTICEPRIVACYLINK$ da Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "las cundiziuns d'utilisaziun"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "la decleraziun da protecziun da datas"
  }
}PK
!<HVV&webextension/_locales/ro/messages.json{
  "addonDescription": {
    "message": "Realizează decupaje și capturi de ecran de pe web și salvează-le temporar sau permanent."
  },
  "contextMenuLabel": {
    "message": "Realizează o captură de ecran"
  },
  "myShotsLink": {
    "message": "Capturile mele"
  },
  "saveScreenshotSelectedArea": {
    "message": "Salvează"
  },
  "cancelScreenshot": {
    "message": "Renunță"
  },
  "downloadScreenshot": {
    "message": "Descarcă"
  },
  "notificationLinkCopiedTitle": {
    "message": "Link copiat"
  },
  "tourSkip": {
    "message": "OMITE"
  },
  "tourNext": {
    "message": "Diapozitivul următor"
  },
  "tourPrevious": {
    "message": "Diapozitivul anterior"
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Termenii"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Politica de confidenţialitate"
  }
}PK
!<:R&webextension/_locales/ru/messages.json{
  "addonDescription": {
    "message": "Делайте вырезки и скриншоты из Интернета и сохраняйте их временно или навсегда."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Сделать скриншот"
  },
  "myShotsLink": {
    "message": "Мои снимки"
  },
  "screenshotInstructions": {
    "message": "Потяните мышью или щёлкните по странице, чтобы выбрать область. Нажмите ESC для отмены."
  },
  "saveScreenshotSelectedArea": {
    "message": "Сохранить"
  },
  "saveScreenshotVisibleArea": {
    "message": "Сохранить видимую область"
  },
  "saveScreenshotFullPage": {
    "message": "Сохранить всю страницу"
  },
  "cancelScreenshot": {
    "message": "Отмена"
  },
  "downloadScreenshot": {
    "message": "Загрузить"
  },
  "notificationLinkCopiedTitle": {
    "message": "Ссылка скопирована"
  },
  "notificationLinkCopiedDetails": {
    "message": "Ссылка на ваш снимок была скопирована в буфер обмена. Нажмите $META_KEY$-V для её вставки.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Произошла ошибка."
  },
  "requestErrorDetails": {
    "message": "Извините! Мы не смогли сохранить ваш снимок. Пожалуйста, попробуйте позже."
  },
  "connectionErrorTitle": {
    "message": "Мы не смогли получить доступ к вашим скриншотам."
  },
  "connectionErrorDetails": {
    "message": "Пожалуйста, проверьте соединение с Интернетом. Если у вам удаётся войти в Интернет, то возможно, возникла временная проблема со службой Скриншотов Firefox."
  },
  "loginErrorDetails": {
    "message": "Мы не можем сохранить ваш снимок, так как возникла проблема с сервисом Скриншотов Firefox. Пожалуйста, попробуйте позже."
  },
  "unshootablePageErrorTitle": {
    "message": "Мы не можем сделать скриншот этой страницы."
  },
  "unshootablePageErrorDetails": {
    "message": "Так как это не обычная веб-страница, мы не сможем сделать её скриншот."
  },
  "selfScreenshotErrorTitle": {
    "message": "Вы не можете сделать скриншот страницы Скриншотов Firefox."
  },
  "emptySelectionErrorTitle": {
    "message": "Выбрана слишком небольшая область"
  },
  "privateWindowErrorTitle": {
    "message": "Скриншоты отключены в режиме Приватного просмотра"
  },
  "privateWindowErrorDetails": {
    "message": "Приносим извинения за неудобства. Мы работаем над включением этой функции в будущие релизы."
  },
  "genericErrorTitle": {
    "message": "Ого! Скриншоты Firefox вышли из строя."
  },
  "genericErrorDetails": {
    "message": "Мы не уверены, в чём проблема. Попробуете ещё раз или сделаете снимок другой страницы?"
  },
  "tourBodyOne": {
    "message": "Делайте, сохраняйте и делитесь скриншотами прямо в Firefox."
  },
  "tourHeaderTwo": {
    "message": "Делайте снимки чего угодно"
  },
  "tourBodyTwo": {
    "message": "Щелкните и потяните мышью для захвата части страницы. Вы также можете навести курсор мыши для подсветки выбранной области."
  },
  "tourHeaderThree": {
    "message": "Захватывайте окна или целые страницы"
  },
  "tourBodyThree": {
    "message": "С помощью кнопок в верхнем правом углу выбирайте захват видимой области окна или страницы целиком."
  },
  "tourHeaderFour": {
    "message": "Как вам нравится"
  },
  "tourBodyFour": {
    "message": "Сохраняйте свои снимки в Интернете, чтобы легко ими делиться, или загружайте их на свой компьютер. Вы также можете просмотреть все сохранённые снимки, нажав на кнопку Мои снимки."
  },
  "tourSkip": {
    "message": "Пропустить"
  },
  "tourNext": {
    "message": "Следующий слайд"
  },
  "tourPrevious": {
    "message": "Предыдущий слайд"
  },
  "tourDone": {
    "message": "Готово"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Используя Скриншоты Firefox, вы соглашаетесь с $TERMSANDPRIVACYNOTICETERMSLINK$ и $TERMSANDPRIVACYNOTICEPRIVACYLINK$ облачных сервисов Firefox.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Условиями использования"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Уведомлением о приватности"
  }
}PK
!<(&webextension/_locales/sk/messages.json{
  "addonDescription": {
    "message": "Vytvorte si snímky obrazovky na webe a uložte si ich dočasne či navždy."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Urobiť snímku obrazovky"
  },
  "myShotsLink": {
    "message": "Moje snímky"
  },
  "screenshotInstructions": {
    "message": "Potiahnutím alebo kliknutím si vyberte oblasť, ktorú chcete zachytiť. Výber zrušíte stlačením klávesa ESC."
  },
  "saveScreenshotSelectedArea": {
    "message": "Uložiť"
  },
  "saveScreenshotVisibleArea": {
    "message": "Uložiť viditeľnú časť"
  },
  "saveScreenshotFullPage": {
    "message": "Uložiť celú stránku"
  },
  "cancelScreenshot": {
    "message": "Zrušiť"
  },
  "downloadScreenshot": {
    "message": "Prevziať"
  },
  "notificationLinkCopiedTitle": {
    "message": "Odkaz bol skopírovaný"
  },
  "notificationLinkCopiedDetails": {
    "message": "Odkaz na vašu snímku bol skopírovaný do schránky. Stlačením $META_KEY$-V ho prilepíte.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Mimo prevádzky."
  },
  "requestErrorDetails": {
    "message": "Mrzí nás to, no nemôžeme uložiť vašu snímku. Skúste to, prosím, neskôr."
  },
  "connectionErrorTitle": {
    "message": "Nemôžeme sa spojiť s vašimi snímkami."
  },
  "connectionErrorDetails": {
    "message": "Prosím, skontrolujte svoje internetové pripojenie. Ak ste pripojení na internet, môže ísť o dočasný problém na strane služby Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Nemohli sme uložiť vašu snímku, pretože nastal problém so službou Firefox Screenshots. Skúste to, prosím, neskôr."
  },
  "unshootablePageErrorTitle": {
    "message": "Túto stránku nemôžeme zachytiť."
  },
  "unshootablePageErrorDetails": {
    "message": "Toto nie je štandardná webová stránka, takže z nej nemôžeme vytvoriť snímku obrazovky."
  },
  "selfScreenshotErrorTitle": {
    "message": "Nemôžete vytvoriť snímku obrazovky stránky Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Váš výber je príliš malý"
  },
  "privateWindowErrorTitle": {
    "message": "Služba Firefox Screenshots je v režime Súkromné prehliadanie zakázaná"
  },
  "privateWindowErrorDetails": {
    "message": "Ospravedlňujeme sa za spôsobené nepríjemnosti. Pracujeme na vylepšení tejto funkcie v budúcich verziách."
  },
  "genericErrorTitle": {
    "message": "Ups! Služba Firefox Screenshots prestala pracovať."
  },
  "genericErrorDetails": {
    "message": "Nie sme si istí, čo sa práve stalo. Chcete tú skúsiť znova alebo chcete vytvoriť snímku inej stránky?"
  },
  "tourBodyOne": {
    "message": "Tvorte, ukladajte a zdieľajte snímky obrazovky bez toho, aby ste museli opustiť Firefox."
  },
  "tourHeaderTwo": {
    "message": "Zachyťte to, čo chcete"
  },
  "tourBodyTwo": {
    "message": "Ak chcete zachytiť časť stránky, urobíte to kliknutím a potiahnutím. Váš výber zvýrazníte tak, že sa naň presuniete myšou."
  },
  "tourHeaderThree": {
    "message": "Zachyťte okná alebo celé webové stránky"
  },
  "tourBodyThree": {
    "message": "Kliknutím na tlačidlo v pravom hornom rohu môžete zachytiť viditeľnú časť stránky. Pomocou ďalšieho tlačidla zachytíte celú stránku."
  },
  "tourHeaderFour": {
    "message": "Urobte to, čo chcete"
  },
  "tourBodyFour": {
    "message": "Uložte si orezanú snímku na web, aby ste ju mohli ľahšie zdieľať alebo si ju prevziať do počítača. Môžete si taktiež pozrieť všetky vaše snímky - stačí, ak kliknete na tlačidlo Moje snímky."
  },
  "tourSkip": {
    "message": "Preskočiť"
  },
  "tourNext": {
    "message": "Ďalšia snímka"
  },
  "tourPrevious": {
    "message": "Predchádzajúca snímka"
  },
  "tourDone": {
    "message": "Hotovo"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Používaním služby Firefox Screenshots súhlasíte s $TERMSANDPRIVACYNOTICETERMSLINK$ a $TERMSANDPRIVACYNOTICEPRIVACYLINK$ Firefox Cloud Services.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "podmienkami"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "zásadami ochrany súkromia"
  }
}PK
!<~&webextension/_locales/sl/messages.json{
  "addonDescription": {
    "message": "Zajemajte posnetke zaslona s spleta ter jih shranite začasno ali trajno."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Zajemi posnetek zaslona"
  },
  "myShotsLink": {
    "message": "Moji posnetki"
  },
  "screenshotInstructions": {
    "message": "Povlecite ali kliknite na strani za izbiro območja. Pritisnite ESC za preklic."
  },
  "saveScreenshotSelectedArea": {
    "message": "Shrani"
  },
  "saveScreenshotVisibleArea": {
    "message": "Shrani vidno"
  },
  "saveScreenshotFullPage": {
    "message": "Shrani celotno stran"
  },
  "cancelScreenshot": {
    "message": "Prekliči"
  },
  "downloadScreenshot": {
    "message": "Prenesi"
  },
  "notificationLinkCopiedTitle": {
    "message": "Povezava kopirana"
  },
  "notificationLinkCopiedDetails": {
    "message": "Povezava do vašega posnetka zaslona je bila kopirana v odložišče. Pritisnite $META_KEY$-V, da jo prilepite.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Ne dela."
  },
  "requestErrorDetails": {
    "message": "Vašega posnetka nismo uspeli shraniti. Poskusite znova kasneje."
  },
  "connectionErrorTitle": {
    "message": "Ne moremo vzpostaviti povezave do vaših posnetkov."
  },
  "connectionErrorDetails": {
    "message": "Preverite svojo internetno povezavo. V kolikor povezava deluje, gre morda za začasno težavo s storitvijo Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Ne moremo shraniti vašega posnetka, ker je prišlo do težave s storitvijo Firefox Screenshots. Poskusite znova kasneje."
  },
  "unshootablePageErrorTitle": {
    "message": "Ne moremo zajeti posnetka te strani."
  },
  "unshootablePageErrorDetails": {
    "message": "To ni običajna spletna stran, zato ne morete zajeti njenega zaslonskega posnetka."
  },
  "selfScreenshotErrorTitle": {
    "message": "Posnetka strani Firefox Screenshots ni mogoče zajeti!"
  },
  "emptySelectionErrorTitle": {
    "message": "Vaš izbor je premajhen"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots je onemogočen v zasebnem načinu brskanja"
  },
  "privateWindowErrorDetails": {
    "message": "Oprostite za nevšečnost. To možnost izboljšujemo za prihodnje izdaje."
  },
  "genericErrorTitle": {
    "message": "Uf! Firefox Screenshots se je pokvaril."
  },
  "genericErrorDetails": {
    "message": "Ne vemo točno, kaj se je pravkar zgodilo. Bi radi poskusili znova ali pa zajeli posnetek kakšne druge strani?"
  },
  "tourBodyOne": {
    "message": "Zajemite, shranite in delite zaslonske posnetke, ne da bi zapustili Firefox."
  },
  "tourHeaderTwo": {
    "message": "Zajemite to, kar hočete"
  },
  "tourBodyTwo": {
    "message": "Kliknite in povlecite, če želite zajeti samo del strani. Svojo izbiro lahko tudi poudarite, tako da preko nje povlečete miškin kazalec."
  },
  "tourHeaderThree": {
    "message": "Zajemite okna ali celotne strani"
  },
  "tourBodyThree": {
    "message": "V zgornjem desnem kotu izberite gumb za zajem vidnega območja v oknu ali celotne strani."
  },
  "tourHeaderFour": {
    "message": "Kot vi želite"
  },
  "tourBodyFour": {
    "message": "Shranite obrezane posnetke na splet za lažje deljenje ali jih prenesite na svoj računalnik. Vse zajete posnetke lahko najdete s klikom na gumb Moji posnetki."
  },
  "tourSkip": {
    "message": "Preskoči"
  },
  "tourNext": {
    "message": "Naslednji diapozitiv"
  },
  "tourPrevious": {
    "message": "Prejšnji diapozitiv"
  },
  "tourDone": {
    "message": "Končano"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Z uporabo Firefox Screenshots se strinjate s $TERMSANDPRIVACYNOTICETERMSLINK$ Firefoxovih storitev v oblaku in $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "pogoji"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "obvestilom o zasebnosti"
  }
}PK
!<1				&webextension/_locales/sq/messages.json{
  "addonDescription": {
    "message": "Përftoni copëza dhe bëni foto në Web dhe ruajini ato përkohësisht ose përfundimisht."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Bëni një Foto"
  },
  "myShotsLink": {
    "message": "Shkrepjet e Mia"
  },
  "screenshotInstructions": {
    "message": "Tërhiqni kursorin ose klikoni te faqja që të përzgjidhni një zonë. Shtypni ESC që të anulohet."
  },
  "saveScreenshotSelectedArea": {
    "message": "Ruaje"
  },
  "saveScreenshotVisibleArea": {
    "message": "Ruaj pjesën e dukshme"
  },
  "saveScreenshotFullPage": {
    "message": "Ruaj krejt faqen"
  },
  "cancelScreenshot": {
    "message": "Anuloje"
  },
  "downloadScreenshot": {
    "message": "Shkarkoje"
  },
  "notificationLinkCopiedTitle": {
    "message": "Lidhja u Kopjua"
  },
  "notificationLinkCopiedDetails": {
    "message": "Lidhja për te fotoja juaj u kopjua në të papastër. Shtypni $META_KEY$-V për ta ngjitur diku.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "S’ka gjendje."
  },
  "requestErrorDetails": {
    "message": "Na ndjeni! S’e ruajtëm dot foton tuaj. Ju lutemi, riprovoni më vonë."
  },
  "connectionErrorTitle": {
    "message": "S’lidhemi dot te fotot tuaja."
  },
  "connectionErrorDetails": {
    "message": "Ju lutemi, kontrolloni lidhjen tuaj Internet. Nëse jeni në gjendje të lidheni në Internet, mund të bëhet fjalë për një problem të përkohshëm me shërbimin Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "S’e ruajtëm dot foton tuaj, ngaqë pati një problem me shërbimin Firefox Screenshots. Ju lutemi, riprovoni më vonë."
  },
  "unshootablePageErrorTitle": {
    "message": "S’bëjmë dot foto të kësaj faqeje."
  },
  "tourHeaderTwo": {
    "message": "Fiksoni Në Foto Aq Sa Doni"
  },
  "tourHeaderThree": {
    "message": "Fiksoni Dritare ose Krejt Faqet"
  },
  "tourHeaderFour": {
    "message": "Si T’ju Pëlqejë"
  },
  "tourDone": {
    "message": "U bë"
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Kushte"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Shënim Privatësie"
  }
}PK
!<Hbgg&webextension/_locales/sr/messages.json{
  "addonDescription": {
    "message": "Бележите снимке екрана са веба и сачувајте их привремено или трајно."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Усликај екран"
  },
  "myShotsLink": {
    "message": "Моји снимци"
  },
  "screenshotInstructions": {
    "message": "Превуците или кликните на страницу да изаберете област. Притисните ESC да прекинете."
  },
  "saveScreenshotSelectedArea": {
    "message": "Сачувај"
  },
  "saveScreenshotVisibleArea": {
    "message": "Сачувај видљиво"
  },
  "saveScreenshotFullPage": {
    "message": "Сачувај целу страницу"
  },
  "cancelScreenshot": {
    "message": "Откажи"
  },
  "downloadScreenshot": {
    "message": "Преузми"
  },
  "notificationLinkCopiedTitle": {
    "message": "Веза копирана"
  },
  "notificationLinkCopiedDetails": {
    "message": "Веза коју сте забележили је копирана у бележницу. Притисните $META_KEY$-V да налепите.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Не ради."
  },
  "requestErrorDetails": {
    "message": "Жао нам је! Нисмо могли сачувати ваш снимак. Покушајте поново касније."
  },
  "connectionErrorTitle": {
    "message": "Не можемо се повезати на ваше снимке."
  },
  "connectionErrorDetails": {
    "message": "Проверите вашу интернет конекцију. Ако можете да се конектујете, онда можда постоји привремени проблем са Firefox Screenshots-ом."
  },
  "loginErrorDetails": {
    "message": "Нисмо могли сачувати ваш снимак јер постоји проблем са Firefox Screenshots-ом. Покушајте поново касније."
  },
  "unshootablePageErrorTitle": {
    "message": "Не можемо забележити снимак ове странице."
  },
  "unshootablePageErrorDetails": {
    "message": "Ово није стандардна веб страница, тако да не можете забележити њен снимак."
  },
  "selfScreenshotErrorTitle": {
    "message": "Не можете усликати Firefox Screenshots страницу!"
  },
  "emptySelectionErrorTitle": {
    "message": "Ваша селекција је премала"
  },
  "privateWindowErrorTitle": {
    "message": "Снимци екрана су онемогућени у приватном режиму"
  },
  "privateWindowErrorDetails": {
    "message": "Жао нам је због овог неспоразума. Радимо на овој могућности за следећа издања."
  },
  "genericErrorTitle": {
    "message": "Ајој! Firefox Screenshots је пошашавио."
  },
  "genericErrorDetails": {
    "message": "Нисмо сигурни шта се управо догодило. Желите ли покушати поново или да усликате другачију страницу?"
  },
  "tourBodyOne": {
    "message": "Забележите, сачувајте и поделите снимке екрана без напуштања Firefox-а."
  },
  "tourHeaderTwo": {
    "message": "Усликајте баш оно што желите"
  },
  "tourBodyTwo": {
    "message": "Кликните и превуците да усликате само део странице. Такође можете означити вашу селекцију."
  },
  "tourHeaderThree": {
    "message": "Усликајте прозоре или целе странице"
  },
  "tourBodyThree": {
    "message": "Изаберите дугмад у горњем десном углу да усликате видљиве делове прозора или да усликате целу страницу."
  },
  "tourHeaderFour": {
    "message": "Као што волите"
  },
  "tourBodyFour": {
    "message": "Сачувајте ваш исечени снимак на веб ради лакшег дељења или преузимања на ваш рачунар. Такође можете кликнути на дугме \"Моји снимци\" да пронађете све ваше снимке."
  },
  "tourSkip": {
    "message": "Прескочи"
  },
  "tourNext": {
    "message": "Следећи слајд"
  },
  "tourPrevious": {
    "message": "Претходни слајд"
  },
  "tourDone": {
    "message": "Готово"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Коришћењем Firefox Screenshots-а, прихватате Firefox Cloud Services $TERMSANDPRIVACYNOTICETERMSLINK$ и $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "услове"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "обавештење о приватности"
  }
}PK
!<I3)webextension/_locales/sv_SE/messages.json{
  "addonDescription": {
    "message": "Ta klipp och skärmbilder från webben och spara dem tillfälligt eller permanent."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Ta en skärmbild"
  },
  "myShotsLink": {
    "message": "Mina skärmbilder"
  },
  "screenshotInstructions": {
    "message": "Dra eller klicka på sidan för att välja en region. Tryck på ESC för att avbryta."
  },
  "saveScreenshotSelectedArea": {
    "message": "Spara"
  },
  "saveScreenshotVisibleArea": {
    "message": "Spara synligt område"
  },
  "saveScreenshotFullPage": {
    "message": "Spara hela sidan"
  },
  "cancelScreenshot": {
    "message": "Avbryt"
  },
  "downloadScreenshot": {
    "message": "Ladda ner"
  },
  "notificationLinkCopiedTitle": {
    "message": "Länk kopierad"
  },
  "notificationLinkCopiedDetails": {
    "message": "Länken till din skärmbild har kopierats till urklipp. Tryck på $META_KEY$-V för att klistra in.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Ur funktion."
  },
  "requestErrorDetails": {
    "message": "Förlåt! Vi kunde inte spara din skärmbild. Försök igen senare."
  },
  "connectionErrorTitle": {
    "message": "Vi kan inte ansluta till dina skärmbilder."
  },
  "connectionErrorDetails": {
    "message": "Kontrollera din internetanslutning. Om du kan ansluta till internet, kan det vara ett tillfälligt problem med tjänsten Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Vi kunde inte spara din skärmbild eftersom det finns ett problem med tjänsten Firefox Screenshots. Försök igen senare."
  },
  "unshootablePageErrorTitle": {
    "message": "Vi kan inte ta en skärmbild av sidan."
  },
  "unshootablePageErrorDetails": {
    "message": "Detta är inte en vanlig webbsida, så du kan inte ta en skärmbild av den."
  },
  "selfScreenshotErrorTitle": {
    "message": "Du kan inte ta en skärmbild av sidan Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Ditt val är för litet"
  },
  "privateWindowErrorTitle": {
    "message": "Skärmbilder är inaktiverad i privat surfläge"
  },
  "privateWindowErrorDetails": {
    "message": "Ledsen för besväret. Vi arbetar med den här funktionen för framtida versioner."
  },
  "genericErrorTitle": {
    "message": "Oj! Firefox Screenshots verkar inte fungera korrekt."
  },
  "genericErrorDetails": {
    "message": "Vi är inte säkra på vad som just hände. Kan du försöka igen eller ta en bild på en annan sida?"
  },
  "tourBodyOne": {
    "message": "Ta, spara, och dela skärmbilder utan att lämna Firefox."
  },
  "tourHeaderTwo": {
    "message": "Fånga precis vad du vill"
  },
  "tourBodyTwo": {
    "message": "Klicka och dra för att fånga bara en del av en sida. Du kan också hovra för att markera ditt val."
  },
  "tourHeaderThree": {
    "message": "Fånga fönster eller hela sidor"
  },
  "tourBodyThree": {
    "message": "Välj knapparna i det övre högra hörnet för att fånga det synliga området i fönstret eller för att fånga en hel sida."
  },
  "tourHeaderFour": {
    "message": "Som du vill ha det"
  },
  "tourBodyFour": {
    "message": "Spara dina beskurna bilder till webben för enklare delning, eller hämta dem till datorn. Du kan också klicka på knappen Mina skärmbilder för att hitta alla bilder du tagit."
  },
  "tourSkip": {
    "message": "Hoppa över"
  },
  "tourNext": {
    "message": "Nästa sida"
  },
  "tourPrevious": {
    "message": "Föregående sida"
  },
  "tourDone": {
    "message": "Färdig"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Genom att använda Firefox Screenshots, godkänner du $TERMSANDPRIVACYNOTICETERMSLINK$ och $TERMSANDPRIVACYNOTICEPRIVACYLINK$ för Firefox molntjänster.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Villkor"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Sekretesspolicy"
  }
}PK
!<l!l!&webextension/_locales/ta/messages.json{
  "addonDescription": {
    "message": "வலைபக்கங்களை நிரந்தரமாக (அ) தற்காலிகமாக துணுக்குகளாக (அ) திரைப்பிடிப்புகளாக சேமியுங்கள்."
  },
  "addonAuthorsList": {
    "message": "மொசில்லா <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "ஒரு திரைப்பிடிப்பு செய்"
  },
  "myShotsLink": {
    "message": "எனது திரைகள்"
  },
  "screenshotInstructions": {
    "message": "பக்கத்தில் இழுத்தோ (அ) சொடுக்கியோ ஒரு பகுதியைத் தேர்வுச்செய்க. இரத்து செய்ய ESC விசையை அழுத்தவும்."
  },
  "saveScreenshotSelectedArea": {
    "message": "சேமி"
  },
  "saveScreenshotVisibleArea": {
    "message": "பார்ப்பதைச் சேமி"
  },
  "saveScreenshotFullPage": {
    "message": "முழு பக்கத்தைச் சேமி"
  },
  "cancelScreenshot": {
    "message": "இரத்து"
  },
  "downloadScreenshot": {
    "message": "பதிவிறக்கு"
  },
  "notificationLinkCopiedTitle": {
    "message": "தொடுப்பு நகலெடுக்கப்பட்டது"
  },
  "notificationLinkCopiedDetails": {
    "message": "நீங்கள் எடுத்த திரைப்பிடிப்பிற்கான தொடுப்பு ஒட்டுபலகைக்கு நகலெடுக்கப்பட்டது. ஒட்ட $META_KEY$ விசையை அழுத்தவும்.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "சேவை இணைப்பில் இல்லை."
  },
  "requestErrorDetails": {
    "message": "மன்னிக்க! உங்களின் திரைப்பிடிப்பைச் சேமிக்க முடியவில்லை. மீண்டும் முயற்சிக்கவும்."
  },
  "connectionErrorTitle": {
    "message": "உங்களின் திரைப்பிடிப்பு சேவையகத்தை அணுக முடியவில்லை."
  },
  "connectionErrorDetails": {
    "message": "தயவுச்செய்து உங்கள் இணைய இணைப்பைச் சரிபாருங்கள். உங்களால் இணையத்தை அணுக முடிந்தால் இது பயர்பாஃசு திரைப்பிடிப்பிற்கான இடைப்பட்ட சேவை துண்டிப்பாகும்."
  },
  "loginErrorDetails": {
    "message": "பயர்பாஃசின் திரைப்பிடிப்பு சேவை தடைப்பட்டதால் உங்களின் திரைப்பிடிப்பைச் சேமிக்க முடியவில்லை. மீண்டும் முயற்சிக்கவும்."
  },
  "unshootablePageErrorTitle": {
    "message": "இப்பக்கத்தை திரைப்பிடிப்பு செய்ய முடியாது."
  },
  "unshootablePageErrorDetails": {
    "message": "இது ஒரு இணையத்தளம் போன்று தெரிவில்லை, எனவே உங்களால் திரைப்பிடிப்பு எடுக்க முடியாது."
  },
  "selfScreenshotErrorTitle": {
    "message": "பயர்பாஃசு திரைப்பிடிப்பு பக்கத்தை உங்களால் திரைப்பிடிப்பு செய்ய முடியாது!"
  },
  "emptySelectionErrorTitle": {
    "message": "உங்களின் தேர்வு மிகச் சிறியது"
  },
  "privateWindowErrorTitle": {
    "message": "அந்தரங்க உலாவல் முறையில் திரைபிடிப்பு முடக்கப்பட்டுள்ளது"
  },
  "privateWindowErrorDetails": {
    "message": "சிரமத்திற்கு வருந்துகிறோம். எதிர்கால வெளியீடுகளில் நாங்கள் இந்த வசதியைச் செய்து தருகிறோம்."
  },
  "genericErrorTitle": {
    "message": "அய் அய்யோ! பயர்பாஃசு திரைப்பிடிப்பு வீணாய் போனது."
  },
  "genericErrorDetails": {
    "message": "என்ன நடந்தது என எங்களுக்குத் தெரியவில்லை. முடிந்தால் மீண்டும் முயற்சியுங்கள் (அ) வேறொரு பக்கத்தில் முயற்சியுங்கள்?"
  },
  "tourBodyOne": {
    "message": "பயர்பாஃசை விட்டு வெளியேறாமல் திரைப்பிடிப்புகளை எடுக்கலாம், சேமித்து மற்றவருடன் பகிர்ந்துக்கொள்ளலாம்."
  },
  "tourHeaderTwo": {
    "message": "உங்களுக்கு என்ன வேண்டுமோ அதைக் கைப்பற்றுங்கள்"
  },
  "tourBodyTwo": {
    "message": "சொடுக்கி இழுத்து சும்மா ஒரு பகுதியைத் தேர்வுச்செய்க. நீங்கள் இங்கும் அங்குமாக நகர்த்திக் கூட நீங்கள் தேர்வுச்செய்த பக்கத்தை மிளிர்க்கச் செய்யலாம்."
  },
  "tourHeaderThree": {
    "message": "சாளரங்களை (அ) முழுப் பக்கங்களை கைப்பற்றவும்"
  },
  "tourBodyThree": {
    "message": "வலது மேல்முனையில் உள்ள கத்திரிகோல் போன்ற பயன்படுத்தி பார்வையில் இருக்கும் வலைப்பக்கத்தையோ (அ) முழு பக்கத்தையோ திரைப்பிடிப்புச் செய்யுங்கள்."
  },
  "tourHeaderFour": {
    "message": "நீங்கள் விரும்பியவாறே"
  },
  "tourBodyFour": {
    "message": "நீங்கள் எடுத்த வெட்டிய திரைப்பிடிப்புகளை இணையத்தில் எளிதில் சேமித்து பகிரவோ (அ) கணினியில் பதிவிறக்கவோ முடியும். 'எனது பிடிப்புகள்' மீது சொடுக்கி உங்களின் திரைப்பிடிப்புகளைக் காணலாம்."
  },
  "tourSkip": {
    "message": "தாவு"
  },
  "tourNext": {
    "message": "அடுத்த வில்லை"
  },
  "tourPrevious": {
    "message": "முந்தைய வில்லை"
  },
  "tourDone": {
    "message": "முடிந்தது"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "பயர்பாஃசு திரைப்பிடிப்பைப் பயன்படுத்துவதன் மூலம் எங்களின் முகில் கணிமச் சேவைகளுக்கான பின்வரும் $TERMSANDPRIVACYNOTICETERMSLINK$ $TERMSANDPRIVACYNOTICEPRIVACYLINK$ நிபந்தனைகளை ஏற்றுக் கொள்கிறீர்கள்.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "நிபந்தனைகள்"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "தனியுரிம கொள்கை"
  }
}PK
!<{c		&webextension/_locales/te/messages.json{
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "ఒక తెరపట్టు తీసుకోండి"
  },
  "myShotsLink": {
    "message": "నా తెరపట్లు"
  },
  "saveScreenshotSelectedArea": {
    "message": "భద్రపరచు"
  },
  "saveScreenshotVisibleArea": {
    "message": "కనిపించే దానిని బద్రపరచండి"
  },
  "saveScreenshotFullPage": {
    "message": "పూర్తి పేజీని భద్రపరచు"
  },
  "cancelScreenshot": {
    "message": "రద్దుచేయి"
  },
  "downloadScreenshot": {
    "message": "దింపుకోండి"
  },
  "notificationLinkCopiedTitle": {
    "message": "లంకె కాపీ అయింది"
  },
  "requestErrorTitle": {
    "message": "పని చెయుట లేదు."
  },
  "requestErrorDetails": {
    "message": "క్షమిచండి! మీ తెరను భద్రపరచలేకపోయాం. దయచేసి కాసేపాగి మళ్ళీ ప్రయత్నించండి."
  },
  "connectionErrorTitle": {
    "message": "మేము మీ స్క్రీన్షాట్లకు కనెక్ట్ చేయలేము."
  },
  "unshootablePageErrorTitle": {
    "message": "మేము ఈ పేజీని స్క్రీన్షాట్ చేయలేము."
  },
  "unshootablePageErrorDetails": {
    "message": "ఇది ప్రామాణిక వెబ్ పేజీ కాదు, కాబట్టి దాని యొక్క స్క్రీన్షాట్ని మీరు తీసుకోలేరు."
  },
  "selfScreenshotErrorTitle": {
    "message": "మీరు Firefox స్క్రీన్షాట్స్ పేజీ యొక్క షాట్ ను తీసుకోలేరు!"
  },
  "emptySelectionErrorTitle": {
    "message": "మీ ఎంపిక చాలా చిన్న్దగా ఉంది"
  },
  "genericErrorTitle": {
    "message": "అయ్యో! Firefox స్క్రీన్షాట్లు haywire వెళ్ళింది."
  },
  "tourBodyOne": {
    "message": "Firefox ను వదలకుండా స్క్రీన్షాట్లను తీసుకోండి, సేవ్ చేయండి మరియు పంచండి."
  },
  "tourHeaderTwo": {
    "message": ""
  },
  "tourHeaderFour": {
    "message": "మీకు నచ్చినట్టుగా"
  },
  "tourSkip": {
    "message": "దాటవేయి"
  },
  "tourNext": {
    "message": "తర్వాతి ఫలకం"
  },
  "tourPrevious": {
    "message": "మునుపటి ఫలకం"
  },
  "tourDone": {
    "message": "పూర్తయింది"
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "నియమాలు"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "గోప్యతా నోటీసు"
  }
}PK
!<]HE&webextension/_locales/th/messages.json{
  "addonDescription": {
    "message": "จับภาพหน้าจอจากเว็บและบันทึกไว้ชั่วคราวหรือถาวร"
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "จับภาพหน้าจอ"
  },
  "myShotsLink": {
    "message": "ภาพของฉัน"
  },
  "screenshotInstructions": {
    "message": "ลากหรือคลิกที่หน้าเพื่อเลือกบริเวณ กด ESC เพื่อยกเลิก"
  },
  "saveScreenshotSelectedArea": {
    "message": "บันทึก"
  },
  "saveScreenshotVisibleArea": {
    "message": "บันทึกส่วนที่มองเห็น"
  },
  "saveScreenshotFullPage": {
    "message": "บันทึกเต็มหน้า"
  },
  "cancelScreenshot": {
    "message": "ยกเลิก"
  },
  "downloadScreenshot": {
    "message": "ดาวน์โหลด"
  },
  "notificationLinkCopiedTitle": {
    "message": "คัดลอกลิงก์แล้ว"
  },
  "notificationLinkCopiedDetails": {
    "message": "คัดลอกลิงก์ไปยังภาพของคุณไปยังคลิปบอร์ดแล้ว กด $META_KEY$-V เพื่อวาง",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "ใช้งานไม่ได้"
  },
  "requestErrorDetails": {
    "message": "ขออภัย! เราไม่สามารถบันทึกภาพของคุณ โปรดลองอีกครั้งในภายหลัง"
  },
  "connectionErrorTitle": {
    "message": "เราไม่สามารถเชื่อมต่อกับภาพหน้าจอของคุณ"
  },
  "connectionErrorDetails": {
    "message": "โปรดตรวจสอบการเชื่อมต่ออินเทอร์เน็ตของคุณ หากคุณสามารถเชื่อมต่ออินเทอร์เน็ต บริการ Firefox Screenshots อาจมีปัญหาชั่วคราว"
  },
  "loginErrorDetails": {
    "message": "เราไม่สามารถบันทึกภาพของคุณเนื่องจากบริการ Firefox Screenshots มีปัญหา โปรดลองอีกครั้งในภายหลัง"
  },
  "unshootablePageErrorTitle": {
    "message": "เราไม่สามารถจับภาพหน้าจอหน้านี้"
  },
  "unshootablePageErrorDetails": {
    "message": "นี่ไม่ใช่หน้าเว็บมาตรฐาน คุณจึงไม่สามารถจับภาพหน้าจอได้"
  },
  "selfScreenshotErrorTitle": {
    "message": "คุณไม่สามารถจับภาพของหน้า Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "การเลือกของคุณเล็กเกินไป"
  },
  "privateWindowErrorTitle": {
    "message": "Screenshots ถูกปิดใช้งานในโหมดการท่องเว็บแบบส่วนตัว"
  },
  "privateWindowErrorDetails": {
    "message": "ขออภัยในความไม่สะดวก เรากำลังพัฒนาคุณลักษณะนี้สำหรับรุ่นในอนาคต"
  },
  "genericErrorTitle": {
    "message": "โอ๊ย! Firefox Screenshots รวน"
  },
  "genericErrorDetails": {
    "message": "เราไม่แน่ใจว่าเกิดอะไรขึ้น ต้องการลองอีกครั้งหรือจับภาพของหน้าอื่น?"
  },
  "tourBodyOne": {
    "message": "จับ บันทึก และแบ่งปันภาพหน้าจอโดยไม่ต้องออกจาก Firefox"
  },
  "tourHeaderTwo": {
    "message": "จับภาพแค่สิ่งที่คุณต้องการ"
  },
  "tourBodyTwo": {
    "message": "คลิกแล้วลากเพื่อจับภาพแค่บางส่วนของหน้า คุณยังสามารถวางเมาส์เพื่อเน้นการเลือกของคุณ"
  },
  "tourHeaderThree": {
    "message": "จับภาพหน้าต่างหรือทั้งหน้า"
  },
  "tourBodyThree": {
    "message": "คลิกที่ปุ่มด้านบนขวาเพื่อจับภาพพื้นที่ที่มองเห็นในหน้าต่างหรือเพื่อจับภาพทั้งหน้า"
  },
  "tourHeaderFour": {
    "message": "ตามใจชอบ"
  },
  "tourBodyFour": {
    "message": "บันทึกภาพที่ครอบตัดของคุณไปยังเว็บเพื่อการแบ่งปันที่ง่ายขึ้น หรือดาวน์โหลดไปยังคอมพิวเตอร์ของคุณ คุณยังสามารถคลิกที่ปุ่ม ภาพของฉัน เพื่อค้นหาภาพทั้งหมดที่คุณจับไว้"
  },
  "tourSkip": {
    "message": "ข้าม"
  },
  "tourNext": {
    "message": "ภาพนิ่งถัดไป"
  },
  "tourPrevious": {
    "message": "ภาพนิ่งก่อนหน้า"
  },
  "tourDone": {
    "message": "เสร็จสิ้น"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "เพื่อใช้ Firefox Screenshots คุณยอมรับ $TERMSANDPRIVACYNOTICETERMSLINK$ และ $TERMSANDPRIVACYNOTICEPRIVACYLINK$ ของบริการกลุ่มเมฆ Firefox",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "ข้อกำหนด"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "ประกาศความเป็นส่วนตัว"
  }
}PK
!<։$$&webextension/_locales/tl/messages.json{
  "addonDescription": {
    "message": "Dalhin ang clip at mga screenshot mula sa Web at i-save ang mga ito pansamantala o permanente."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Kumuha ng Screenshot"
  },
  "myShotsLink": {
    "message": "Aking Shots"
  },
  "screenshotInstructions": {
    "message": "I-drag o i-click sa pahina upang pumili ng rehiyon. Pindutin ang ESC upang kanselahin."
  },
  "saveScreenshotSelectedArea": {
    "message": "I-save"
  },
  "saveScreenshotVisibleArea": {
    "message": "I-save na nakikita"
  },
  "saveScreenshotFullPage": {
    "message": "I-save ang buong pahina"
  },
  "cancelScreenshot": {
    "message": "Kanselahin"
  },
  "downloadScreenshot": {
    "message": "Download"
  },
  "notificationLinkCopiedTitle": {
    "message": "Kinopya ang Link"
  },
  "notificationLinkCopiedDetails": {
    "message": "Ang link na ito sa iyong shot ay kinopya sa clipboard. Pindutin $META_KEY$-V i-paste.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Mula sa pagkakasunod-sunod."
  },
  "requestErrorDetails": {
    "message": "Paumanhin! Hindi namin mai-save ang iyong mga shot. Subukang muli mamaya."
  },
  "connectionErrorTitle": {
    "message": "Hindi namin maaaring i-kunekta sa iyong mga screenshot."
  },
  "connectionErrorDetails": {
    "message": "Mangyaring suriin ang iyong koneksyon sa Internet. Kung ikaw ay kumonekta sa Internet, maaaring may isang pansamantalang problema sa serbisyo Firefox screenshot."
  },
  "loginErrorDetails": {
    "message": "Hindi namin mai-save ang iyong mga shot dahil may problema sa serbisyo Firefox screenshot. Subukang muli mamaya."
  },
  "unshootablePageErrorTitle": {
    "message": "Hindi namin maaaring screenshot pahinang ito."
  },
  "unshootablePageErrorDetails": {
    "message": "Ito ay hindi isang standard na Web page, kaya hindi ka maaaring kumuha ng isang screenshot ng mga ito."
  },
  "selfScreenshotErrorTitle": {
    "message": "Hindi ka maaaring kumuha ng isang shot ng isang pahina ng Firefox screenshot!"
  },
  "genericErrorTitle": {
    "message": "Whoa! Nagiging magulo ang Firefox screenshot."
  },
  "genericErrorDetails": {
    "message": "Hindi kami sigurado kung ano ang nangyari. Pag-aalaga upang subukang muli o kumuha ng isang shot ng isang iba't ibang mga pahina?"
  },
  "tourBodyOne": {
    "message": "Dumaan, i-save, at ibahagi ang mga screenshot nang hindi umaalis sa Firefox."
  },
  "tourHeaderTwo": {
    "message": "Kunan Kung Ano Ang Gusto Mo"
  },
  "tourBodyTwo": {
    "message": "I-click at i-drag upang makuha lamang ang isang bahagi ng isang pahina. Maaari mo ring i-hover upang i-highlight ang iyong pagpili."
  },
  "tourHeaderThree": {
    "message": "I-capture ang Windows o Buong Pahina"
  },
  "tourBodyThree": {
    "message": "Piliin ang pindutan sa kanang itaas upang makuha ang nakikitang lugar sa window o upang makuha ang isang buong pahina."
  },
  "tourHeaderFour": {
    "message": "Bilang Nagustuhan Mo ito"
  },
  "tourBodyFour": {
    "message": "I-save ang iyong crop shot sa Web para sa madaling pagbabahagi, o i-download ito sa iyong computer. Maaari mo ring i-click sa pindutan ng My Shots upang mahanap ang lahat ng mga pag-shot na kinunan mo."
  },
  "tourSkip": {
    "message": "Laktawan"
  },
  "tourNext": {
    "message": "Susunod na Slide"
  },
  "tourPrevious": {
    "message": "Nakaraan na Slide"
  },
  "tourDone": {
    "message": "Tapos"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Sa paggamit ng Firefox Screenshots, tinatanggap mo ang Firefox Cloud Services $TERMSANDPRIVACYNOTICETERMSLINK$ at $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Mga tuntunin"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Abiso sa Privacy"
  }
}PK
!<-j&webextension/_locales/tr/messages.json{
  "addonDescription": {
    "message": "Web sayfalarının ekran görüntülerini alın, ister geçici ister kalıcı olarak kaydedin."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Ekran görüntüsü al"
  },
  "myShotsLink": {
    "message": "Ekran görüntülerim"
  },
  "screenshotInstructions": {
    "message": "Bir bölgeyi seçmek için işaretçiyi sürükleyin veya tıklayın. İptal etmek için ESC tuşuna basın."
  },
  "saveScreenshotSelectedArea": {
    "message": "Kaydet"
  },
  "saveScreenshotVisibleArea": {
    "message": "Görünür alanı kaydet"
  },
  "saveScreenshotFullPage": {
    "message": "Tüm sayfayı kaydet"
  },
  "cancelScreenshot": {
    "message": "Vazgeç"
  },
  "downloadScreenshot": {
    "message": "İndir"
  },
  "notificationLinkCopiedTitle": {
    "message": "Bağlantı kopyalandı"
  },
  "notificationLinkCopiedDetails": {
    "message": "Ekran görüntünüzün bağlantısı panoya kopyalandı. Yapıştırmak için $META_KEY$-V tuşlarına basabilirsiniz.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Arıza var."
  },
  "requestErrorDetails": {
    "message": "Ekran görüntünüzü kaydedemedik. Lütfen daha sonra yeniden deneyin."
  },
  "connectionErrorTitle": {
    "message": "Ekran görüntülerinize bağlanamadık."
  },
  "connectionErrorDetails": {
    "message": "Lütfen internet bağlantınızı kontrol edin. İnternete bağlanabiliyorsanız Firefox Screenhosts hizmeti ile ilgili geçici bir sorun olabilir."
  },
  "loginErrorDetails": {
    "message": "Firefox Screenshosts hizmetinde bir sorun yaşandığı için ekran görüntünüzü kaydedemedik. Lütfen daha sonra yeniden deneyin."
  },
  "unshootablePageErrorTitle": {
    "message": "Bu sayfanın ekran görüntüsü alınamıyor."
  },
  "unshootablePageErrorDetails": {
    "message": "Bu sayfa standart bir web sayfası olmadığı için ekran görüntüsünü alamazsınız."
  },
  "selfScreenshotErrorTitle": {
    "message": "Firefox Screenshots sayfalarının ekran görüntüsünü alamazsınz."
  },
  "emptySelectionErrorTitle": {
    "message": "Seçiminiz çok küçük"
  },
  "privateWindowErrorTitle": {
    "message": "Gizli Gezinti modunda Screenshosts özelliği kullanılamaz"
  },
  "privateWindowErrorDetails": {
    "message": "Aksaklıktan dolayı özür dileriz. Gelecek sürümlerde bu özelliği devreye almak için çalışıyoruz."
  },
  "genericErrorTitle": {
    "message": "Firefox Screenshosts kafayı yedi!"
  },
  "genericErrorDetails": {
    "message": "Ne olduğunu biz de anlamadık. Bir daha denemeye veya başka bir sayfanın ekran görüntüsünü almaya ne dersiniz?"
  },
  "tourBodyOne": {
    "message": "Firefox'tan çıkmadan ekran görüntüleri alın, kaydedin ve paylaşın."
  },
  "tourHeaderTwo": {
    "message": "İstediğini yakala"
  },
  "tourBodyTwo": {
    "message": "Sayfanın belli bir kısmını yakalamak için işaretçiyi tıklayıp sürükleyin. Seçiminizi vurgulamak için fareyle üzerine gelebilirsiniz."
  },
  "tourHeaderThree": {
    "message": "Pencereleri veya sayfaların tamamını yakala"
  },
  "tourBodyThree": {
    "message": "Yalnızca pencerede gördüğünüz alanı veya sayfanın tamamını yakalamak için sağ üstteki düğmelerden uygun olanı seçin."
  },
  "tourHeaderFour": {
    "message": "İstediğin gibi yakala"
  },
  "tourBodyFour": {
    "message": "Ekran görüntülerinizi daha kolay paylaşmak veya bilgisayarınıza indirmek için web’e kaydedin. Kaydettiğiniz tüm görüntüleri bulmak için \"Ekran görüntülerim\" düğmesine tıklayabilirsiniz."
  },
  "tourSkip": {
    "message": "GEÇ"
  },
  "tourNext": {
    "message": "Sonraki slayt"
  },
  "tourPrevious": {
    "message": "Önceki slayt"
  },
  "tourDone": {
    "message": "Tamam"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Firefox Screenshots'ı kullandığınızda Firefox Bulut Hizmetleri'nin $TERMSANDPRIVACYNOTICETERMSLINK$ ve $TERMSANDPRIVACYNOTICEPRIVACYLINK$ kabul etmiş sayılırsınız.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Koşullarımızı"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Gizlilik Bildirimimizi"
  }
}PK
!<:g&webextension/_locales/uk/messages.json{
  "addonDescription": {
    "message": "Робіть вирізки та знімки екрану в Інтернеті та зберігайте їх для подальшої роботи."
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Зробити знімок екрану"
  },
  "myShotsLink": {
    "message": "Мої знімки"
  },
  "screenshotInstructions": {
    "message": "Потягніть або клацніть на сторінці для вибору області. Натисніть ESC для скасування."
  },
  "saveScreenshotSelectedArea": {
    "message": "Зберегти"
  },
  "saveScreenshotVisibleArea": {
    "message": "Зберегти видиму область"
  },
  "saveScreenshotFullPage": {
    "message": "Зберегти всю сторінку"
  },
  "cancelScreenshot": {
    "message": "Скасувати"
  },
  "downloadScreenshot": {
    "message": "Завантажити"
  },
  "notificationLinkCopiedTitle": {
    "message": "Посилання скопійовано"
  },
  "notificationLinkCopiedDetails": {
    "message": "Посилання на ваш знімок було скопійоване до буфера обміну. Натисніть $META_KEY$-V для вставлення.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Сталася помилка."
  },
  "requestErrorDetails": {
    "message": "Вибачте! Нам не вдалося зберегти ваш знімок. Спробуйте знову пізніше."
  },
  "connectionErrorTitle": {
    "message": "Ми не можемо отримати доступ до ваших знімків."
  },
  "connectionErrorDetails": {
    "message": "Будь ласка, перевірте ваше підключення до Інтернету. Якщо у вас все в порядку з Інтернетом, можливо, виникли тимчасові проблеми зі службою Firefox Screenshots."
  },
  "loginErrorDetails": {
    "message": "Нам не вдалося зберегти ваш знімок, тому що виникли проблеми зі службою Firefox Screenshots. Спробуйте знову пізніше."
  },
  "unshootablePageErrorTitle": {
    "message": "Ми не можемо зробити знімок цієї сторінки."
  },
  "unshootablePageErrorDetails": {
    "message": "Це не стандартна веб-сторінка, тому ви не можете зробити її знімок."
  },
  "selfScreenshotErrorTitle": {
    "message": "Ви не можете зробити знімок сторінки Firefox Screenshots!"
  },
  "emptySelectionErrorTitle": {
    "message": "Обрана область є замалою"
  },
  "privateWindowErrorTitle": {
    "message": "Знімки екрану вимкнено в приватному перегляді"
  },
  "privateWindowErrorDetails": {
    "message": "Вибачте за незручності. Ми працюємо над цією функцією для майбутніх випусків."
  },
  "genericErrorTitle": {
    "message": "Оу! З Firefox Screenshots щось негаразд."
  },
  "genericErrorDetails": {
    "message": "Ми не впевнені, в чому проблема. Спробувати ще раз, або ж зробити знімок іншої сторінки?"
  },
  "tourBodyOne": {
    "message": "Робіть знімки екрану, зберігайте та діліться ними прямо в Firefox."
  },
  "tourHeaderTwo": {
    "message": "Робіть знімки чого завгодно"
  },
  "tourBodyTwo": {
    "message": "Клацніть і потягніть мишею для захоплення частини сторінки. Ви також можете навести курсор миші для підсвічення вибраної області."
  },
  "tourHeaderThree": {
    "message": "Захоплюйте вікна або цілі сторінки"
  },
  "tourBodyThree": {
    "message": "За допомогою кнопок у верхній правій частині обирайте захоплення видимої області вікна, або сторінки повністю."
  },
  "tourHeaderFour": {
    "message": "Як вам подобається"
  },
  "tourBodyFour": {
    "message": "Зберігайте свої знімки в Інтернеті, щоб легко ними ділитися, або завантажуйте їх на свій комп'ютер. Ви також можете переглянути всі збережені знімки, натиснувши на кнопку Мої знімки."
  },
  "tourSkip": {
    "message": "Пропустити"
  },
  "tourNext": {
    "message": "Наступний слайд"
  },
  "tourPrevious": {
    "message": "Попередній слайд"
  },
  "tourDone": {
    "message": "Готово"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "Використовуючи Firefox Screenshots, ви погоджуєтеся з умовами хмарних послуг Firefox: $TERMSANDPRIVACYNOTICETERMSLINK$ та $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Умовами використання"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Повідомленням про приватність"
  }
}PK
!<.[=ll&webextension/_locales/ur/messages.json{
  "addonDescription": {
    "message": "ویب سے کللبس یاا اسکرین شاٹیں لیں اور ان کو عارظی یا مستقل طور پر محفوظ کریں۔"
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "ایک سکرین شاٹ لیں"
  },
  "myShotsLink": {
    "message": "میری شاٹس"
  },
  "screenshotInstructions": {
    "message": "علاقہ منتخب کرنے کے لیئے گھسیٹیں یا صفحہ پر کلک کریں۔ منسوخ کرنے کے لیئے ESC دبائیں۔"
  },
  "saveScreenshotSelectedArea": {
    "message": "محفوظ کریں"
  },
  "saveScreenshotVisibleArea": {
    "message": "مرئی محفوظ کریں"
  },
  "saveScreenshotFullPage": {
    "message": "پورا صفحہ محفوظ کریں"
  },
  "cancelScreenshot": {
    "message": "منسوخ کریں"
  },
  "downloadScreenshot": {
    "message": "ڈاؤن لوڈ"
  },
  "notificationLinkCopiedTitle": {
    "message": "تبط نقل کر دیا گیا"
  },
  "notificationLinkCopiedDetails": {
    "message": "آُپ کی شاٹس کا ربط و تختہ تراشہ پر نقل کر دیا گیا ہے۔ چسپاں کرنے کے لیئے $META_KEY$-V دبائِں۔",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "خراب ہے۔"
  },
  "requestErrorDetails": {
    "message": "معاف کیجیئے گا! ہم آپ کی شاٹ محفوظ نہیں کر سکے۔ براہ مہربانی کچھ دیر بعد کوشش کریں۔"
  },
  "connectionErrorTitle": {
    "message": "ہم آپ کی اسکرین شاٹس سے نہیں جڑ سکتے۔"
  },
  "connectionErrorDetails": {
    "message": "براہ مہربانی اپنے انٹرنیٹ کنکشن کی پڑتال کریں۔ اگر آپ انٹرنیٹ سے جڑنے کے قابل ہیں، تو شاید Firefox اسکرین شاٹ خدمات کے ساتھ عارظی مسلہ ہو۔"
  },
  "loginErrorDetails": {
    "message": "ہم آُپ کی شاٹ محفوظ نہیں کر سکے کیونکہ Firefox اسکرین شاٹ خدمت کے ساتھ مسلہ ہے۔ براہ مہربانی کچھ دیربعد کوشش کیجیئے۔"
  },
  "unshootablePageErrorTitle": {
    "message": "ہم اس صفحہ کی اسکرین شاٹ نہیں کر سکتے۔"
  },
  "unshootablePageErrorDetails": {
    "message": "یہ ایک میعاری صفحہ نہہیں، تو آپ اسکی اسکرین شاٹ نہیں لے سکتے۔"
  },
  "selfScreenshotErrorTitle": {
    "message": "آپ Firefox اسکرین شاٹس صفحے! کی ایک شاٹ نہیں لے سکت"
  },
  "emptySelectionErrorTitle": {
    "message": "آپ کا انتخاب بہت چھوٹا ہے"
  },
  "genericErrorTitle": {
    "message": "لاجواب! Firefox Screenshots بہت مشہور ہو گیا۔"
  },
  "genericErrorDetails": {
    "message": "ہمیں یقین نہیں کہ کیا ہوا تھا۔ خیال رکھ کر پھر کوشش کریں یا بھر مختلف صفحہ کی تصویرلیں؟"
  },
  "tourBodyOne": {
    "message": "۔Firefox کو چھوڑے بغیر اسکرینشاٹس لیں، محفوظ کریں اور شیئر کریں۔"
  },
  "tourHeaderTwo": {
    "message": "جو آپ چاہتے ہیں وہ گرفت کریں"
  },
  "tourBodyTwo": {
    "message": "صفحہ کا ایک حصہ گرفت کرنے کے لیئے گھسیتیں اور کلک کریں.آُپ اپنے انتخاب کو نمایاں کرنے کے لیئے منڈلا سکتے ہیں۔"
  },
  "tourHeaderThree": {
    "message": "دریچہ ہا مکمل صفحہ گرفت کریں"
  },
  "tourBodyThree": {
    "message": "دریچہ میں نظر آنے والے علاقے یا مکمل صفحہ کو گرفت کرنے کے لیئے بالائی دائیں جانب بٹن کا انتخاب کریں۔"
  },
  "tourHeaderFour": {
    "message": "جس طرح آپ کو پسند ہے"
  },
  "tourBodyFour": {
    "message": "اپنے کمپیوٹڑ میں ڈائونلوڈ کرنے یا ویب پر آسانی سے شیئر کرنے کے لیئےاپنی کتری ہوئی شاٹس محفوظ کریں۔ آپ میری شاٹس کے بٹن پ کلک کر کے بھی اتمام پنی لی گئی شاٹس ڈھّونڈ سکتےہیں۔"
  },
  "tourSkip": {
    "message": "اچٹیں"
  },
  "tourNext": {
    "message": "اگلى سلائيڈ"
  },
  "tourPrevious": {
    "message": "پچھلی سلائڈ"
  },
  "tourDone": {
    "message": "ہوگیا"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "۔Firefox Screenshots کے استعمال کے ساتھ  آپ Firefox Cloud Services کے $TERMSANDPRIVACYNOTICETERMSLINK$ اور $TERMSANDPRIVACYNOTICEPRIVACYLINK$ کے ساتھ متفق ہیں۔",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "شرائط"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "اطلاع نامہ نجی نوعیت"
  }
}PK
!<ó\&webextension/_locales/uz/messages.json{
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Rasmini olish"
  },
  "myShotsLink": {
    "message": "Rasmlarim"
  },
  "screenshotInstructions": {
    "message": "Hududni belgilash uchun sahifa ustiga tashlang yoki bosing. Chiqish uchun “ESC” tugmasidan foydalaning."
  },
  "saveScreenshotSelectedArea": {
    "message": "Saqlash"
  },
  "saveScreenshotVisibleArea": {
    "message": "Ko‘rinadiganini saqlash"
  },
  "saveScreenshotFullPage": {
    "message": "To‘liq sahifani saqlash"
  },
  "cancelScreenshot": {
    "message": "Bekor qilish"
  },
  "downloadScreenshot": {
    "message": "Yuklab olish"
  },
  "notificationLinkCopiedTitle": {
    "message": "Havoladan nusxa olindi"
  },
  "notificationLinkCopiedDetails": {
    "message": "Rasm havolasidan maxsus xotiraga nusxa olindi. Qo‘yish uchun $META_KEY$-V tugmalarini bosing.",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "Xizmat hozircha ishlamayapti"
  },
  "requestErrorDetails": {
    "message": "Uzr! Rasmni saqlay olmaymiz. Keyinroq urinib ko‘ring."
  },
  "connectionErrorTitle": {
    "message": "Ekran rasmiga ulana olmadik."
  },
  "connectionErrorDetails": {
    "message": "Internetga ulanishni tekshiring. Ulana olsangiz, demak Firefox Screenshot xizmatida vaqtinchalik muammo bo‘lishi mumkin."
  },
  "loginErrorDetails": {
    "message": "Olingan rasmni saqlay olmaymiz, chunki Firefox Screenshot xizmatida muammo mavjud. Keyinroq urinib ko‘ring."
  },
  "unshootablePageErrorTitle": {
    "message": "Bu sahifani rasmga tushira olmaymiz."
  },
  "unshootablePageErrorDetails": {
    "message": "Bu sahifa standart sahifa emas, shuning uchun uni rasmga tushira olmaymiz."
  },
  "selfScreenshotErrorTitle": {
    "message": "Firefox Screenshot sahifasini rasmga tushirish mumkin emas!"
  }
}PK
!<z99&webextension/_locales/vi/messages.json{
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "Chụp ảnh màn hình"
  },
  "myShotsLink": {
    "message": "Các ảnh chụp của tôi"
  },
  "saveScreenshotSelectedArea": {
    "message": "Lưu lại"
  },
  "saveScreenshotVisibleArea": {
    "message": "Lưu phần nhìn thấy"
  },
  "saveScreenshotFullPage": {
    "message": "Lưu toàn trang"
  },
  "cancelScreenshot": {
    "message": "Hủy bỏ"
  },
  "downloadScreenshot": {
    "message": "Tải xuống"
  },
  "notificationLinkCopiedTitle": {
    "message": "Đã sao chép liên kết"
  },
  "tourHeaderFour": {
    "message": "Như bạn thích"
  },
  "tourSkip": {
    "message": "SKIP"
  },
  "tourNext": {
    "message": "Slide tiếp theo"
  },
  "tourPrevious": {
    "message": "Slide trước đó"
  },
  "tourDone": {
    "message": "Xong"
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "Điều khoản"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "Chính sách riêng tư"
  }
}PK
!<z'-)webextension/_locales/zh_CN/messages.json{
  "addonDescription": {
    "message": "截取网页截图,可临时或永久存储。"
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "截图"
  },
  "myShotsLink": {
    "message": "我的截图"
  },
  "screenshotInstructions": {
    "message": "在页面上拖拽或单击即可选择要截图的区域。按 ESC 键可取消。"
  },
  "saveScreenshotSelectedArea": {
    "message": "保存"
  },
  "saveScreenshotVisibleArea": {
    "message": "截取可见范围"
  },
  "saveScreenshotFullPage": {
    "message": "截取整个页面"
  },
  "cancelScreenshot": {
    "message": "取消"
  },
  "downloadScreenshot": {
    "message": "下载"
  },
  "notificationLinkCopiedTitle": {
    "message": "链接已复制"
  },
  "notificationLinkCopiedDetails": {
    "message": "您的截图的链接已复制到剪贴板。按 $META_KEY$-V 可粘贴。",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "出故障了。"
  },
  "requestErrorDetails": {
    "message": "很抱歉,我们无法为您保存截图。请稍后再试。"
  },
  "connectionErrorTitle": {
    "message": "我们无法连接到您的截图。"
  },
  "connectionErrorDetails": {
    "message": "请检查您的互联网连接。如果您正常连接到互联网,可能是 Firefox Screenshots 的服务器临时出了问题。"
  },
  "loginErrorDetails": {
    "message": "Firefox Screenshots 服务遇到问题,我们现在无法保存您的截图。请稍后再试。"
  },
  "unshootablePageErrorTitle": {
    "message": "我们无法截图此页面。"
  },
  "unshootablePageErrorDetails": {
    "message": "这不是一个标准的网页,所以无法截图。"
  },
  "selfScreenshotErrorTitle": {
    "message": "您不能截取 Firefox Screenshots 的页面!"
  },
  "emptySelectionErrorTitle": {
    "message": "您选择的范围太小"
  },
  "privateWindowErrorTitle": {
    "message": "隐私浏览模式下屏幕截图已被禁用"
  },
  "privateWindowErrorDetails": {
    "message": "很抱歉因此带来的不便。我们将在后续版本中提供此功能。"
  },
  "genericErrorTitle": {
    "message": "哎呀,Firefox Screenshots 遇到问题。"
  },
  "genericErrorDetails": {
    "message": "我们不确定发生了什么。您可以再试一次或者试试另一个页面。"
  },
  "tourBodyOne": {
    "message": "截取、保存和分享屏幕截图,无需 Firefox 以外的工具。"
  },
  "tourHeaderTwo": {
    "message": "截取你所需"
  },
  "tourBodyTwo": {
    "message": "单击并拖动以截取页面某个区域。您也可以把光标移到你要的地方,高亮后单击即可截图。"
  },
  "tourHeaderThree": {
    "message": "截取窗口或整个页面"
  },
  "tourBodyThree": {
    "message": "选择右上角的按钮可以截取窗口中的可见区域或者整个页面。"
  },
  "tourHeaderFour": {
    "message": "做您所想"
  },
  "tourBodyFour": {
    "message": "将您裁剪后的截图保存到网上以便共享,或者下载到您的计算机。您也可以点击“我的截图”按钮找到您截取的所有截图。"
  },
  "tourSkip": {
    "message": "跳过"
  },
  "tourNext": {
    "message": "下一页"
  },
  "tourPrevious": {
    "message": "上一页"
  },
  "tourDone": {
    "message": "完成"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "使用 Firefox Screenshots 即代表您同意 Firefox 云服务的$TERMSANDPRIVACYNOTICETERMSLINK$和$TERMSANDPRIVACYNOTICEPRIVACYLINK$。",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "条款"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "隐私声明"
  }
}PK
!<c)webextension/_locales/zh_TW/messages.json{
  "addonDescription": {
    "message": "拍攝網頁的擷圖,可暫時儲存或永久儲存。"
  },
  "addonAuthorsList": {
    "message": "Mozilla <screenshots-feedback@mozilla.com>"
  },
  "contextMenuLabel": {
    "message": "拍攝畫面擷圖"
  },
  "myShotsLink": {
    "message": "我的擷圖"
  },
  "screenshotInstructions": {
    "message": "拖曳或點擊頁面來選擇區域,按下 ESC 取消。"
  },
  "saveScreenshotSelectedArea": {
    "message": "儲存"
  },
  "saveScreenshotVisibleArea": {
    "message": "儲存可見範圍"
  },
  "saveScreenshotFullPage": {
    "message": "儲存完整頁面"
  },
  "cancelScreenshot": {
    "message": "取消"
  },
  "downloadScreenshot": {
    "message": "下載"
  },
  "notificationLinkCopiedTitle": {
    "message": "已複製鏈結"
  },
  "notificationLinkCopiedDetails": {
    "message": "已將您拍攝的圖片鏈結複製到剪貼簿,按下 $META_KEY$+V 即可貼上。",
    "placeholders": {
      "meta_key": {
        "content": "$1"
      }
    }
  },
  "requestErrorTitle": {
    "message": "系統維護中。"
  },
  "requestErrorDetails": {
    "message": "抱歉!無法儲存您拍攝的圖片,請稍候再試一次。"
  },
  "connectionErrorTitle": {
    "message": "無法連線至您的畫面擷圖。"
  },
  "connectionErrorDetails": {
    "message": "請檢查您的網路連線。若您可以正常上網,可能是 Firefox Screenshots 臨時出了問題。"
  },
  "loginErrorDetails": {
    "message": "Firefox Screenshots 服務發生問題,我們無法儲存您拍攝的擷圖。請稍候再試。"
  },
  "unshootablePageErrorTitle": {
    "message": "無法幫此頁面拍照。"
  },
  "unshootablePageErrorDetails": {
    "message": "這不是標準的網頁,無法拍照。"
  },
  "selfScreenshotErrorTitle": {
    "message": "您不能幫 Firefox Screenshots 的頁面拍照!"
  },
  "emptySelectionErrorTitle": {
    "message": "您的選擇範圍太小"
  },
  "privateWindowErrorTitle": {
    "message": "隱私瀏覽模式中將停用 Screenshots 套件"
  },
  "privateWindowErrorDetails": {
    "message": "很抱歉帶來不便,我們將在未來提供此功能。"
  },
  "genericErrorTitle": {
    "message": "唉呀,Firefox Screenshots 有點秀逗了。"
  },
  "genericErrorDetails": {
    "message": "我們不確定剛剛發生了什麼事,您可以再試一次,或拍攝其他頁面的擷圖嗎?"
  },
  "tourBodyOne": {
    "message": "不用離開 Firefox 就可以拍攝、儲存、分享畫面擷圖。"
  },
  "tourHeaderTwo": {
    "message": "只拍你想拍的"
  },
  "tourBodyTwo": {
    "message": "點擊並拖曳出要擷取的範圍。或者您也可以用滑鼠移上頁面中的各部分,擷取該範圍。"
  },
  "tourHeaderThree": {
    "message": "擷取可見範圍或整張網頁"
  },
  "tourBodyThree": {
    "message": "透過右上角的不同按鈕來選擇只拍攝視窗中的可見區域,或是整張網頁。"
  },
  "tourHeaderFour": {
    "message": "用您想要的方式分享"
  },
  "tourBodyFour": {
    "message": "裁切過的擷圖,可直接傳到網路上方便分享,也能下載到電腦裡。您也可以點擊「我的擷圖」按鈕,尋找您拍過的所有擷圖。"
  },
  "tourSkip": {
    "message": "略過"
  },
  "tourNext": {
    "message": "下一頁"
  },
  "tourPrevious": {
    "message": "上一頁"
  },
  "tourDone": {
    "message": "完成"
  },
  "termsAndPrivacyNoticeCloudServices": {
    "message": "繼續使用 Firefox Screenshots,代表您同意 Firefox 雲端服務的 $TERMSANDPRIVACYNOTICETERMSLINK$ 以及 $TERMSANDPRIVACYNOTICEPRIVACYLINK$。",
    "placeholders": {
      "termsandprivacynoticetermslink": {
        "content": "$1"
      },
      "termsandprivacynoticeprivacylink": {
        "content": "$2"
      }
    }
  },
  "termsAndPrivacyNoticeTermsLink": {
    "message": "使用條款"
  },
  "termsAndPrivacyNoticyPrivacyLink": {
    "message": "隱私權保護政策"
  }
}PK
!<X\%webextension/assertIsBlankDocument.js/** For use inside an iframe onload function, throws an Error if iframe src is not blank.html

    Should be applied *inside* catcher.watchFunction
*/
this.assertIsBlankDocument = function assertIsBlankDocument(doc) {
  if (doc.documentURI !== browser.extension.getURL("blank.html")) {
    let exc = new Error('iframe URL does not match expected blank.html');
    exc.foundURL = doc.documentURI;
    throw exc;
  }
}
null;
PK
!<i{Bwebextension/assertIsTrusted.js/** For use with addEventListener, assures that any events have event.isTrusted set to true
      https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted
    Should be applied *inside* catcher.watchFunction
*/
this.assertIsTrusted = function assertIsTrusted(handlerFunction) {
  return function(event) {
    if (!event) {
      let exc = new Error("assertIsTrusted did not get an event");
      exc.noPopup = true;
      throw exc;
    }
    if (!event.isTrusted) {
      let exc = new Error(`Received untrusted event (type: ${event.type})`);
      exc.noPopup = true;
      throw exc;
    }
    return handlerFunction.call(this, event);
  };
}
null;
PK
!<Q[		$webextension/background/analytics.js/* globals main, auth, catcher, deviceInfo, communication, log */

"use strict";

this.analytics = (function() {
  let exports = {};

  let telemetryPrefKnown = false;
  let telemetryPref;

  exports.sendEvent = function(action, label, options) {
    let eventCategory = "addon";
    if (!telemetryPrefKnown) {
      log.warn("sendEvent called before we were able to refresh");
      return Promise.resolve();
    }
    if (!telemetryPref) {
      log.info(`Cancelled sendEvent ${eventCategory}/${action}/${label || 'none'} ${JSON.stringify(options)}`);
      return Promise.resolve();
    }
    if (typeof label == "object" && (!options)) {
      options = label;
      label = undefined;
    }
    options = options || {};
    let di = deviceInfo();
    return new Promise((resolve, reject) => {
      let url = main.getBackend() + "/event";
      let req = new XMLHttpRequest();
      req.open("POST", url);
      req.setRequestHeader("content-type", "application/json");
      req.onload = catcher.watchFunction(() => {
        if (req.status >= 300) {
          let exc = new Error("Bad response from POST /event");
          exc.status = req.status;
          exc.statusText = req.statusText;
          reject(exc);
        } else {
          resolve();
        }
      });
      options.applicationName = di.appName;
      options.applicationVersion = di.addonVersion;
      let abTests = auth.getAbTests();
      for (let [gaField, value] of Object.entries(abTests)) {
        options[gaField] = value;
      }
      log.info(`sendEvent ${eventCategory}/${action}/${label || 'none'} ${JSON.stringify(options)}`);
      req.send(JSON.stringify({
        deviceId: auth.getDeviceId(),
        event: eventCategory,
        action,
        label,
        options
      }));
    });
  };

  exports.refreshTelemetryPref = function() {
    return communication.sendToBootstrap("getTelemetryPref").then((result) => {
      telemetryPrefKnown = true;
      if (result === communication.NO_BOOTSTRAP) {
        telemetryPref = true;
      } else {
        telemetryPref = result;
      }
    }, (error) => {
      // If there's an error reading the pref, we should assume that we shouldn't send data
      telemetryPrefKnown = true;
      telemetryPref = false;
      throw error;
    });
  };

  exports.getTelemetryPrefSync = function() {
    catcher.watchPromise(exports.refreshTelemetryPref());
    return !!telemetryPref;
  };

  return exports;
})();
PK
!<V&webextension/background/auth.js/* globals log */
/* globals main, makeUuid, deviceInfo, analytics, catcher, buildSettings, communication */

"use strict";

this.auth = (function() {
  let exports = {};

  let registrationInfo;
  let initialized = false;
  let authHeader = null;
  let sentryPublicDSN = null;
  let abTests = {};

  let registrationInfoFetched = catcher.watchPromise(browser.storage.local.get(["registrationInfo", "abTests"]).then((result) => {
    if (result.abTests) {
      abTests = result.abTests;
    }
    if (result.registrationInfo) {
      registrationInfo = result.registrationInfo;
    } else {
      registrationInfo = generateRegistrationInfo();
      log.info("Generating new device authentication ID", registrationInfo);
      return browser.storage.local.set({registrationInfo});
    }
  }));

  exports.getDeviceId = function() {
    return registrationInfo && registrationInfo.deviceId;
  };

  function generateRegistrationInfo() {
    let info = {
      deviceId: `anon${makeUuid()}`,
      secret: makeUuid(),
      registered: false
    };
    return info;
  }

  function register() {
    return new Promise((resolve, reject) => {
      let registerUrl = main.getBackend() + "/api/register";
      // TODO: replace xhr with Fetch #2261
      let req = new XMLHttpRequest();
      req.open("POST", registerUrl);
      req.setRequestHeader("content-type", "application/json");
      req.onload = catcher.watchFunction(() => {
        if (req.status == 200) {
          log.info("Registered login");
          initialized = true;
          saveAuthInfo(JSON.parse(req.responseText));
          resolve(true);
          analytics.sendEvent("registered");
        } else {
          analytics.sendEvent("register-failed", `bad-response-${req.status}`);
          log.warn("Error in response:", req.responseText);
          let exc = new Error("Bad response: " + req.status);
          exc.popupMessage = "LOGIN_ERROR";
          reject(exc);
        }
      });
      req.onerror = catcher.watchFunction(() => {
        analytics.sendEvent("register-failed", "connection-error");
        let exc = new Error("Error contacting server");
        exc.popupMessage = "LOGIN_CONNECTION_ERROR";
        reject(exc);
      });
      req.send(JSON.stringify({
        deviceId: registrationInfo.deviceId,
        secret: registrationInfo.secret,
        deviceInfo: JSON.stringify(deviceInfo())
      }));
    });
  }

  function login(options) {
    let { ownershipCheck, noRegister } = options || {};
    return new Promise((resolve, reject) => {
      let loginUrl = main.getBackend() + "/api/login";
      // TODO: replace xhr with Fetch #2261
      let req = new XMLHttpRequest();
      req.open("POST", loginUrl);
      req.onload = catcher.watchFunction(() => {
        if (req.status == 404) {
          if (noRegister) {
            resolve(false);
          } else {
            resolve(register());
          }
        } else if (req.status >= 300) {
          log.warn("Error in response:", req.responseText);
          let exc = new Error("Could not log in: " + req.status);
          exc.popupMessage = "LOGIN_ERROR";
          analytics.sendEvent("login-failed", `bad-response-${req.status}`);
          reject(exc);
        } else if (req.status === 0) {
          let error = new Error("Could not log in, server unavailable");
          error.popupMessage = "LOGIN_CONNECTION_ERROR";
          analytics.sendEvent("login-failed", "connection-error");
          reject(error);
        } else {
          initialized = true;
          let jsonResponse = JSON.parse(req.responseText);
          log.info("Screenshots logged in");
          analytics.sendEvent("login");
          saveAuthInfo(jsonResponse);
          if (ownershipCheck) {
            resolve({isOwner: jsonResponse.isOwner});
          } else {
            resolve(true);
          }
        }
      });
      req.onerror = catcher.watchFunction(() => {
        analytics.sendEvent("login-failed", "connection-error");
        let exc = new Error("Connection failed");
        exc.url = loginUrl;
        exc.popupMessage = "CONNECTION_ERROR";
        reject(exc);
      });
      req.setRequestHeader("content-type", "application/json");
      req.send(JSON.stringify({
        deviceId: registrationInfo.deviceId,
        secret: registrationInfo.secret,
        deviceInfo: JSON.stringify(deviceInfo()),
        ownershipCheck
      }));
    });
  }

  function saveAuthInfo(responseJson) {
    if (responseJson.sentryPublicDSN) {
      sentryPublicDSN = responseJson.sentryPublicDSN;
    }
    if (responseJson.authHeader) {
      authHeader = responseJson.authHeader;
      if (!registrationInfo.registered) {
        registrationInfo.registered = true;
        catcher.watchPromise(browser.storage.local.set({registrationInfo}));
      }
    }
    if (responseJson.abTests) {
      abTests = responseJson.abTests;
      catcher.watchPromise(browser.storage.local.set({abTests}));
    }
  }

  exports.getDeviceId = function() {
    return registrationInfo.deviceId;
  };

  exports.authHeaders = function() {
    let initPromise = Promise.resolve();
    if (!initialized) {
      initPromise = login();
    }
    return initPromise.then(() => {
      if (authHeader) {
        return {"x-screenshots-auth": authHeader};
      }
      log.warn("No auth header available");
      return {};
    });
  };

  exports.getSentryPublicDSN = function() {
    return sentryPublicDSN || buildSettings.defaultSentryDsn;
  };

  exports.getAbTests = function() {
    return abTests;
  };

  exports.isRegistered = function() {
    return registrationInfo.registered;
  };

  exports.setDeviceInfoFromOldAddon = function(newDeviceInfo) {
    return registrationInfoFetched.then(() => {
      if (!(newDeviceInfo.deviceId && newDeviceInfo.secret)) {
        throw new Error("Bad deviceInfo");
      }
      if (registrationInfo.deviceId === newDeviceInfo.deviceId &&
        registrationInfo.secret === newDeviceInfo.secret) {
        // Probably we already imported the information
        return Promise.resolve(false);
      }
      registrationInfo = {
        deviceId: newDeviceInfo.deviceId,
        secret: newDeviceInfo.secret,
        registered: true
      };
      initialized = false;
      return browser.storage.local.set({registrationInfo}).then(() => {
        return true;
      });
    });
  };

  communication.register("getAuthInfo", (sender, ownershipCheck) => {
    return registrationInfoFetched.then(() => {
      let info = registrationInfo;
      if (info.registered) {
        return login({ownershipCheck}).then((result) => {
          return {isOwner: result && result.isOwner, deviceId: registrationInfo.deviceId};
        });
      }
      return info;
    });
  });

  return exports;
})();
PK
!<7

(webextension/background/communication.js/* globals catcher, log */

"use strict";

this.communication = (function() {
  let exports = {};

  let registeredFunctions = {};

  exports.onMessage = catcher.watchFunction((req, sender, sendResponse) => {
    if (!(req.funcName in registeredFunctions)) {
      log.error(`Received unknown internal message type ${req.funcName}`);
      sendResponse({type: "error", name: "Unknown message type"});
      return;
    }
    if (!Array.isArray(req.args)) {
      log.error("Received message with no .args list");
      sendResponse({type: "error", name: "No .args"});
      return;
    }
    let func = registeredFunctions[req.funcName];
    let result;
    try {
      req.args.unshift(sender);
      result = func.apply(null, req.args);
    } catch (e) {
      log.error(`Error in ${req.funcName}:`, e, e.stack);
      // FIXME: should consider using makeError from catcher here:
      sendResponse({type: "error", message: e + "", errorCode: e.errorCode, popupMessage: e.popupMessage});
      return;
    }
    if (result && result.then) {
      result.then((concreteResult) => {
        sendResponse({type: "success", value: concreteResult});
      }).catch((errorResult) => {
        log.error(`Promise error in ${req.funcName}:`, errorResult, errorResult && errorResult.stack);
        sendResponse({type: "error", message: errorResult + "", errorCode: errorResult.errorCode, popupMessage: errorResult.popupMessage});
      });
      return true;
    }
    sendResponse({type: "success", value: result});
  });

  exports.register = function(name, func) {
    registeredFunctions[name] = func;
  };

  /** Send a message to bootstrap.js
      Technically any worker can listen to this.  If the bootstrap wrapper is not in place, then this
      will *not* fail, and will return a value of exports.NO_BOOTSTRAP  */
  exports.sendToBootstrap = function(funcName, ...args) {
    return browser.runtime.sendMessage({funcName, args}).then((result) => {
      if (result.type === "success") {
        return result.value;
      }
      throw new Error(`Error in ${funcName}: ${result.name || 'unknown'}`);
    }, (error) => {
      if (isBootstrapMissingError(error)) {
        return exports.NO_BOOTSTRAP;
      }
      throw error;
    });
  };

  function isBootstrapMissingError(error) {
    // Note: some of this logic is copied into startBackground.js's getOldDeviceInfo call
    if (!error) {
      return false;
    }
    return ('errorCode' in error && error.errorCode === "NO_RECEIVING_END") ||
      (!error.errorCode && error.message === "Could not establish connection. Receiving end does not exist.");
  }


  // A singleton/sentinel (with a name):
  exports.NO_BOOTSTRAP = {name: "communication.NO_BOOTSTRAP"};

  return exports;
})();
PK
!<~%webextension/background/deviceInfo.js/* globals catcher */

"use strict";

this.deviceInfo = (function() {
  let manifest = browser.runtime.getManifest();

  let platformInfo = {};
  catcher.watchPromise(browser.runtime.getPlatformInfo().then((info) => {
    platformInfo = info;
  }));

  return function deviceInfo() {
    let match = navigator.userAgent.match(/Chrom(?:e|ium)\/([0-9\.]{1,1000})/);
    let chromeVersion = match ? match[1] : null;
    match = navigator.userAgent.match(/Firefox\/([0-9\.]{1,1000})/);
    let firefoxVersion = match ? match[1] : null;
    let appName = chromeVersion ? "chrome" : "firefox";

    return {
      addonVersion: manifest.version,
      platform: platformInfo.os,
      architecture: platformInfo.arch,
      version: firefoxVersion || chromeVersion,
      // These don't seem to apply to Chrome:
      // build: system.build,
      // platformVersion: system.platformVersion,
      userAgent: navigator.userAgent,
      appVendor: appName,
      appName
    };
  };

})();
PK
!<.]((webextension/background/main.js/* globals selectorLoader, analytics, communication, catcher, log, makeUuid, auth, senderror */

"use strict";

this.main = (function() {
  let exports = {};

  const pasteSymbol = (window.navigator.platform.match(/Mac/i)) ? "\u2318" : "Ctrl";
  const { sendEvent } = analytics;

  let manifest = browser.runtime.getManifest();
  let backend;

  let hasSeenOnboarding;

  browser.storage.local.get(["hasSeenOnboarding"]).then((result) => {
    hasSeenOnboarding = !!result.hasSeenOnboarding;
    if (!hasSeenOnboarding) {
      setIconActive(false, null);
      // Note that the branded name 'Firefox Screenshots' is not localized:
      browser.browserAction.setTitle({
        title: "Firefox Screenshots"
      });
    }
  }).catch((error) => {
    log.error("Error getting hasSeenOnboarding:", error);
  });

  exports.setBackend = function(newBackend) {
    backend = newBackend;
    backend = backend.replace(/\/*$/, "");
  };

  exports.getBackend = function() {
    return backend;
  };

  communication.register("getBackend", () => {
    return backend;
  });

  function getOnboardingUrl() {
    return backend + "/#hello";
  }

  for (let permission of manifest.permissions) {
    if (/^https?:\/\//.test(permission)) {
      exports.setBackend(permission);
      break;
    }
  }

  function setIconActive(active, tabId) {
    let path = active ? "icons/icon-highlight-32-v2.svg" : "icons/icon-32-v2.svg";
    if ((!hasSeenOnboarding) && !active) {
      path = "icons/icon-starred-32-v2.svg";
    }
    browser.browserAction.setIcon({path, tabId}).catch((error) => {
      // FIXME: use errorCode
      if (error.message && /Invalid tab ID/.test(error.message)) {
        // This is a normal exception that we can ignore
      } else {
        catcher.unhandled(error);
      }
    });
  }

  function toggleSelector(tab) {
    return analytics.refreshTelemetryPref()
      .then(() => selectorLoader.toggle(tab.id, hasSeenOnboarding))
      .then(active => {
        setIconActive(active, tab.id);
        return active;
      })
      .catch((error) => {
        if (error.message && /Missing host permission for the tab/.test(error.message)) {
          error.noReport = true;
        }
        error.popupMessage = "UNSHOOTABLE_PAGE";
        throw error;
      });
  }

  function startSelectionWithOnboarding(tab) {
    return analytics.refreshTelemetryPref().then(() => {
      return selectorLoader.testIfLoaded(tab.id);
    }).then((isLoaded) => {
      if (!isLoaded) {
        sendEvent("start-shot", "site-request");
        setIconActive(true, tab.id);
        selectorLoader.toggle(tab.id, false);
      }
    });
  }

  function shouldOpenMyShots(url) {
    return /^about:(?:newtab|blank)/i.test(url) || /^resource:\/\/activity-streams\//i.test(url);
  }

  // This is called by startBackground.js, directly in response to browser.browserAction.onClicked
  exports.onClicked = catcher.watchFunction((tab) => {
    if (tab.incognito) {
      senderror.showError({
        popupMessage: "PRIVATE_WINDOW"
      });
      return;
    }
    if (shouldOpenMyShots(tab.url)) {
      if (!hasSeenOnboarding) {
        catcher.watchPromise(analytics.refreshTelemetryPref().then(() => {
          sendEvent("goto-onboarding", "selection-button");
          return forceOnboarding();
        }));
        return;
      }
      catcher.watchPromise(analytics.refreshTelemetryPref().then(() => {
        sendEvent("goto-myshots", "about-newtab");
      }));
      catcher.watchPromise(
        auth.authHeaders()
        .then(() => browser.tabs.update({url: backend + "/shots"})));
    } else {
      catcher.watchPromise(
        toggleSelector(tab)
          .then(active => {
            const event = active ? "start-shot" : "cancel-shot";
            sendEvent(event, "toolbar-button");
          }, (error) => {
            if ((!hasSeenOnboarding) && error.popupMessage == "UNSHOOTABLE_PAGE") {
              sendEvent("goto-onboarding", "selection-button");
              return forceOnboarding();
            }
            throw error;
          }));
    }
  });

  function forceOnboarding() {
    return browser.tabs.create({url: getOnboardingUrl()});
  }

  exports.onClickedContextMenu = catcher.watchFunction((info, tab) => {
    if (!tab) {
      // Not in a page/tab context, ignore
      return;
    }
    if (tab.incognito) {
      senderror.showError({
        popupMessage: "PRIVATE_WINDOW"
      });
      return;
    }
    if (!urlEnabled(tab.url)) {
      senderror.showError({
        popupMessage: "UNSHOOTABLE_PAGE"
      });
      return;
    }
    catcher.watchPromise(
      toggleSelector(tab)
        .then(() => sendEvent("start-shot", "context-menu")));
  });

  function urlEnabled(url) {
    if (shouldOpenMyShots(url)) {
      return true;
    }
    if (isShotOrMyShotPage(url) || /^(?:about|data|moz-extension):/i.test(url) || isBlacklistedUrl(url)) {
      return false;
    }
    return true;
  }

  function isShotOrMyShotPage(url) {
    // It's okay to take a shot of any pages except shot pages and My Shots
    if (!url.startsWith(backend)) {
      return false;
    }
    let path = url.substr(backend.length).replace(/^\/*/, "").replace(/[?#].*/, "");
    if (path == "shots") {
      return true;
    }
    if (/^[^/]{1,4000}\/[^/]{1,4000}$/.test(path)) {
      // Blocks {:id}/{:domain}, but not /, /privacy, etc
      return true;
    }
    return false;
  }

  function isBlacklistedUrl(url) {
    // These specific domains are not allowed for general WebExtension permission reasons
    // Discussion: https://bugzilla.mozilla.org/show_bug.cgi?id=1310082
    // List of domains copied from: https://dxr.mozilla.org/mozilla-central/source/browser/app/permissions#18-19
    // Note we disable it here to be informative, the security check is done in WebExtension code
    const badDomains = ["addons.mozilla.org", "testpilot.firefox.com"];
    let domain = url.replace(/^https?:\/\//i, "");
    domain = domain.replace(/\/.*/, "").replace(/:.*/, "");
    domain = domain.toLowerCase();
    return badDomains.includes(domain);
  }

  communication.register("sendEvent", (sender, ...args) => {
    catcher.watchPromise(sendEvent(...args));
    // We don't wait for it to complete:
    return null;
  });

  communication.register("openMyShots", (sender) => {
    return catcher.watchPromise(
      auth.authHeaders()
      .then(() => browser.tabs.create({url: backend + "/shots"})));
  });

  communication.register("openShot", (sender, {url, copied}) => {
    if (copied) {
      const id = makeUuid();
      return browser.notifications.create(id, {
        type: "basic",
        iconUrl: "../icons/copy.png",
        title: browser.i18n.getMessage("notificationLinkCopiedTitle"),
        message: browser.i18n.getMessage("notificationLinkCopiedDetails", pasteSymbol)
      });
    }
  });

  communication.register("downloadShot", (sender, info) => {
    // 'data:' urls don't work directly, let's use a Blob
    // see http://stackoverflow.com/questions/40269862/save-data-uri-as-file-using-downloads-download-api
    const binary = atob(info.url.split(',')[1]); // just the base64 data
    const data = Uint8Array.from(binary, char => char.charCodeAt(0))
    const blob = new Blob([data], {type: "image/png"})
    let url = URL.createObjectURL(blob);
    let downloadId;
    let onChangedCallback = catcher.watchFunction(function(change) {
      if (!downloadId || downloadId != change.id) {
        return;
      }
      if (change.state && change.state.current != "in_progress") {
        URL.revokeObjectURL(url);
        browser.downloads.onChanged.removeListener(onChangedCallback);
      }
    });
    browser.downloads.onChanged.addListener(onChangedCallback)
    return browser.downloads.download({
      url,
      filename: info.filename
    }).then((id) => {
      downloadId = id;
    });
  });

  communication.register("closeSelector", (sender) => {
    setIconActive(false, sender.tab.id);
  });

  catcher.watchPromise(communication.sendToBootstrap("getOldDeviceInfo").then((deviceInfo) => {
    if (deviceInfo === communication.NO_BOOTSTRAP || !deviceInfo) {
      return;
    }
    deviceInfo = JSON.parse(deviceInfo);
    if (deviceInfo && typeof deviceInfo == "object") {
      return auth.setDeviceInfoFromOldAddon(deviceInfo).then((updated) => {
        if (updated === communication.NO_BOOTSTRAP) {
          throw new Error("bootstrap.js disappeared unexpectedly");
        }
        if (updated) {
          return communication.sendToBootstrap("removeOldAddon");
        }
      });
    }
  }));

  communication.register("hasSeenOnboarding", () => {
    hasSeenOnboarding = true;
    catcher.watchPromise(browser.storage.local.set({hasSeenOnboarding}));
    setIconActive(false, null);
    browser.browserAction.setTitle({
      title: browser.i18n.getMessage("contextMenuLabel")
    });
  });

  communication.register("abortFrameset", () => {
    sendEvent("abort-start-shot", "frame-page");
    // Note, we only show the error but don't report it, as we know that we can't
    // take shots of these pages:
    senderror.showError({
      popupMessage: "UNSHOOTABLE_PAGE"
    });
  });

  communication.register("abortNoDocumentBody", (sender, tagName) => {
    tagName = String(tagName || "").replace(/[^a-z0-9]/ig, "");
    sendEvent("abort-start-shot", `document-is-${tagName}`);
    // Note, we only show the error but don't report it, as we know that we can't
    // take shots of these pages:
    senderror.showError({
      popupMessage: "UNSHOOTABLE_PAGE"
    });
  });

  // Note: this signal is only needed until bug 1357589 is fixed.
  communication.register("openTermsPage", () => {
    return catcher.watchPromise(browser.tabs.create({url: "https://www.mozilla.org/about/legal/terms/services/"}));
  });

  // Note: this signal is also only needed until bug 1357589 is fixed.
  communication.register("openPrivacyPage", () => {
    return catcher.watchPromise(browser.tabs.create({url: "https://www.mozilla.org/privacy/firefox-cloud/"}));
  });

  // A Screenshots page wants us to start/force onboarding
  communication.register("requestOnboarding", (sender) => {
    return startSelectionWithOnboarding(sender.tab);
  });

  return exports;
})();
PK
!<)webextension/background/selectorLoader.js/* globals catcher, log */

"use strict";

var global = this;

this.selectorLoader = (function() {
  const exports = {};

  // These modules are loaded in order, first standardScripts, then optionally onboardingScripts, and then selectorScripts
  // The order is important due to dependencies
  const standardScripts = [
    "build/buildSettings.js",
    "log.js",
    "catcher.js",
    "assertIsTrusted.js",
    "assertIsBlankDocument.js",
    "background/selectorLoader.js",
    "selector/callBackground.js",
    "selector/util.js"
  ];

  const selectorScripts = [
    "clipboard.js",
    "makeUuid.js",
    "build/shot.js",
    "randomString.js",
    "domainFromUrl.js",
    "build/inlineSelectionCss.js",
    "selector/documentMetadata.js",
    "selector/ui.js",
    "selector/shooter.js",
    "selector/uicontrol.js"
  ];

  // These are loaded on request (by the selector worker) to activate the onboarding:
  const onboardingScripts = [
    "build/onboardingCss.js",
    "build/onboardingHtml.js",
    "onboarding/slides.js"
  ];

  exports.unloadIfLoaded = function(tabId) {
    return browser.tabs.executeScript(tabId, {
      code: "this.selectorLoader && this.selectorLoader.unloadModules()",
      runAt: "document_start"
    }).then(result => {
      return result && result[0];
    });
  };

  exports.testIfLoaded = function(tabId) {
    if (loadingTabs.has(tabId)) {
      return true;
    }
    return browser.tabs.executeScript(tabId, {
      code: "!!this.selectorLoader",
      runAt: "document_start"
    }).then(result => {
      return result && result[0];
    });
  };

  let loadingTabs = new Set();

  exports.loadModules = function(tabId, hasSeenOnboarding) {
    let promise;
    loadingTabs.add(tabId);
    if (hasSeenOnboarding) {
      promise = executeModules(tabId, standardScripts.concat(selectorScripts));
    } else {
      promise = executeModules(tabId, standardScripts.concat(onboardingScripts).concat(selectorScripts));
    }
    return promise.then((result) => {
      loadingTabs.delete(tabId);
      return result;
    }, (error) => {
      loadingTabs.delete(tabId);
      throw error;
    });
  };

  function executeModules(tabId, scripts) {
    let lastPromise = Promise.resolve(null);
    scripts.forEach((file) => {
      lastPromise = lastPromise.then(() => {
        return browser.tabs.executeScript(tabId, {
          file,
          runAt: "document_end"
        }).catch((error) => {
          log.error("error in script:", file, error);
          error.scriptName = file;
          throw error;
        });
      });
    });
    return lastPromise.then(() => {
      log.debug("finished loading scripts:", scripts.join(" "));
    },
    (error) => {
      exports.unloadIfLoaded(tabId);
      catcher.unhandled(error);
      throw error;
    });
  }

  exports.unloadModules = function() {
    const watchFunction = catcher.watchFunction;
    let allScripts = standardScripts.concat(onboardingScripts).concat(selectorScripts);
    const moduleNames = allScripts.map((filename) =>
      filename.replace(/^.*\//, "").replace(/\.js$/, ""));
    moduleNames.reverse();
    for (let moduleName of moduleNames) {
      let moduleObj = global[moduleName];
      if (moduleObj && moduleObj.unload) {
        try {
          watchFunction(moduleObj.unload)();
        } catch (e) {
          // ignore (watchFunction handles it)
        }
      }
      delete global[moduleName];
    }
    return true;
  };

  exports.toggle = function(tabId, hasSeenOnboarding) {
    return exports.unloadIfLoaded(tabId)
      .then(wasLoaded => {
        if (!wasLoaded) {
          exports.loadModules(tabId, hasSeenOnboarding);
        }
        return !wasLoaded;
      })
  };

  return exports;
})();
null;
PK
!<k{]]$webextension/background/senderror.js/* globals analytics, communication, makeUuid, Raven, catcher, auth, log */

"use strict";

const startTime = Date.now();

this.senderror = (function() {
  let exports = {};

  let manifest = browser.runtime.getManifest();

  // Do not show an error more than every ERROR_TIME_LIMIT milliseconds:
  const ERROR_TIME_LIMIT = 3000;

  let messages = {
    REQUEST_ERROR: {
      title: browser.i18n.getMessage("requestErrorTitle"),
      info: browser.i18n.getMessage("requestErrorDetails")
    },
    CONNECTION_ERROR: {
      title: browser.i18n.getMessage("connectionErrorTitle"),
      info: browser.i18n.getMessage("connectionErrorDetails")
    },
    LOGIN_ERROR: {
      title: browser.i18n.getMessage("requestErrorTitle"),
      info: browser.i18n.getMessage("loginErrorDetails")
    },
    LOGIN_CONNECTION_ERROR: {
      title: browser.i18n.getMessage("connectionErrorTitle"),
      info: browser.i18n.getMessage("connectionErrorDetails")
    },
    UNSHOOTABLE_PAGE: {
      title: browser.i18n.getMessage("unshootablePageErrorTitle"),
      info: browser.i18n.getMessage("unshootablePageErrorDetails")
    },
    SHOT_PAGE: {
      title: browser.i18n.getMessage("selfScreenshotErrorTitle")
    },
    MY_SHOTS: {
      title: browser.i18n.getMessage("selfScreenshotErrorTitle")
    },
    EMPTY_SELECTION: {
      title: browser.i18n.getMessage("emptySelectionErrorTitle")
    },
    PRIVATE_WINDOW: {
      title: browser.i18n.getMessage("privateWindowErrorTitle"),
      info: browser.i18n.getMessage("privateWindowErrorDetails")
    },
    generic: {
      title: browser.i18n.getMessage("genericErrorTitle"),
      info: browser.i18n.getMessage("genericErrorDetails"),
      showMessage: true
    }
  };

  communication.register("reportError", (sender, error) => {
    catcher.unhandled(error);
  });

  let lastErrorTime;

  exports.showError = function(error) {
    if (lastErrorTime && (Date.now() - lastErrorTime) < ERROR_TIME_LIMIT) {
      return;
    }
    lastErrorTime = Date.now();
    let id = makeUuid();
    let popupMessage = error.popupMessage || "generic";
    if (!messages[popupMessage]) {
      popupMessage = "generic";
    }
    let title = messages[popupMessage].title;
    let message = messages[popupMessage].info || '';
    let showMessage = messages[popupMessage].showMessage;
    if (error.message && showMessage) {
      if (message) {
        message += "\n" + error.message;
      } else {
        message = error.message;
      }
    }
    if (Date.now() - startTime > 5 * 1000) {
      browser.notifications.create(id, {
        type: "basic",
        // FIXME: need iconUrl for an image, see #2239
        title,
        message
      });
    }
  };

  exports.reportError = function(e) {
    if (!analytics.getTelemetryPrefSync()) {
      log.error("Telemetry disabled. Not sending critical error:", e);
      return;
    }
    let dsn = auth.getSentryPublicDSN();
    if (!dsn) {
      log.warn("Screenshots error:", e);
      return;
    }
    if (!Raven.isSetup()) {
      Raven.config(dsn, {allowSecretKey: true}).install();
    }
    let exception = new Error(e.message);
    exception.stack = e.multilineStack || e.stack || undefined;

    // To improve Sentry reporting & grouping, replace the
    // moz-extension://$uuid base URL with a generic resource:// URL.
    exception.stack = exception.stack.replace(
      /moz-extension:\/\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/g,
      "resource://screenshots-addon"
    );
    let rest = {};
    for (let attr in e) {
      if (!["name", "message", "stack", "multilineStack", "popupMessage", "version", "sentryPublicDSN", "help", "fromMakeError"].includes(attr)) {
        rest[attr] = e[attr];
      }
    }
    rest.stack = exception.stack;
    Raven.captureException(exception, {
      logger: 'addon',
      tags: {category: e.popupMessage},
      release: manifest.version,
      message: exception.message,
      extra: rest
    });
  };

  catcher.registerHandler((errorObj) => {
    if (!errorObj.noPopup) {
      exports.showError(errorObj);
    }
    if (!errorObj.noReport) {
      exports.reportError(errorObj);
    }
  });

  return exports;
})();
PK
!<Z"*webextension/background/startBackground.js/* globals browser, main, communication */
/* This file handles:
     browser.browserAction.onClicked
     browser.contextMenus.onClicked
     browser.runtime.onMessage
   and loads the rest of the background page in response to those events, forwarding
   the events to main.onClicked, main.onClickedContextMenu, or communication.onMessage
*/

this.startBackground = (function() {
  const backgroundScripts = [
    "log.js",
    "makeUuid.js",
    "catcher.js",
    "background/selectorLoader.js",
    "background/communication.js",
    "background/auth.js",
    "background/senderror.js",
    "build/raven.js",
    "build/shot.js",
    "background/analytics.js",
    "background/deviceInfo.js",
    "background/takeshot.js",
    "background/main.js"
  ];

  // Maximum milliseconds to wait before checking for migration possibility
  const CHECK_MIGRATION_DELAY = 2000;

  browser.browserAction.onClicked.addListener((tab) => {
    loadIfNecessary().then(() => {
      main.onClicked(tab);
    }).catch((error) => {
      console.error("Error loading Screenshots:", error);
    });
  });

  browser.contextMenus.create({
    id: "create-screenshot",
    title: browser.i18n.getMessage("contextMenuLabel"),
    contexts: ["page"],
    documentUrlPatterns: ["<all_urls>"]
  });

  browser.contextMenus.onClicked.addListener((info, tab) => {
    loadIfNecessary().then(() => {
      main.onClickedContextMenu(info, tab);
    }).catch((error) => {
      console.error("Error loading Screenshots:", error);
    });
  });

  // Note this duplicates functionality in main.js, but we need to change
  // the onboarding icon before main.js loads up
  browser.storage.local.get(["hasSeenOnboarding"]).then((result) => {
    let hasSeenOnboarding = !!result.hasSeenOnboarding;
    if (!hasSeenOnboarding) {
      let path = "icons/icon-starred-32-v2.svg";
      browser.browserAction.setIcon({path});
    }
  }).catch((error) => {
    console.error("Error loading Screenshots onboarding flag:", error);
  });

  browser.runtime.onMessage.addListener((req, sender, sendResponse) => {
    loadIfNecessary().then(() => {
      return communication.onMessage(req, sender, sendResponse);
    }).catch((error) => {
      console.error("Error loading Screenshots:", error);
    });
    return true;
  });

  // We delay this check (by CHECK_MIGRATION_DELAY) just to avoid piling too
  // many things onto browser/add-on startup
  requestIdleCallback(() => {
    browser.runtime.sendMessage({funcName: "getOldDeviceInfo"}).then((result) => {
      if (result && result.type == "success" && result.value) {
        // There is a possible migration to run, so we'll load the entire background
        // page and continue the process
        return loadIfNecessary();
      }
      if (!result) {
        throw new Error("Got no result from getOldDeviceInfo");
      }
      if (result.type == "error") {
        throw new Error(`Error from getOldDeviceInfo: ${result.name}`);
      }
    }).catch((error) => {
      if (error && error.message == "Could not establish connection. Receiving end does not exist") {
        // Just a missing bootstrap.js, ignore
      } else {
        console.error("Screenshots error checking for Page Shot migration:", error);
      }
    });
  }, {timeout: CHECK_MIGRATION_DELAY});

  let loadedPromise;

  function loadIfNecessary() {
    if (loadedPromise) {
      return loadedPromise;
    }
    loadedPromise = Promise.resolve();
    backgroundScripts.forEach((script) => {
      loadedPromise = loadedPromise.then(() => {
        return new Promise((resolve, reject) => {
          let tag = document.createElement("script");
          tag.src = browser.extension.getURL(script);
          tag.onload = () => {
            resolve();
          };
          tag.onerror = (error) => {
            let exc = new Error(`Error loading script: ${error.message}`);
            exc.scriptName = script;
            reject(exc);
          };
          document.head.appendChild(tag);
        });
      });
    });
    return loadedPromise;
  }

})();
PK
!<ټ#webextension/background/takeshot.js/* globals communication, shot, main, auth, catcher, analytics */

"use strict";

this.takeshot = (function() {
  let exports = {};
  const Shot = shot.AbstractShot;
  const { sendEvent } = analytics;

  communication.register("takeShot", catcher.watchFunction((sender, options) => {
    let { captureType, captureText, scroll, selectedPos, shotId, shot } = options;
    shot = new Shot(main.getBackend(), shotId, shot);
    shot.favicon = sender.tab.favIconUrl;
    let capturePromise = Promise.resolve();
    let openedTab;
    if (!shot.clipNames().length) {
      // canvas.drawWindow isn't available, so we fall back to captureVisibleTab
      capturePromise = screenshotPage(selectedPos, scroll).then((dataUrl) => {
        shot.addClip({
          createdDate: Date.now(),
          image: {
            url: dataUrl,
            captureType,
            text: captureText,
            location: selectedPos,
            dimensions: {
              x: selectedPos.right - selectedPos.left,
              y: selectedPos.bottom - selectedPos.top
            }
          }
        });
      });
    }
    let shotAbTests = {};
    let abTests = auth.getAbTests();
    for (let testName of Object.keys(abTests)) {
      if (abTests[testName].shotField) {
        shotAbTests[testName] = abTests[testName].value;
      }
    }
    if (Object.keys(shotAbTests).length) {
      shot.abTests = shotAbTests;
    }
    return catcher.watchPromise(capturePromise.then(() => {
      return browser.tabs.create({url: shot.creatingUrl})
    }).then((tab) => {
      openedTab = tab;
      return uploadShot(shot);
    }).then(() => {
      return browser.tabs.update(openedTab.id, {url: shot.viewUrl}).then(
        null,
        (error) => {
          // FIXME: If https://bugzilla.mozilla.org/show_bug.cgi?id=1365718 is resolved,
          // use the errorCode added as an additional check:
          if ((/invalid tab id/i).test(error)) {
            // This happens if the tab was closed before the upload completed
            return browser.tabs.create({url: shot.viewUrl});
          }
          throw error;
        }
      );
    }).then(() => {
      return shot.viewUrl;
    }).catch((error) => {
      browser.tabs.remove(openedTab.id);
      throw error;
    }));
  }));

  communication.register("screenshotPage", (sender, selectedPos, scroll) => {
    return screenshotPage(selectedPos, scroll);
  });

  function screenshotPage(pos, scroll) {
    pos = {
      top: pos.top - scroll.scrollY,
      left: pos.left - scroll.scrollX,
      bottom: pos.bottom - scroll.scrollY,
      right: pos.right - scroll.scrollX
    };
    pos.width = pos.right - pos.left;
    pos.height = pos.bottom - pos.top;
    return catcher.watchPromise(browser.tabs.captureVisibleTab(
      null,
      {format: "png"}
    ).then((dataUrl) => {
      let image = new Image();
      image.src = dataUrl;
      return new Promise((resolve, reject) => {
        image.onload = catcher.watchFunction(() => {
          let xScale = image.width / scroll.innerWidth;
          let yScale = image.height / scroll.innerHeight;
          let canvas = document.createElement("canvas");
          canvas.height = pos.height * yScale;
          canvas.width = pos.width * xScale;
          let context = canvas.getContext("2d");
          context.drawImage(
            image,
            pos.left * xScale, pos.top * yScale,
            pos.width * xScale, pos.height * yScale,
            0, 0,
            pos.width * xScale, pos.height * yScale
          );
          let result = canvas.toDataURL();
          resolve(result);
        });
      });
    }));
  }

  function uploadShot(shot) {
    return auth.authHeaders().then((headers) => {
      headers["content-type"] = "application/json";
      let body = JSON.stringify(shot.asJson());
      sendEvent("upload", "started", {eventValue: Math.floor(body.length / 1000)});
      return fetch(shot.jsonUrl, {
        method: "PUT",
        mode: "cors",
        headers,
        body
      });
    }).then((resp) => {
      if (!resp.ok) {
        sendEvent("upload-failed", `status-${resp.status}`);
        let exc = new Error(`Response failed with status ${resp.status}`);
        exc.popupMessage = "REQUEST_ERROR";
        throw exc;
      } else {
        sendEvent("upload", "success");
      }
    }, (error) => {
      // FIXME: I'm not sure what exceptions we can expect
      sendEvent("upload-failed", "connection");
      error.popupMessage = "CONNECTION_ERROR";
      throw error;
    });
  }

  return exports;
})();
PK
!<webextension/blank.html<html></html>
PK
!<\k#webextension/build/buildSettings.jswindow.buildSettings = {
  defaultSentryDsn: "https://904ccdd4866247c092ae8fc1a4764a63:940d44bdc71d4daea133c19080ccd38d@sentry.prod.mozaws.net/224",
  logLevel: "" || "warn",
  captureText: ("" === "true")
};
null;

PK
!<e55(webextension/build/inlineSelectionCss.js/* Created from build/server/static/css/inline-selection.css */
window.inlineSelectionCss = `
.button, .highlight-button-cancel, .highlight-button-save, .highlight-button-download {
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 1px;
  cursor: pointer;
  font-size: 16px;
  font-weight: 400;
  height: 40px;
  min-width: 40px;
  outline: none;
  padding: 0 10px;
  position: relative;
  text-align: center;
  text-decoration: none;
  transition: background 150ms cubic-bezier(0.07, 0.95, 0, 1), border 150ms cubic-bezier(0.07, 0.95, 0, 1);
  user-select: none;
  white-space: nowrap; }
  .button.small, .small.highlight-button-cancel, .small.highlight-button-save, .small.highlight-button-download {
    height: 32px;
    line-height: 32px;
    padding: 0 8px; }
  .button.tiny, .tiny.highlight-button-cancel, .tiny.highlight-button-save, .tiny.highlight-button-download {
    font-size: 14px;
    height: 26px;
    border: 1px solid #c7c7c7; }
    .button.tiny:hover, .tiny.highlight-button-cancel:hover, .tiny.highlight-button-save:hover, .tiny.highlight-button-download:hover, .button.tiny:focus, .tiny.highlight-button-cancel:focus, .tiny.highlight-button-save:focus, .tiny.highlight-button-download:focus {
      background: #ebebeb;
      border-color: #989898; }
    .button.tiny:active, .tiny.highlight-button-cancel:active, .tiny.highlight-button-save:active, .tiny.highlight-button-download:active {
      background: #dedede;
      border-color: #989898; }
  .button.block-button, .block-button.highlight-button-cancel, .block-button.highlight-button-save, .block-button.highlight-button-download {
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    border: none;
    border-right: 1px solid #c7c7c7;
    box-shadow: none;
    border-radius: 0;
    flex-shrink: 0;
    font-size: 20px;
    height: 100px;
    line-height: 100%;
    overflow: hidden; }
    @media (max-width: 719px) {
      .button.block-button, .block-button.highlight-button-cancel, .block-button.highlight-button-save, .block-button.highlight-button-download {
        justify-content: flex-start;
        font-size: 16px;
        height: 72px;
        margin-right: 10px;
        padding: 0 5px; } }
    .button.block-button:hover, .block-button.highlight-button-cancel:hover, .block-button.highlight-button-save:hover, .block-button.highlight-button-download:hover {
      background: #ebebeb; }
    .button.block-button:active, .block-button.highlight-button-cancel:active, .block-button.highlight-button-save:active, .block-button.highlight-button-download:active {
      background: #dedede; }

.inverse-color-scheme {
  background: #3e3d40;
  color: #f5f5f7; }
  .inverse-color-scheme a {
    color: #e1e1e6; }

.default-color-scheme {
  background: #f5f5f7;
  color: #3e3d40; }
  .default-color-scheme a {
    color: #009ec0; }

.highlight-color-scheme {
  background: #009ec0;
  color: #fff; }
  .highlight-color-scheme a {
    color: #fff;
    text-decoration: underline; }

.alt-color-scheme {
  background: #31365A;
  color: #f5f5f7; }
  .alt-color-scheme h1 {
    color: #6F7FB6; }
  .alt-color-scheme a {
    color: #e1e1e6;
    text-decoration: underline; }

.button.primary, .primary.highlight-button-cancel, .highlight-button-save, .primary.highlight-button-download {
  background-color: #009ec0;
  color: #fff; }
  .button.primary:hover, .primary.highlight-button-cancel:hover, .highlight-button-save:hover, .primary.highlight-button-download:hover, .button.primary:focus, .primary.highlight-button-cancel:focus, .highlight-button-save:focus, .primary.highlight-button-download:focus {
    background-color: #00819c; }
  .button.primary:active, .primary.highlight-button-cancel:active, .highlight-button-save:active, .primary.highlight-button-download:active {
    background-color: #006c83; }

.button.secondary, .highlight-button-cancel, .secondary.highlight-button-save, .highlight-button-download {
  background-color: #f5f5f7;
  color: #3e3d40; }
  .button.secondary:hover, .highlight-button-cancel:hover, .secondary.highlight-button-save:hover, .highlight-button-download:hover {
    background-color: #ebebeb; }
  .button.secondary:hover, .highlight-button-cancel:hover, .secondary.highlight-button-save:hover, .highlight-button-download:hover {
    background-color: #dedede; }

.button.transparent, .transparent.highlight-button-cancel, .transparent.highlight-button-save, .transparent.highlight-button-download {
  background-color: transparent;
  color: #3e3d40; }
  .button.transparent:hover, .transparent.highlight-button-cancel:hover, .transparent.highlight-button-save:hover, .transparent.highlight-button-download:hover, .button.transparent:focus, .transparent.highlight-button-cancel:focus, .transparent.highlight-button-save:focus, .transparent.highlight-button-download:focus, .button.transparent:active, .transparent.highlight-button-cancel:active, .transparent.highlight-button-save:active, .transparent.highlight-button-download:active {
    background-color: rgba(0, 0, 0, 0.05); }

.button.warning, .warning.highlight-button-cancel, .warning.highlight-button-save, .warning.highlight-button-download {
  color: #fff;
  background: #d92215; }
  .button.warning:hover, .warning.highlight-button-cancel:hover, .warning.highlight-button-save:hover, .warning.highlight-button-download:hover, .button.warning:focus, .warning.highlight-button-cancel:focus, .warning.highlight-button-save:focus, .warning.highlight-button-download:focus {
    background: #b81d12; }
  .button.warning:active, .warning.highlight-button-cancel:active, .warning.highlight-button-save:active, .warning.highlight-button-download:active {
    background: #a11910; }

.subtitle-link {
  color: #009ec0; }

@keyframes fade-in {
  0% {
    opacity: 0; }
  100% {
    opacity: 1; } }

@keyframes pop {
  0% {
    transform: scale(1); }
  97% {
    transform: scale(1.04); }
  100% {
    transform: scale(1); } }

@keyframes pulse {
  0% {
    opacity: .3;
    transform: scale(1); }
  70% {
    opacity: .25;
    transform: scale(1.04); }
  100% {
    opacity: .3;
    transform: scale(1); } }

@keyframes slide-left {
  0% {
    opacity: 0;
    transform: translate3d(160px, 0, 0); }
  100% {
    opacity: 1;
    transform: translate3d(0, 0, 0); } }

.mover-target {
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: auto;
  position: absolute;
  z-index: 5; }

.highlight,
.mover-target {
  background-color: transparent;
  background-image: none; }

.mover-target,
.bghighlight {
  border: 0; }

.hover-highlight {
  animation: fade-in 125ms forwards cubic-bezier(0.07, 0.95, 0, 1);
  background: rgba(255, 255, 255, 0.2);
  border-radius: 1px;
  pointer-events: none;
  position: absolute;
  z-index: 10000000000; }
  .hover-highlight:before {
    border: 2px dashed rgba(255, 255, 255, 0.4);
    bottom: 0;
    content: '';
    left: 0;
    position: absolute;
    right: 0;
    top: 0; }

.mover-target.direction-topLeft {
  cursor: nwse-resize;
  height: 60px;
  left: -30px;
  top: -30px;
  width: 60px; }

.mover-target.direction-top {
  cursor: ns-resize;
  height: 60px;
  left: 0;
  top: -30px;
  width: 100%;
  z-index: 4; }

.mover-target.direction-topRight {
  cursor: nesw-resize;
  height: 60px;
  right: -30px;
  top: -30px;
  width: 60px; }

.mover-target.direction-left {
  cursor: ew-resize;
  height: 100%;
  left: -30px;
  top: 0;
  width: 60px;
  z-index: 4; }

.mover-target.direction-right {
  cursor: ew-resize;
  height: 100%;
  right: -30px;
  top: 0;
  width: 60px;
  z-index: 4; }

.mover-target.direction-bottomLeft {
  bottom: -30px;
  cursor: nesw-resize;
  height: 60px;
  left: -30px;
  width: 60px; }

.mover-target.direction-bottom {
  bottom: -30px;
  cursor: ns-resize;
  height: 60px;
  left: 0;
  width: 100%;
  z-index: 4; }

.mover-target.direction-bottomRight {
  bottom: -30px;
  cursor: nwse-resize;
  height: 60px;
  right: -30px;
  width: 60px; }

.mover-target:hover .mover {
  transform: scale(1.05); }

.mover {
  background-color: #fff;
  border-radius: 50%;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.5);
  height: 16px;
  opacity: 1;
  position: relative;
  transition: transform 125ms cubic-bezier(0.07, 0.95, 0, 1);
  width: 16px; }
  .small-selection .mover {
    height: 10px;
    width: 10px; }

.direction-topLeft .mover,
.direction-left .mover,
.direction-bottomLeft .mover {
  left: -1px; }

.direction-topLeft .mover,
.direction-top .mover,
.direction-topRight .mover {
  top: -1px; }

.direction-topRight .mover,
.direction-right .mover,
.direction-bottomRight .mover {
  right: -1px; }

.direction-bottomRight .mover,
.direction-bottom .mover,
.direction-bottomLeft .mover {
  bottom: -1px; }

.bghighlight {
  background-color: rgba(0, 0, 0, 0.7);
  position: absolute;
  z-index: 9999999999; }

.preview-overlay {
  align-items: center;
  background-color: rgba(0, 0, 0, 0.7);
  display: flex;
  height: 100%;
  justify-content: center;
  left: 0;
  margin: 0;
  padding: 0;
  position: fixed;
  top: 0;
  width: 100%;
  z-index: 9999999999; }

.highlight {
  border-radius: 2px;
  border: 2px dashed rgba(255, 255, 255, 0.8);
  box-sizing: border-box;
  cursor: move;
  position: absolute;
  z-index: 9999999999; }

.highlight-buttons {
  display: flex;
  align-items: center;
  justify-content: center;
  bottom: -55px;
  position: absolute;
  right: 5px;
  z-index: 6; }
  .bottom-selection .highlight-buttons {
    bottom: 5px; }
  .left-selection .highlight-buttons {
    right: auto;
    left: 5px; }

.highlight-button-cancel {
  background-image: url("MOZ_EXTENSION/icons/cancel.svg");
  background-position: center center;
  background-repeat: no-repeat;
  background-size: 18px 18px;
  border: 1px solid #dedede;
  margin: 5px;
  width: 40px; }

.highlight-button-save {
  background-image: url("MOZ_EXTENSION/icons/cloud.svg");
  background-position: 8px center;
  background-repeat: no-repeat;
  background-size: 20px 18px;
  font-size: 18px;
  margin: 5px;
  min-width: 80px;
  padding-left: 34px; }

.highlight-button-download {
  background-image: url("MOZ_EXTENSION/icons/download.svg");
  background-position: center center;
  background-repeat: no-repeat;
  background-size: 18px 18px;
  border: 1px solid #dedede;
  display: block;
  margin: 5px;
  width: 40px; }

.pixel-dimensions {
  position: absolute;
  pointer-events: none;
  font-weight: bold;
  font-family: sans-serif;
  font-size: 70%;
  color: #000;
  text-shadow: -1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff, 1px 1px 0 #fff; }

.fixed-container {
  align-items: center;
  display: flex;
  flex-direction: column;
  height: 100vh;
  justify-content: center;
  left: 0;
  margin: 0;
  padding: 0;
  pointer-events: none;
  position: fixed;
  top: 0;
  width: 100%; }

.face-container {
  position: relative;
  width: 64px;
  height: 64px; }

.face {
  width: 62.4px;
  height: 62.4px;
  display: block;
  background-image: url("MOZ_EXTENSION/icons/icon-welcome-face-without-eyes.svg"); }

.eye {
  background-color: #fff;
  width: 10.8px;
  height: 14.6px;
  position: absolute;
  border-radius: 100%;
  overflow: hidden;
  left: 16.4px;
  top: 19.8px; }

.eyeball {
  position: absolute;
  width: 6px;
  height: 6px;
  background-color: #000;
  border-radius: 50%;
  left: 2.4px;
  top: 4.3px;
  z-index: 10; }

.left {
  margin-left: 0; }

.right {
  margin-left: 20px; }

.preview-instructions {
  display: flex;
  align-items: center;
  justify-content: center;
  animation: pulse 125mm cubic-bezier(0.07, 0.95, 0, 1);
  color: #fff;
  font-family: -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 24px;
  line-height: 32px;
  text-align: center;
  padding-top: 20px;
  width: 400px; }

.myshots-all-buttons-container {
  display: flex;
  flex-direction: row-reverse;
  background: #f5f5f5;
  border-radius: 2px;
  box-sizing: border-box;
  height: 80px;
  padding: 8px;
  position: absolute;
  right: 5px;
  top: 5px; }
  html[dir="rtl"] .myshots-all-buttons-container {
    left: 5px;
    right: inherit; }
  .myshots-all-buttons-container .spacer {
    background-color: #c9c9c9;
    flex: 0 0 1px;
    height: 80px;
    margin: 0 10px;
    position: relative;
    top: -8px; }
  .myshots-all-buttons-container button {
    display: flex;
    align-items: center;
    flex-direction: column;
    justify-content: flex-end;
    background-color: #f5f5f5;
    background-position: center top;
    background-repeat: no-repeat;
    background-size: 46px 46px;
    border: 1px solid transparent;
    cursor: pointer;
    height: 100%;
    min-width: 90px;
    padding: 46px 5px 5px;
    pointer-events: all;
    transition: border 150ms cubic-bezier(0.07, 0.95, 0, 1), background-color 150ms cubic-bezier(0.07, 0.95, 0, 1);
    white-space: nowrap; }
    .myshots-all-buttons-container button:hover {
      background-color: #ebebeb;
      border: 1px solid #c7c7c7; }
    .myshots-all-buttons-container button:active {
      background-color: #dedede;
      border: 1px solid #989898; }
  .myshots-all-buttons-container .myshots-button {
    background-image: url("MOZ_EXTENSION/icons/menu-myshot.svg"); }
  .myshots-all-buttons-container .full-page {
    background-image: url("MOZ_EXTENSION/icons/menu-fullpage.svg"); }
  .myshots-all-buttons-container .visible {
    background-image: url("MOZ_EXTENSION/icons/menu-visible.svg"); }

.myshots-button-container {
  display: flex;
  align-items: center;
  justify-content: center; }

@keyframes pulse {
  0% {
    transform: scale(1); }
  50% {
    transform: scale(1.06); }
  100% {
    transform: scale(1); } }

@keyframes fade-in {
  0% {
    opacity: 0; }
  100% {
    opacity: 1; } }

`;
null;

PK
!<'0##webextension/build/onboardingCss.js/* Created from build/server/static/css/onboarding.css */
window.onboardingCss = `
@keyframes fade-in {
  0% {
    opacity: 0; }
  100% {
    opacity: 1; } }

@keyframes pop {
  0% {
    transform: scale(1); }
  97% {
    transform: scale(1.04); }
  100% {
    transform: scale(1); } }

@keyframes pulse {
  0% {
    opacity: .3;
    transform: scale(1); }
  70% {
    opacity: .25;
    transform: scale(1.04); }
  100% {
    opacity: .3;
    transform: scale(1); } }

@keyframes slide-left {
  0% {
    opacity: 0;
    transform: translate3d(160px, 0, 0); }
  100% {
    opacity: 1;
    transform: translate3d(0, 0, 0); } }

html,
body {
  box-sizing: border-box;
  font-family: -apple-system, BlinkMacSystemFont, sans-serif;
  height: 100%;
  margin: 0;
  width: 100%; }

#slide-overlay {
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  animation: fade-in 250ms forwards cubic-bezier(0.07, 0.95, 0, 1);
  background: rgba(0, 0, 0, 0.8);
  height: 100%;
  opacity: 0;
  width: 100%; }

#slide-container {
  animation-delay: 50ms;
  animation: fade-in 250ms forwards cubic-bezier(0.07, 0.95, 0, 1);
  opacity: 0; }

.slide {
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  background-color: #f5f5f7;
  border-radius: 5px;
  height: 520px;
  overflow: hidden;
  width: 700px; }
  .slide .slide-image {
    background-size: 700px 378px;
    flex: 0 0 360px;
    font-size: 16px;
    width: 100%; }
  .slide .slide-content {
    display: flex;
    align-items: center;
    flex-direction: column;
    justify-content: center;
    box-sizing: border-box;
    flex: 0 0 160px;
    padding: 5px;
    text-align: center; }
  .slide h1 {
    font-size: 30px;
    font-weight: 400;
    margin: 0 0 10px; }
    .slide h1 sup {
      background: #00d1e6;
      border-radius: 2px;
      color: #fff;
      font-size: 16px;
      margin-left: 5px;
      padding: 2px; }
  .slide p {
    animation-duration: 350ms;
    font-size: 16px;
    line-height: 23px;
    margin: 0;
    width: 75%; }
  .slide .slide-content-aligner h1 {
    font-size: 34px; }
  .slide .slide-content-aligner p {
    margin: 0 auto; }
  .slide .onboarding-legal-notice {
    font-size: 12px;
    color: #858585; }
    .slide .onboarding-legal-notice a {
      color: #009ec0;
      text-decoration: none; }
  .slide:not(.slide-1) h1 {
    opacity: 0;
    transform: translate3d(160px, 0, 0);
    animation: slide-left 500ms forwards cubic-bezier(0.07, 0.95, 0, 1); }
  .slide:not(.slide-1) p {
    opacity: 0;
    transform: translate3d(160px, 0, 0);
    animation: slide-left 600ms forwards cubic-bezier(0.07, 0.95, 0, 1); }
  .slide:not(.slide-1) .slide-image {
    background-color: #00d1e6; }
  .slide.slide-1 {
    background: #fff; }
    .slide.slide-1 .slide-content {
      justify-content: space-between;
      width: 100%; }

.slide-1,
.slide-2,
.slide-3,
.slide-4,
.slide-5 {
  display: none; }

.active-slide-1 .slide-1,
.active-slide-2 .slide-2,
.active-slide-3 .slide-3,
.active-slide-4 .slide-4 {
  display: flex; }

#slide-status-container {
  display: flex;
  align-items: center;
  justify-content: center;
  padding-top: 15px; }

.goto-slide {
  background: transparent;
  background-color: #f5f5f7;
  border-radius: 50%;
  border: 0;
  flex: 0 0 9px;
  height: 9px;
  margin: 0 4px;
  opacity: 0.7;
  padding: 0;
  transition: height 100ms cubic-bezier(0.07, 0.95, 0, 1), opacity 100ms cubic-bezier(0.07, 0.95, 0, 1); }

.goto-slide:hover {
  opacity: 1; }

.active-slide-1 .goto-slide-1,
.active-slide-2 .goto-slide-2,
.active-slide-3 .goto-slide-3,
.active-slide-4 .goto-slide-4 {
  opacity: 1;
  transform: scale(1.1); }

#prev, #next,
#done {
  background-color: #f0f0f0;
  border-radius: 50%;
  border: 0;
  box-shadow: 0 0 12px rgba(0, 0, 0, 0.2);
  display: inline-block;
  height: 70px;
  margin-top: -70px;
  position: absolute;
  text-align: center;
  top: 50%;
  transition: background-color 150ms cubic-bezier(0.07, 0.95, 0, 1), background-size 250ms cubic-bezier(0.07, 0.95, 0, 1);
  width: 70px; }

#prev {
  background-image: url("MOZ_EXTENSION/icons/back.svg");
  left: 50%;
  margin-left: -385px; }

#next,
#done {
  left: 50%;
  margin-left: 315px; }

#prev,
#next,
#done {
  background-position: center center;
  background-repeat: no-repeat;
  background-size: 20px 20px; }
  #prev:hover,
  #next:hover,
  #done:hover {
    background-color: #fff;
    background-size: 22px 22px; }
  #prev:active,
  #next:active,
  #done:active {
    background-color: #fff;
    background-size: 24px 24px; }

#next {
  background-image: url("MOZ_EXTENSION/icons/back.svg");
  transform: rotate(180deg); }
  .active-slide-1 #next {
    background-image: url("MOZ_EXTENSION/icons/back-highlight.svg"); }

#skip {
  background: none;
  border: 0;
  color: #fff;
  font-size: 16px;
  left: 50%;
  margin-left: -330px;
  margin-top: 257px;
  opacity: 0.7;
  position: absolute;
  top: 50%;
  transition: opacity 100ms cubic-bezier(0.07, 0.95, 0, 1);
  z-index: 10; }

#skip:hover {
  opacity: 1; }

.active-slide-1 #prev,
.active-slide-3 #next {
  display: none; }

#done {
  background-image: url("MOZ_EXTENSION/icons/done.svg");
  display: none; }

.active-slide-3 #done {
  display: inline-block; }

/* for smaller screen sizes */
@media screen and (max-width: 768px) {
  .slide {
    height: 360px;
    width: 450px; }
    .slide .slide-image {
      background-size: contain;
      background-repeat: no-repeat;
      background-position: center;
      flex: 0 0 200px; }
    .slide .slide-content {
      flex: 0 0 160px; }
      .slide .slide-content h1 {
        font-size: 24px; }
      .slide .slide-content p {
        font-size: 14px;
        line-height: 21px;
        width: 85%; }
      .slide .slide-content .onboarding-legal-notice {
        font-size: 10px;
        line-height: 16px; }
  #skip {
    margin-left: -205px;
    margin-top: 177px; }
  #prev {
    margin-left: -260px; }
  #next,
  #done {
    margin-left: 190px; } }

`;
null;

PK
!<)7,
,
$webextension/build/onboardingHtml.js/* Created from addon/webextension/onboarding/slides.html */
window.onboardingHtml = `
<!DOCTYPE html>
<html>
  <head>
    <!-- onboarding.scss is automatically inserted here: -->
    <style></style>
    <!-- Here and in onboarding.scss use MOZ_EXTENSION/path to refer to local files -->
  </head>
  <body>
    <div id="slide-overlay">
      <!-- The current slide is set by having .active-slide-1, .active-slide-2, etc on #slide element: -->
      <div id="slide-container" data-number-of-slides="3" class="active-slide-1">
        <div class="slide slide-1">
          <!-- Note: all images must be listed in manifest.json.template under web_accessible_resources -->
          <div class="slide-image" style="background-image: url('MOZ_EXTENSION/icons/onboarding-1.png');"></div>
          <div class="slide-content">
            <div class="slide-content-aligner">
              <h1><span><strong>Firefox</strong> Screenshots</span><sup>Beta</sup></h1>
              <p data-l10n-id="tourBodyOne"></p>
            </div>
            <p class="onboarding-legal-notice"><!-- Substituted with termsAndPrivacyNotice --></p>
          </div>
        </div>
        <div class="slide slide-2">
          <div class="slide-image" style="background-image: url('MOZ_EXTENSION/icons/onboarding-2.png');"></div>
          <div class="slide-content">
            <h1 data-l10n-id="tourHeaderTwo"></h1>
            <p data-l10n-id="tourBodyTwo"></p>
          </div>
        </div>
        <div class="slide slide-3">
          <div class="slide-image" style="background-image: url('MOZ_EXTENSION/icons/onboarding-4.png');"></div>
          <div class="slide-content">
            <h1 data-l10n-id="tourHeaderFour"></h1>
            <p data-l10n-id="tourBodyFour"></p>
          </div>
        </div>

        <!-- Clickable elements should be buttons for accessibility -->
        <button id="skip" data-l10n-id="tourSkip" tabindex=1>Skip</button>
        <button id="prev" tabindex=2 data-l10n-label-id="tourPrevious"></button>
        <button id="next" tabindex=3 data-l10n-label-id="tourNext"></button>
        <button id="done" tabindex=4 data-l10n-label-id="tourDone"></button>
        <div id="slide-status-container">
          <button class="goto-slide goto-slide-1" data-number="1" tabindex=4></button>
          <button class="goto-slide goto-slide-2" data-number="2" tabindex=5></button>
          <button class="goto-slide goto-slide-3" data-number="3" tabindex=6></button>
        </div>
        <!-- FIXME: Need to put in privacy / etc links -->
      </div>
    </div>
  </body>
</html>

`;
null;

PK
!<ws||webextension/build/raven.js/*! Raven.js 3.15.0 (d49a1b8) | github.com/getsentry/raven-js */

/*
 * Includes TraceKit
 * https://github.com/getsentry/TraceKit
 *
 * Copyright 2017 Matt Robenolt and other contributors
 * Released under the BSD license
 * https://github.com/getsentry/raven-js/blob/master/LICENSE
 *
 */

(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Raven = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
'use strict';

function RavenConfigError(message) {
    this.name = 'RavenConfigError';
    this.message = message;
}
RavenConfigError.prototype = new Error();
RavenConfigError.prototype.constructor = RavenConfigError;

module.exports = RavenConfigError;

},{}],2:[function(_dereq_,module,exports){
'use strict';

var wrapMethod = function(console, level, callback) {
    var originalConsoleLevel = console[level];
    var originalConsole = console;

    if (!(level in console)) {
        return;
    }

    var sentryLevel = level === 'warn'
        ? 'warning'
        : level;

    console[level] = function () {
        var args = [].slice.call(arguments);

        var msg = '' + args.join(' ');
        var data = {level: sentryLevel, logger: 'console', extra: {'arguments': args}};
        callback && callback(msg, data);

        // this fails for some browsers. :(
        if (originalConsoleLevel) {
            // IE9 doesn't allow calling apply on console functions directly
            // See: https://stackoverflow.com/questions/5472938/does-ie9-support-console-log-and-is-it-a-real-function#answer-5473193
            Function.prototype.apply.call(
                originalConsoleLevel,
                originalConsole,
                args
            );
        }
    };
};

module.exports = {
    wrapMethod: wrapMethod
};

},{}],3:[function(_dereq_,module,exports){
(function (global){
/*global XDomainRequest:false, __DEV__:false*/
'use strict';

var TraceKit = _dereq_(6);
var stringify = _dereq_(7);
var RavenConfigError = _dereq_(1);
var utils = _dereq_(5);

var isError = utils.isError,
    isObject = utils.isObject;

var wrapConsoleMethod = _dereq_(2).wrapMethod;

var dsnKeys = 'source protocol user pass host port path'.split(' '),
    dsnPattern = /^(?:(\w+):)?\/\/(?:(\w+)(:\w+)?@)?([\w\.-]+)(?::(\d+))?(\/.*)/;

function now() {
    return +new Date();
}

// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785)
var _window = typeof window !== 'undefined' ? window
            : typeof global !== 'undefined' ? global
            : typeof self !== 'undefined' ? self
            : {};
var _document = _window.document;
var _navigator = _window.navigator;

// First, check for JSON support
// If there is no JSON, we no-op the core features of Raven
// since JSON is required to encode the payload
function Raven() {
    this._hasJSON = !!(typeof JSON === 'object' && JSON.stringify);
    // Raven can run in contexts where there's no document (react-native)
    this._hasDocument = !isUndefined(_document);
    this._hasNavigator = !isUndefined(_navigator);
    this._lastCapturedException = null;
    this._lastData = null;
    this._lastEventId = null;
    this._globalServer = null;
    this._globalKey = null;
    this._globalProject = null;
    this._globalContext = {};
    this._globalOptions = {
        logger: 'javascript',
        ignoreErrors: [],
        ignoreUrls: [],
        whitelistUrls: [],
        includePaths: [],
        crossOrigin: 'anonymous',
        collectWindowErrors: true,
        maxMessageLength: 0,

        // By default, truncates URL values to 250 chars
        maxUrlLength: 250,
        stackTraceLimit: 50,
        autoBreadcrumbs: true,
        instrument: true,
        sampleRate: 1
    };
    this._ignoreOnError = 0;
    this._isRavenInstalled = false;
    this._originalErrorStackTraceLimit = Error.stackTraceLimit;
    // capture references to window.console *and* all its methods first
    // before the console plugin has a chance to monkey patch
    this._originalConsole = _window.console || {};
    this._originalConsoleMethods = {};
    this._plugins = [];
    this._startTime = now();
    this._wrappedBuiltIns = [];
    this._breadcrumbs = [];
    this._lastCapturedEvent = null;
    this._keypressTimeout;
    this._location = _window.location;
    this._lastHref = this._location && this._location.href;
    this._resetBackoff();

    for (var method in this._originalConsole) {  // eslint-disable-line guard-for-in
      this._originalConsoleMethods[method] = this._originalConsole[method];
    }
}

/*
 * The core Raven singleton
 *
 * @this {Raven}
 */

Raven.prototype = {
    // Hardcode version string so that raven source can be loaded directly via
    // webpack (using a build step causes webpack #1617). Grunt verifies that
    // this value matches package.json during build.
    //   See: https://github.com/getsentry/raven-js/issues/465
    VERSION: '3.15.0',

    debug: false,

    TraceKit: TraceKit, // alias to TraceKit

    /*
     * Configure Raven with a DSN and extra options
     *
     * @param {string} dsn The public Sentry DSN
     * @param {object} options Optional set of of global options [optional]
     * @return {Raven}
     */
    config: function(dsn, options) {
        var self = this;

        if (self._globalServer) {
                this._logDebug('error', 'Error: Raven has already been configured');
            return self;
        }
        if (!dsn) return self;

        var globalOptions = self._globalOptions;

        // merge in options
        if (options) {
            each(options, function(key, value){
                // tags and extra are special and need to be put into context
                if (key === 'tags' || key === 'extra' || key === 'user') {
                    self._globalContext[key] = value;
                } else {
                    globalOptions[key] = value;
                }
            });
        }

        self.setDSN(dsn);

        // "Script error." is hard coded into browsers for errors that it can't read.
        // this is the result of a script being pulled in from an external domain and CORS.
        globalOptions.ignoreErrors.push(/^Script error\.?$/);
        globalOptions.ignoreErrors.push(/^Javascript error: Script error\.? on line 0$/);

        // join regexp rules into one big rule
        globalOptions.ignoreErrors = joinRegExp(globalOptions.ignoreErrors);
        globalOptions.ignoreUrls = globalOptions.ignoreUrls.length ? joinRegExp(globalOptions.ignoreUrls) : false;
        globalOptions.whitelistUrls = globalOptions.whitelistUrls.length ? joinRegExp(globalOptions.whitelistUrls) : false;
        globalOptions.includePaths = joinRegExp(globalOptions.includePaths);
        globalOptions.maxBreadcrumbs = Math.max(0, Math.min(globalOptions.maxBreadcrumbs || 100, 100)); // default and hard limit is 100

        var autoBreadcrumbDefaults = {
            xhr: true,
            console: true,
            dom: true,
            location: true
        };

        var autoBreadcrumbs = globalOptions.autoBreadcrumbs;
        if ({}.toString.call(autoBreadcrumbs) === '[object Object]') {
            autoBreadcrumbs = objectMerge(autoBreadcrumbDefaults, autoBreadcrumbs);
        } else if (autoBreadcrumbs !== false) {
            autoBreadcrumbs = autoBreadcrumbDefaults;
        }
        globalOptions.autoBreadcrumbs = autoBreadcrumbs;

        var instrumentDefaults = {
            tryCatch: true
        };

        var instrument = globalOptions.instrument;
        if ({}.toString.call(instrument) === '[object Object]') {
            instrument = objectMerge(instrumentDefaults, instrument);
        } else if (instrument !== false) {
            instrument = instrumentDefaults;
        }
        globalOptions.instrument = instrument;

        TraceKit.collectWindowErrors = !!globalOptions.collectWindowErrors;

        // return for chaining
        return self;
    },

    /*
     * Installs a global window.onerror error handler
     * to capture and report uncaught exceptions.
     * At this point, install() is required to be called due
     * to the way TraceKit is set up.
     *
     * @return {Raven}
     */
    install: function() {
        var self = this;
        if (self.isSetup() && !self._isRavenInstalled) {
            TraceKit.report.subscribe(function () {
                self._handleOnErrorStackInfo.apply(self, arguments);
            });
            if (self._globalOptions.instrument && self._globalOptions.instrument.tryCatch) {
              self._instrumentTryCatch();
            }

            if (self._globalOptions.autoBreadcrumbs)
                self._instrumentBreadcrumbs();

            // Install all of the plugins
            self._drainPlugins();

            self._isRavenInstalled = true;
        }

        Error.stackTraceLimit = self._globalOptions.stackTraceLimit;
        return this;
    },

    /*
     * Set the DSN (can be called multiple time unlike config)
     *
     * @param {string} dsn The public Sentry DSN
     */
    setDSN: function(dsn) {
        var self = this,
            uri = self._parseDSN(dsn),
          lastSlash = uri.path.lastIndexOf('/'),
          path = uri.path.substr(1, lastSlash);

        self._dsn = dsn;
        self._globalKey = uri.user;
        self._globalSecret = uri.pass && uri.pass.substr(1);
        self._globalProject = uri.path.substr(lastSlash + 1);

        self._globalServer = self._getGlobalServer(uri);

        self._globalEndpoint = self._globalServer +
            '/' + path + 'api/' + self._globalProject + '/store/';

        // Reset backoff state since we may be pointing at a
        // new project/server
        this._resetBackoff();
    },

    /*
     * Wrap code within a context so Raven can capture errors
     * reliably across domains that is executed immediately.
     *
     * @param {object} options A specific set of options for this context [optional]
     * @param {function} func The callback to be immediately executed within the context
     * @param {array} args An array of arguments to be called with the callback [optional]
     */
    context: function(options, func, args) {
        if (isFunction(options)) {
            args = func || [];
            func = options;
            options = undefined;
        }

        return this.wrap(options, func).apply(this, args);
    },

    /*
     * Wrap code within a context and returns back a new function to be executed
     *
     * @param {object} options A specific set of options for this context [optional]
     * @param {function} func The function to be wrapped in a new context
     * @param {function} func A function to call before the try/catch wrapper [optional, private]
     * @return {function} The newly wrapped functions with a context
     */
    wrap: function(options, func, _before) {
        var self = this;
        // 1 argument has been passed, and it's not a function
        // so just return it
        if (isUndefined(func) && !isFunction(options)) {
            return options;
        }

        // options is optional
        if (isFunction(options)) {
            func = options;
            options = undefined;
        }

        // At this point, we've passed along 2 arguments, and the second one
        // is not a function either, so we'll just return the second argument.
        if (!isFunction(func)) {
            return func;
        }

        // We don't wanna wrap it twice!
        try {
            if (func.__raven__) {
                return func;
            }

            // If this has already been wrapped in the past, return that
            if (func.__raven_wrapper__ ){
                return func.__raven_wrapper__ ;
            }
        } catch (e) {
            // Just accessing custom props in some Selenium environments
            // can cause a "Permission denied" exception (see raven-js#495).
            // Bail on wrapping and return the function as-is (defers to window.onerror).
            return func;
        }

        function wrapped() {
            var args = [], i = arguments.length,
                deep = !options || options && options.deep !== false;

            if (_before && isFunction(_before)) {
                _before.apply(this, arguments);
            }

            // Recursively wrap all of a function's arguments that are
            // functions themselves.
            while(i--) args[i] = deep ? self.wrap(options, arguments[i]) : arguments[i];

            try {
                // Attempt to invoke user-land function
                // NOTE: If you are a Sentry user, and you are seeing this stack frame, it
                //       means Raven caught an error invoking your application code. This is
                //       expected behavior and NOT indicative of a bug with Raven.js.
                return func.apply(this, args);
            } catch(e) {
                self._ignoreNextOnError();
                self.captureException(e, options);
                throw e;
            }
        }

        // copy over properties of the old function
        for (var property in func) {
            if (hasKey(func, property)) {
                wrapped[property] = func[property];
            }
        }
        wrapped.prototype = func.prototype;

        func.__raven_wrapper__ = wrapped;
        // Signal that this function has been wrapped already
        // for both debugging and to prevent it to being wrapped twice
        wrapped.__raven__ = true;
        wrapped.__inner__ = func;

        return wrapped;
    },

    /*
     * Uninstalls the global error handler.
     *
     * @return {Raven}
     */
    uninstall: function() {
        TraceKit.report.uninstall();

        this._restoreBuiltIns();

        Error.stackTraceLimit = this._originalErrorStackTraceLimit;
        this._isRavenInstalled = false;

        return this;
    },

    /*
     * Manually capture an exception and send it over to Sentry
     *
     * @param {error} ex An exception to be logged
     * @param {object} options A specific set of options for this error [optional]
     * @return {Raven}
     */
    captureException: function(ex, options) {
        // If not an Error is passed through, recall as a message instead
        if (!isError(ex)) {
            return this.captureMessage(ex, objectMerge({
                trimHeadFrames: 1,
                stacktrace: true // if we fall back to captureMessage, default to attempting a new trace
            }, options));
        }

        // Store the raw exception object for potential debugging and introspection
        this._lastCapturedException = ex;

        // TraceKit.report will re-raise any exception passed to it,
        // which means you have to wrap it in try/catch. Instead, we
        // can wrap it here and only re-raise if TraceKit.report
        // raises an exception different from the one we asked to
        // report on.
        try {
            var stack = TraceKit.computeStackTrace(ex);
            this._handleStackInfo(stack, options);
        } catch(ex1) {
            if(ex !== ex1) {
                throw ex1;
            }
        }

        return this;
    },

    /*
     * Manually send a message to Sentry
     *
     * @param {string} msg A plain message to be captured in Sentry
     * @param {object} options A specific set of options for this message [optional]
     * @return {Raven}
     */
    captureMessage: function(msg, options) {
        // config() automagically converts ignoreErrors from a list to a RegExp so we need to test for an
        // early call; we'll error on the side of logging anything called before configuration since it's
        // probably something you should see:
        if (!!this._globalOptions.ignoreErrors.test && this._globalOptions.ignoreErrors.test(msg)) {
            return;
        }

        options = options || {};

        var data = objectMerge({
            message: msg + ''  // Make sure it's actually a string
        }, options);

        if (this._globalOptions.stacktrace || (options && options.stacktrace)) {
            var ex;
            // Generate a "synthetic" stack trace from this point.
            // NOTE: If you are a Sentry user, and you are seeing this stack frame, it is NOT indicative
            //       of a bug with Raven.js. Sentry generates synthetic traces either by configuration,
            //       or if it catches a thrown object without a "stack" property.
            try {
                throw new Error(msg);
            } catch (ex1) {
                ex = ex1;
            }

            // null exception name so `Error` isn't prefixed to msg
            ex.name = null;

            options = objectMerge({
                // fingerprint on msg, not stack trace (legacy behavior, could be
                // revisited)
                fingerprint: msg,
                // since we know this is a synthetic trace, the top N-most frames
                // MUST be from Raven.js, so mark them as in_app later by setting
                // trimHeadFrames
                trimHeadFrames: (options.trimHeadFrames || 0) + 1
            }, options);

            var stack = TraceKit.computeStackTrace(ex);
            var frames = this._prepareFrames(stack, options);
            data.stacktrace = {
                // Sentry expects frames oldest to newest
                frames: frames.reverse()
            }
        }

        // Fire away!
        this._send(data);

        return this;
    },

    captureBreadcrumb: function (obj) {
        var crumb = objectMerge({
            timestamp: now() / 1000
        }, obj);

        if (isFunction(this._globalOptions.breadcrumbCallback)) {
            var result = this._globalOptions.breadcrumbCallback(crumb);

            if (isObject(result) && !isEmptyObject(result)) {
                crumb = result;
            } else if (result === false) {
                return this;
            }
        }

        this._breadcrumbs.push(crumb);
        if (this._breadcrumbs.length > this._globalOptions.maxBreadcrumbs) {
            this._breadcrumbs.shift();
        }
        return this;
    },

    addPlugin: function(plugin /*arg1, arg2, ... argN*/) {
        var pluginArgs = [].slice.call(arguments, 1);

        this._plugins.push([plugin, pluginArgs]);
        if (this._isRavenInstalled) {
            this._drainPlugins();
        }

        return this;
    },

    /*
     * Set/clear a user to be sent along with the payload.
     *
     * @param {object} user An object representing user data [optional]
     * @return {Raven}
     */
    setUserContext: function(user) {
        // Intentionally do not merge here since that's an unexpected behavior.
        this._globalContext.user = user;

        return this;
    },

    /*
     * Merge extra attributes to be sent along with the payload.
     *
     * @param {object} extra An object representing extra data [optional]
     * @return {Raven}
     */
    setExtraContext: function(extra) {
        this._mergeContext('extra', extra);

        return this;
    },

    /*
     * Merge tags to be sent along with the payload.
     *
     * @param {object} tags An object representing tags [optional]
     * @return {Raven}
     */
    setTagsContext: function(tags) {
        this._mergeContext('tags', tags);

        return this;
    },

    /*
     * Clear all of the context.
     *
     * @return {Raven}
     */
    clearContext: function() {
        this._globalContext = {};

        return this;
    },

    /*
     * Get a copy of the current context. This cannot be mutated.
     *
     * @return {object} copy of context
     */
    getContext: function() {
        // lol javascript
        return JSON.parse(stringify(this._globalContext));
    },


    /*
     * Set environment of application
     *
     * @param {string} environment Typically something like 'production'.
     * @return {Raven}
     */
    setEnvironment: function(environment) {
        this._globalOptions.environment = environment;

        return this;
    },

    /*
     * Set release version of application
     *
     * @param {string} release Typically something like a git SHA to identify version
     * @return {Raven}
     */
    setRelease: function(release) {
        this._globalOptions.release = release;

        return this;
    },

    /*
     * Set the dataCallback option
     *
     * @param {function} callback The callback to run which allows the
     *                            data blob to be mutated before sending
     * @return {Raven}
     */
    setDataCallback: function(callback) {
        var original = this._globalOptions.dataCallback;
        this._globalOptions.dataCallback = isFunction(callback)
          ? function (data) { return callback(data, original); }
          : callback;

        return this;
    },

    /*
     * Set the breadcrumbCallback option
     *
     * @param {function} callback The callback to run which allows filtering
     *                            or mutating breadcrumbs
     * @return {Raven}
     */
    setBreadcrumbCallback: function(callback) {
        var original = this._globalOptions.breadcrumbCallback;
        this._globalOptions.breadcrumbCallback = isFunction(callback)
          ? function (data) { return callback(data, original); }
          : callback;

        return this;
    },

    /*
     * Set the shouldSendCallback option
     *
     * @param {function} callback The callback to run which allows
     *                            introspecting the blob before sending
     * @return {Raven}
     */
    setShouldSendCallback: function(callback) {
        var original = this._globalOptions.shouldSendCallback;
        this._globalOptions.shouldSendCallback = isFunction(callback)
            ? function (data) { return callback(data, original); }
            : callback;

        return this;
    },

    /**
     * Override the default HTTP transport mechanism that transmits data
     * to the Sentry server.
     *
     * @param {function} transport Function invoked instead of the default
     *                             `makeRequest` handler.
     *
     * @return {Raven}
     */
    setTransport: function(transport) {
        this._globalOptions.transport = transport;

        return this;
    },

    /*
     * Get the latest raw exception that was captured by Raven.
     *
     * @return {error}
     */
    lastException: function() {
        return this._lastCapturedException;
    },

    /*
     * Get the last event id
     *
     * @return {string}
     */
    lastEventId: function() {
        return this._lastEventId;
    },

    /*
     * Determine if Raven is setup and ready to go.
     *
     * @return {boolean}
     */
    isSetup: function() {
        if (!this._hasJSON) return false;  // needs JSON support
        if (!this._globalServer) {
            if (!this.ravenNotConfiguredError) {
              this.ravenNotConfiguredError = true;
              this._logDebug('error', 'Error: Raven has not been configured.');
            }
            return false;
        }
        return true;
    },

    afterLoad: function () {
        // TODO: remove window dependence?

        // Attempt to initialize Raven on load
        var RavenConfig = _window.RavenConfig;
        if (RavenConfig) {
            this.config(RavenConfig.dsn, RavenConfig.config).install();
        }
    },

    showReportDialog: function (options) {
        if (!_document) // doesn't work without a document (React native)
            return;

        options = options || {};

        var lastEventId = options.eventId || this.lastEventId();
        if (!lastEventId) {
            throw new RavenConfigError('Missing eventId');
        }

        var dsn = options.dsn || this._dsn;
        if (!dsn) {
            throw new RavenConfigError('Missing DSN');
        }

        var encode = encodeURIComponent;
        var qs = '';
        qs += '?eventId=' + encode(lastEventId);
        qs += '&dsn=' + encode(dsn);

        var user = options.user || this._globalContext.user;
        if (user) {
            if (user.name)  qs += '&name=' + encode(user.name);
            if (user.email) qs += '&email=' + encode(user.email);
        }

        var globalServer = this._getGlobalServer(this._parseDSN(dsn));

        var script = _document.createElement('script');
        script.async = true;
        script.src = globalServer + '/api/embed/error-page/' + qs;
        (_document.head || _document.body).appendChild(script);
    },

    /**** Private functions ****/
    _ignoreNextOnError: function () {
        var self = this;
        this._ignoreOnError += 1;
        setTimeout(function () {
            // onerror should trigger before setTimeout
            self._ignoreOnError -= 1;
        });
    },

    _triggerEvent: function(eventType, options) {
        // NOTE: `event` is a native browser thing, so let's avoid conflicting wiht it
        var evt, key;

        if (!this._hasDocument)
            return;

        options = options || {};

        eventType = 'raven' + eventType.substr(0,1).toUpperCase() + eventType.substr(1);

        if (_document.createEvent) {
            evt = _document.createEvent('HTMLEvents');
            evt.initEvent(eventType, true, true);
        } else {
            evt = _document.createEventObject();
            evt.eventType = eventType;
        }

        for (key in options) if (hasKey(options, key)) {
            evt[key] = options[key];
        }

        if (_document.createEvent) {
            // IE9 if standards
            _document.dispatchEvent(evt);
        } else {
            // IE8 regardless of Quirks or Standards
            // IE9 if quirks
            try {
                _document.fireEvent('on' + evt.eventType.toLowerCase(), evt);
            } catch(e) {
                // Do nothing
            }
        }
    },

    /**
     * Wraps addEventListener to capture UI breadcrumbs
     * @param evtName the event name (e.g. "click")
     * @returns {Function}
     * @private
     */
    _breadcrumbEventHandler: function(evtName) {
        var self = this;
        return function (evt) {
            // reset keypress timeout; e.g. triggering a 'click' after
            // a 'keypress' will reset the keypress debounce so that a new
            // set of keypresses can be recorded
            self._keypressTimeout = null;

            // It's possible this handler might trigger multiple times for the same
            // event (e.g. event propagation through node ancestors). Ignore if we've
            // already captured the event.
            if (self._lastCapturedEvent === evt)
                return;

            self._lastCapturedEvent = evt;

            // try/catch both:
            // - accessing evt.target (see getsentry/raven-js#838, #768)
            // - `htmlTreeAsString` because it's complex, and just accessing the DOM incorrectly
            //   can throw an exception in some circumstances.
            var target;
            try {
                target = htmlTreeAsString(evt.target);
            } catch (e) {
                target = '<unknown>';
            }

            self.captureBreadcrumb({
                category: 'ui.' + evtName, // e.g. ui.click, ui.input
                message: target
            });
        };
    },

    /**
     * Wraps addEventListener to capture keypress UI events
     * @returns {Function}
     * @private
     */
    _keypressEventHandler: function() {
        var self = this,
            debounceDuration = 1000; // milliseconds

        // TODO: if somehow user switches keypress target before
        //       debounce timeout is triggered, we will only capture
        //       a single breadcrumb from the FIRST target (acceptable?)
        return function (evt) {
            var target;
            try {
                target = evt.target;
            } catch (e) {
                // just accessing event properties can throw an exception in some rare circumstances
                // see: https://github.com/getsentry/raven-js/issues/838
                return;
            }
            var tagName = target && target.tagName;

            // only consider keypress events on actual input elements
            // this will disregard keypresses targeting body (e.g. tabbing
            // through elements, hotkeys, etc)
            if (!tagName || tagName !== 'INPUT' && tagName !== 'TEXTAREA' && !target.isContentEditable)
                return;

            // record first keypress in a series, but ignore subsequent
            // keypresses until debounce clears
            var timeout = self._keypressTimeout;
            if (!timeout) {
                self._breadcrumbEventHandler('input')(evt);
            }
            clearTimeout(timeout);
            self._keypressTimeout = setTimeout(function () {
                self._keypressTimeout = null;
            }, debounceDuration);
        };
    },

    /**
     * Captures a breadcrumb of type "navigation", normalizing input URLs
     * @param to the originating URL
     * @param from the target URL
     * @private
     */
    _captureUrlChange: function(from, to) {
        var parsedLoc = parseUrl(this._location.href);
        var parsedTo = parseUrl(to);
        var parsedFrom = parseUrl(from);

        // because onpopstate only tells you the "new" (to) value of location.href, and
        // not the previous (from) value, we need to track the value of the current URL
        // state ourselves
        this._lastHref = to;

        // Use only the path component of the URL if the URL matches the current
        // document (almost all the time when using pushState)
        if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host)
            to = parsedTo.relative;
        if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host)
            from = parsedFrom.relative;

        this.captureBreadcrumb({
            category: 'navigation',
            data: {
                to: to,
                from: from
            }
        });
    },

    /**
     * Wrap timer functions and event targets to catch errors and provide
     * better metadata.
     */
    _instrumentTryCatch: function() {
        var self = this;

        var wrappedBuiltIns = self._wrappedBuiltIns;

        function wrapTimeFn(orig) {
            return function (fn, t) { // preserve arity
                // Make a copy of the arguments to prevent deoptimization
                // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments
                var args = new Array(arguments.length);
                for(var i = 0; i < args.length; ++i) {
                    args[i] = arguments[i];
                }
                var originalCallback = args[0];
                if (isFunction(originalCallback)) {
                    args[0] = self.wrap(originalCallback);
                }

                // IE < 9 doesn't support .call/.apply on setInterval/setTimeout, but it
                // also supports only two arguments and doesn't care what this is, so we
                // can just call the original function directly.
                if (orig.apply) {
                    return orig.apply(this, args);
                } else {
                    return orig(args[0], args[1]);
                }
            };
        }

        var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs;

        function wrapEventTarget(global) {
            var proto = _window[global] && _window[global].prototype;
            if (proto && proto.hasOwnProperty && proto.hasOwnProperty('addEventListener')) {
                fill(proto, 'addEventListener', function(orig) {
                    return function (evtName, fn, capture, secure) { // preserve arity
                        try {
                            if (fn && fn.handleEvent) {
                                fn.handleEvent = self.wrap(fn.handleEvent);
                            }
                        } catch (err) {
                            // can sometimes get 'Permission denied to access property "handle Event'
                        }

                        // More breadcrumb DOM capture ... done here and not in `_instrumentBreadcrumbs`
                        // so that we don't have more than one wrapper function
                        var before,
                            clickHandler,
                            keypressHandler;

                        if (autoBreadcrumbs && autoBreadcrumbs.dom && (global === 'EventTarget' || global === 'Node')) {
                            // NOTE: generating multiple handlers per addEventListener invocation, should
                            //       revisit and verify we can just use one (almost certainly)
                            clickHandler = self._breadcrumbEventHandler('click');
                            keypressHandler = self._keypressEventHandler();
                            before = function (evt) {
                                // need to intercept every DOM event in `before` argument, in case that
                                // same wrapped method is re-used for different events (e.g. mousemove THEN click)
                                // see #724
                                if (!evt) return;

                                var eventType;
                                try {
                                    eventType = evt.type
                                } catch (e) {
                                    // just accessing event properties can throw an exception in some rare circumstances
                                    // see: https://github.com/getsentry/raven-js/issues/838
                                    return;
                                }
                                if (eventType === 'click')
                                    return clickHandler(evt);
                                else if (eventType === 'keypress')
                                    return keypressHandler(evt);
                            };
                        }
                        return orig.call(this, evtName, self.wrap(fn, undefined, before), capture, secure);
                    };
                }, wrappedBuiltIns);
                fill(proto, 'removeEventListener', function (orig) {
                    return function (evt, fn, capture, secure) {
                        try {
                            fn = fn && (fn.__raven_wrapper__ ? fn.__raven_wrapper__  : fn);
                        } catch (e) {
                            // ignore, accessing __raven_wrapper__ will throw in some Selenium environments
                        }
                        return orig.call(this, evt, fn, capture, secure);
                    };
                }, wrappedBuiltIns);
            }
        }

        fill(_window, 'setTimeout', wrapTimeFn, wrappedBuiltIns);
        fill(_window, 'setInterval', wrapTimeFn, wrappedBuiltIns);
        if (_window.requestAnimationFrame) {
            fill(_window, 'requestAnimationFrame', function (orig) {
                return function (cb) {
                    return orig(self.wrap(cb));
                };
            }, wrappedBuiltIns);
        }

        // event targets borrowed from bugsnag-js:
        // https://github.com/bugsnag/bugsnag-js/blob/master/src/bugsnag.js#L666
        var eventTargets = ['EventTarget', 'Window', 'Node', 'ApplicationCache', 'AudioTrackList', 'ChannelMergerNode', 'CryptoOperation', 'EventSource', 'FileReader', 'HTMLUnknownElement', 'IDBDatabase', 'IDBRequest', 'IDBTransaction', 'KeyOperation', 'MediaController', 'MessagePort', 'ModalWindow', 'Notification', 'SVGElementInstance', 'Screen', 'TextTrack', 'TextTrackCue', 'TextTrackList', 'WebSocket', 'WebSocketWorker', 'Worker', 'XMLHttpRequest', 'XMLHttpRequestEventTarget', 'XMLHttpRequestUpload'];
        for (var i = 0; i < eventTargets.length; i++) {
            wrapEventTarget(eventTargets[i]);
        }
    },


    /**
     * Instrument browser built-ins w/ breadcrumb capturing
     *  - XMLHttpRequests
     *  - DOM interactions (click/typing)
     *  - window.location changes
     *  - console
     *
     * Can be disabled or individually configured via the `autoBreadcrumbs` config option
     */
    _instrumentBreadcrumbs: function () {
        var self = this;
        var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs;

        var wrappedBuiltIns = self._wrappedBuiltIns;

        function wrapProp(prop, xhr) {
            if (prop in xhr && isFunction(xhr[prop])) {
                fill(xhr, prop, function (orig) {
                    return self.wrap(orig);
                }); // intentionally don't track filled methods on XHR instances
            }
        }

        if (autoBreadcrumbs.xhr && 'XMLHttpRequest' in _window) {
            var xhrproto = XMLHttpRequest.prototype;
            fill(xhrproto, 'open', function(origOpen) {
                return function (method, url) { // preserve arity

                    // if Sentry key appears in URL, don't capture
                    if (isString(url) && url.indexOf(self._globalKey) === -1) {
                        this.__raven_xhr = {
                            method: method,
                            url: url,
                            status_code: null
                        };
                    }

                    return origOpen.apply(this, arguments);
                };
            }, wrappedBuiltIns);

            fill(xhrproto, 'send', function(origSend) {
                return function (data) { // preserve arity
                    var xhr = this;

                    function onreadystatechangeHandler() {
                        if (xhr.__raven_xhr && (xhr.readyState === 1 || xhr.readyState === 4)) {
                            try {
                                // touching statusCode in some platforms throws
                                // an exception
                                xhr.__raven_xhr.status_code = xhr.status;
                            } catch (e) { /* do nothing */ }
                            self.captureBreadcrumb({
                                type: 'http',
                                category: 'xhr',
                                data: xhr.__raven_xhr
                            });
                        }
                    }

                    var props = ['onload', 'onerror', 'onprogress'];
                    for (var j = 0; j < props.length; j++) {
                        wrapProp(props[j], xhr);
                    }

                    if ('onreadystatechange' in xhr && isFunction(xhr.onreadystatechange)) {
                        fill(xhr, 'onreadystatechange', function (orig) {
                            return self.wrap(orig, undefined, onreadystatechangeHandler);
                        } /* intentionally don't track this instrumentation */);
                    } else {
                        // if onreadystatechange wasn't actually set by the page on this xhr, we
                        // are free to set our own and capture the breadcrumb
                        xhr.onreadystatechange = onreadystatechangeHandler;
                    }

                    return origSend.apply(this, arguments);
                };
            }, wrappedBuiltIns);
        }

        if (autoBreadcrumbs.xhr && 'fetch' in _window) {
            fill(_window, 'fetch', function(origFetch) {
                return function (fn, t) { // preserve arity
                    // Make a copy of the arguments to prevent deoptimization
                    // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments
                    var args = new Array(arguments.length);
                    for (var i = 0; i < args.length; ++i) {
                        args[i] = arguments[i];
                    }

                    var fetchInput = args[0];
                    var method = 'GET';
                    var url;

                    if (typeof fetchInput === 'string') {
                        url = fetchInput;
                    } else {
                        url = fetchInput.url;
                        if (fetchInput.method) {
                            method = fetchInput.method;
                        }
                    }

                    if (args[1] && args[1].method) {
                        method = args[1].method;
                    }

                    var fetchData = {
                        method: method,
                        url: url,
                        status_code: null
                    };

                    self.captureBreadcrumb({
                        type: 'http',
                        category: 'fetch',
                        data: fetchData
                    });

                    return origFetch.apply(this, args).then(function (response) {
                        fetchData.status_code = response.status;

                        return response;
                    });
                };
            }, wrappedBuiltIns);
        }

        // Capture breadcrumbs from any click that is unhandled / bubbled up all the way
        // to the document. Do this before we instrument addEventListener.
        if (autoBreadcrumbs.dom && this._hasDocument) {
            if (_document.addEventListener) {
                _document.addEventListener('click', self._breadcrumbEventHandler('click'), false);
                _document.addEventListener('keypress', self._keypressEventHandler(), false);
            }
            else {
                // IE8 Compatibility
                _document.attachEvent('onclick', self._breadcrumbEventHandler('click'));
                _document.attachEvent('onkeypress', self._keypressEventHandler());
            }
        }

        // record navigation (URL) changes
        // NOTE: in Chrome App environment, touching history.pushState, *even inside
        //       a try/catch block*, will cause Chrome to output an error to console.error
        // borrowed from: https://github.com/angular/angular.js/pull/13945/files
        var chrome = _window.chrome;
        var isChromePackagedApp = chrome && chrome.app && chrome.app.runtime;
        var hasPushState = !isChromePackagedApp && _window.history && history.pushState;
        if (autoBreadcrumbs.location && hasPushState) {
            // TODO: remove onpopstate handler on uninstall()
            var oldOnPopState = _window.onpopstate;
            _window.onpopstate = function () {
                var currentHref = self._location.href;
                self._captureUrlChange(self._lastHref, currentHref);

                if (oldOnPopState) {
                    return oldOnPopState.apply(this, arguments);
                }
            };

            fill(history, 'pushState', function (origPushState) {
                // note history.pushState.length is 0; intentionally not declaring
                // params to preserve 0 arity
                return function (/* state, title, url */) {
                    var url = arguments.length > 2 ? arguments[2] : undefined;

                    // url argument is optional
                    if (url) {
                        // coerce to string (this is what pushState does)
                        self._captureUrlChange(self._lastHref, url + '');
                    }

                    return origPushState.apply(this, arguments);
                };
            }, wrappedBuiltIns);
        }

        if (autoBreadcrumbs.console && 'console' in _window && console.log) {
            // console
            var consoleMethodCallback = function (msg, data) {
                self.captureBreadcrumb({
                    message: msg,
                    level: data.level,
                    category: 'console'
                });
            };

            each(['debug', 'info', 'warn', 'error', 'log'], function (_, level) {
                wrapConsoleMethod(console, level, consoleMethodCallback);
            });
        }

    },

    _restoreBuiltIns: function () {
        // restore any wrapped builtins
        var builtin;
        while (this._wrappedBuiltIns.length) {
            builtin = this._wrappedBuiltIns.shift();

            var obj = builtin[0],
              name = builtin[1],
              orig = builtin[2];

            obj[name] = orig;
        }
    },

    _drainPlugins: function() {
        var self = this;

        // FIX ME TODO
        each(this._plugins, function(_, plugin) {
            var installer = plugin[0];
            var args = plugin[1];
            installer.apply(self, [self].concat(args));
        });
    },

    _parseDSN: function(str) {
        var m = dsnPattern.exec(str),
            dsn = {},
            i = 7;

        try {
            while (i--) dsn[dsnKeys[i]] = m[i] || '';
        } catch(e) {
            throw new RavenConfigError('Invalid DSN: ' + str);
        }

        if (dsn.pass && !this._globalOptions.allowSecretKey) {
            throw new RavenConfigError('Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key');
        }

        return dsn;
    },

    _getGlobalServer: function(uri) {
        // assemble the endpoint from the uri pieces
        var globalServer = '//' + uri.host +
            (uri.port ? ':' + uri.port : '');

        if (uri.protocol) {
            globalServer = uri.protocol + ':' + globalServer;
        }
        return globalServer;
    },

    _handleOnErrorStackInfo: function() {
        // if we are intentionally ignoring errors via onerror, bail out
        if (!this._ignoreOnError) {
            this._handleStackInfo.apply(this, arguments);
        }
    },

    _handleStackInfo: function(stackInfo, options) {
        var frames = this._prepareFrames(stackInfo, options);

        this._triggerEvent('handle', {
            stackInfo: stackInfo,
            options: options
        });

        this._processException(
            stackInfo.name,
            stackInfo.message,
            stackInfo.url,
            stackInfo.lineno,
            frames,
            options
        );
    },

    _prepareFrames: function(stackInfo, options) {
        var self = this;
        var frames = [];
        if (stackInfo.stack && stackInfo.stack.length) {
            each(stackInfo.stack, function(i, stack) {
                var frame = self._normalizeFrame(stack);
                if (frame) {
                    frames.push(frame);
                }
            });

            // e.g. frames captured via captureMessage throw
            if (options && options.trimHeadFrames) {
                for (var j = 0; j < options.trimHeadFrames && j < frames.length; j++) {
                    frames[j].in_app = false;
                }
            }
        }
        frames = frames.slice(0, this._globalOptions.stackTraceLimit);
        return frames;
    },


    _normalizeFrame: function(frame) {
        if (!frame.url) return;

        // normalize the frames data
        var normalized = {
            filename:   frame.url,
            lineno:     frame.line,
            colno:      frame.column,
            'function': frame.func || '?'
        };

        normalized.in_app = !( // determine if an exception came from outside of our app
            // first we check the global includePaths list.
            !!this._globalOptions.includePaths.test && !this._globalOptions.includePaths.test(normalized.filename) ||
            // Now we check for fun, if the function name is Raven or TraceKit
            /(Raven|TraceKit)\./.test(normalized['function']) ||
            // finally, we do a last ditch effort and check for raven.min.js
            /raven\.(min\.)?js$/.test(normalized.filename)
        );

        return normalized;
    },

    _processException: function(type, message, fileurl, lineno, frames, options) {
        var stacktrace;
        if (!!this._globalOptions.ignoreErrors.test && this._globalOptions.ignoreErrors.test(message)) return;

        message += '';

        if (frames && frames.length) {
            fileurl = frames[0].filename || fileurl;
            // Sentry expects frames oldest to newest
            // and JS sends them as newest to oldest
            frames.reverse();
            stacktrace = {frames: frames};
        } else if (fileurl) {
            stacktrace = {
                frames: [{
                    filename: fileurl,
                    lineno: lineno,
                    in_app: true
                }]
            };
        }

        if (!!this._globalOptions.ignoreUrls.test && this._globalOptions.ignoreUrls.test(fileurl)) return;
        if (!!this._globalOptions.whitelistUrls.test && !this._globalOptions.whitelistUrls.test(fileurl)) return;

        var data = objectMerge({
            // sentry.interfaces.Exception
            exception: {
                values: [{
                    type: type,
                    value: message,
                    stacktrace: stacktrace
                }]
            },
            culprit: fileurl
        }, options);

        // Fire away!
        this._send(data);
    },

    _trimPacket: function(data) {
        // For now, we only want to truncate the two different messages
        // but this could/should be expanded to just trim everything
        var max = this._globalOptions.maxMessageLength;
        if (data.message) {
            data.message = truncate(data.message, max);
        }
        if (data.exception) {
            var exception = data.exception.values[0];
            exception.value = truncate(exception.value, max);
        }

        var request = data.request;
        if (request) {
            if (request.url) {
                request.url = truncate(request.url, this._globalOptions.maxUrlLength);
            }
            if (request.Referer) {
                request.Referer = truncate(request.Referer, this._globalOptions.maxUrlLength);
            }
        }

        if (data.breadcrumbs && data.breadcrumbs.values)
            this._trimBreadcrumbs(data.breadcrumbs);

        return data;
    },

    /**
     * Truncate breadcrumb values (right now just URLs)
     */
    _trimBreadcrumbs: function (breadcrumbs) {
        // known breadcrumb properties with urls
        // TODO: also consider arbitrary prop values that start with (https?)?://
        var urlProps = ['to', 'from', 'url'],
            urlProp,
            crumb,
            data;

        for (var i = 0; i < breadcrumbs.values.length; ++i) {
            crumb = breadcrumbs.values[i];
            if (!crumb.hasOwnProperty('data') || !isObject(crumb.data))
                continue;

            data = crumb.data;
            for (var j = 0; j < urlProps.length; ++j) {
                urlProp = urlProps[j];
                if (data.hasOwnProperty(urlProp)) {
                    data[urlProp] = truncate(data[urlProp], this._globalOptions.maxUrlLength);
                }
            }
        }
    },

    _getHttpData: function() {
        if (!this._hasNavigator && !this._hasDocument) return;
        var httpData = {};

        if (this._hasNavigator && _navigator.userAgent) {
            httpData.headers = {
              'User-Agent': navigator.userAgent
            };
        }

        if (this._hasDocument) {
            if (_document.location && _document.location.href) {
                httpData.url = _document.location.href;
            }
            if (_document.referrer) {
                if (!httpData.headers) httpData.headers = {};
                httpData.headers.Referer = _document.referrer;
            }
        }

        return httpData;
    },

    _resetBackoff: function() {
        this._backoffDuration = 0;
        this._backoffStart = null;
    },

    _shouldBackoff: function() {
        return this._backoffDuration && now() - this._backoffStart < this._backoffDuration;
    },

    /**
     * Returns true if the in-process data payload matches the signature
     * of the previously-sent data
     *
     * NOTE: This has to be done at this level because TraceKit can generate
     *       data from window.onerror WITHOUT an exception object (IE8, IE9,
     *       other old browsers). This can take the form of an "exception"
     *       data object with a single frame (derived from the onerror args).
     */
    _isRepeatData: function (current) {
        var last = this._lastData;

        if (!last ||
            current.message !== last.message || // defined for captureMessage
            current.culprit !== last.culprit)   // defined for captureException/onerror
            return false;

        // Stacktrace interface (i.e. from captureMessage)
        if (current.stacktrace || last.stacktrace) {
            return isSameStacktrace(current.stacktrace, last.stacktrace);
        }
        // Exception interface (i.e. from captureException/onerror)
        else if (current.exception || last.exception) {
            return isSameException(current.exception, last.exception);
        }

        return true;
    },

    _setBackoffState: function(request) {
        // If we are already in a backoff state, don't change anything
        if (this._shouldBackoff()) {
            return;
        }

        var status = request.status;

        // 400 - project_id doesn't exist or some other fatal
        // 401 - invalid/revoked dsn
        // 429 - too many requests
        if (!(status === 400 || status === 401 || status === 429))
            return;

        var retry;
        try {
            // If Retry-After is not in Access-Control-Expose-Headers, most
            // browsers will throw an exception trying to access it
            retry = request.getResponseHeader('Retry-After');
            retry = parseInt(retry, 10) * 1000; // Retry-After is returned in seconds
        } catch (e) {
            /* eslint no-empty:0 */
        }


        this._backoffDuration = retry
            // If Sentry server returned a Retry-After value, use it
            ? retry
            // Otherwise, double the last backoff duration (starts at 1 sec)
            : this._backoffDuration * 2 || 1000;

        this._backoffStart = now();
    },

    _send: function(data) {
        var globalOptions = this._globalOptions;

        var baseData = {
            project: this._globalProject,
            logger: globalOptions.logger,
            platform: 'javascript'
        }, httpData = this._getHttpData();

        if (httpData) {
            baseData.request = httpData;
        }

        // HACK: delete `trimHeadFrames` to prevent from appearing in outbound payload
        if (data.trimHeadFrames) delete data.trimHeadFrames;

        data = objectMerge(baseData, data);

        // Merge in the tags and extra separately since objectMerge doesn't handle a deep merge
        data.tags = objectMerge(objectMerge({}, this._globalContext.tags), data.tags);
        data.extra = objectMerge(objectMerge({}, this._globalContext.extra), data.extra);

        // Send along our own collected metadata with extra
        data.extra['session:duration'] = now() - this._startTime;

        if (this._breadcrumbs && this._breadcrumbs.length > 0) {
            // intentionally make shallow copy so that additions
            // to breadcrumbs aren't accidentally sent in this request
            data.breadcrumbs = {
                values: [].slice.call(this._breadcrumbs, 0)
            };
        }

        // If there are no tags/extra, strip the key from the payload alltogther.
        if (isEmptyObject(data.tags)) delete data.tags;

        if (this._globalContext.user) {
            // sentry.interfaces.User
            data.user = this._globalContext.user;
        }

        // Include the environment if it's defined in globalOptions
        if (globalOptions.environment) data.environment = globalOptions.environment;

        // Include the release if it's defined in globalOptions
        if (globalOptions.release) data.release = globalOptions.release;

        // Include server_name if it's defined in globalOptions
        if (globalOptions.serverName) data.server_name = globalOptions.serverName;

        if (isFunction(globalOptions.dataCallback)) {
            data = globalOptions.dataCallback(data) || data;
        }

        // Why??????????
        if (!data || isEmptyObject(data)) {
            return;
        }

        // Check if the request should be filtered or not
        if (isFunction(globalOptions.shouldSendCallback) && !globalOptions.shouldSendCallback(data)) {
            return;
        }

        // Backoff state: Sentry server previously responded w/ an error (e.g. 429 - too many requests),
        // so drop requests until "cool-off" period has elapsed.
        if (this._shouldBackoff()) {
            this._logDebug('warn', 'Raven dropped error due to backoff: ', data);
            return;
        }

        if (typeof globalOptions.sampleRate === 'number') {
            if (Math.random() < globalOptions.sampleRate) {
                this._sendProcessedPayload(data);
            }
        } else {
            this._sendProcessedPayload(data);
        }
    },

    _getUuid: function () {
      return uuid4();
    },

    _sendProcessedPayload: function(data, callback) {
        var self = this;
        var globalOptions = this._globalOptions;

        if (!this.isSetup()) return;

        // Send along an event_id if not explicitly passed.
        // This event_id can be used to reference the error within Sentry itself.
        // Set lastEventId after we know the error should actually be sent
        this._lastEventId = data.event_id || (data.event_id = this._getUuid());

        // Try and clean up the packet before sending by truncating long values
        data = this._trimPacket(data);

        // ideally duplicate error testing should occur *before* dataCallback/shouldSendCallback,
        // but this would require copying an un-truncated copy of the data packet, which can be
        // arbitrarily deep (extra_data) -- could be worthwhile? will revisit
        if (!this._globalOptions.allowDuplicates && this._isRepeatData(data)) {
            this._logDebug('warn', 'Raven dropped repeat event: ', data);
            return;
        }

        // Store outbound payload after trim
        this._lastData = data;

        this._logDebug('debug', 'Raven about to send:', data);

        var auth = {
            sentry_version: '7',
            sentry_client: 'raven-js/' + this.VERSION,
            sentry_key: this._globalKey
        };
        if (this._globalSecret) {
            auth.sentry_secret = this._globalSecret;
        }

        var exception = data.exception && data.exception.values[0];
        this.captureBreadcrumb({
            category: 'sentry',
            message: exception
                ? (exception.type ? exception.type + ': ' : '') + exception.value
                : data.message,
            event_id: data.event_id,
            level: data.level || 'error' // presume error unless specified
        });

        var url = this._globalEndpoint;
        (globalOptions.transport || this._makeRequest).call(this, {
            url: url,
            auth: auth,
            data: data,
            options: globalOptions,
            onSuccess: function success() {
                self._resetBackoff();

                self._triggerEvent('success', {
                    data: data,
                    src: url
                });
                callback && callback();
            },
            onError: function failure(error) {
                self._logDebug('error', 'Raven transport failed to send: ', error);

                if (error.request) {
                    self._setBackoffState(error.request);
                }

                self._triggerEvent('failure', {
                    data: data,
                    src: url
                });
                error = error || new Error('Raven send failed (no additional details provided)');
                callback && callback(error);
            }
        });
    },

    _makeRequest: function(opts) {
        var request = new XMLHttpRequest();

        // if browser doesn't support CORS (e.g. IE7), we are out of luck
        var hasCORS =
            'withCredentials' in request ||
            typeof XDomainRequest !== 'undefined';

        if (!hasCORS) return;

        var url = opts.url;

        if ('withCredentials' in request) {
            request.onreadystatechange = function () {
                if (request.readyState !== 4) {
                    return;
                } else if (request.status === 200) {
                    opts.onSuccess && opts.onSuccess();
                } else if (opts.onError) {
                    var err = new Error('Sentry error code: ' + request.status);
                    err.request = request;
                    opts.onError(err);
                }
            };
        } else {
            request = new XDomainRequest();
            // xdomainrequest cannot go http -> https (or vice versa),
            // so always use protocol relative
            url = url.replace(/^https?:/, '');

            // onreadystatechange not supported by XDomainRequest
            if (opts.onSuccess) {
                request.onload = opts.onSuccess;
            }
            if (opts.onError) {
                request.onerror = function () {
                    var err = new Error('Sentry error code: XDomainRequest');
                    err.request = request;
                    opts.onError(err);
                }
            }
        }

        // NOTE: auth is intentionally sent as part of query string (NOT as custom
        //       HTTP header) so as to avoid preflight CORS requests
        request.open('POST', url + '?' + urlencode(opts.auth));
        request.send(stringify(opts.data));
    },

    _logDebug: function(level) {
        if (this._originalConsoleMethods[level] && this.debug) {
            // In IE<10 console methods do not have their own 'apply' method
            Function.prototype.apply.call(
                this._originalConsoleMethods[level],
                this._originalConsole,
                [].slice.call(arguments, 1)
            );
        }
    },

    _mergeContext: function(key, context) {
        if (isUndefined(context)) {
            delete this._globalContext[key];
        } else {
            this._globalContext[key] = objectMerge(this._globalContext[key] || {}, context);
        }
    }
};

/*------------------------------------------------
 * utils
 *
 * conditionally exported for test via Raven.utils
 =================================================
 */
var objectPrototype = Object.prototype;

function isUndefined(what) {
    return what === void 0;
}

function isFunction(what) {
    return typeof what === 'function';
}

function isString(what) {
    return objectPrototype.toString.call(what) === '[object String]';
}


function isEmptyObject(what) {
    for (var _ in what) return false;  // eslint-disable-line guard-for-in, no-unused-vars
    return true;
}

function each(obj, callback) {
    var i, j;

    if (isUndefined(obj.length)) {
        for (i in obj) {
            if (hasKey(obj, i)) {
                callback.call(null, i, obj[i]);
            }
        }
    } else {
        j = obj.length;
        if (j) {
            for (i = 0; i < j; i++) {
                callback.call(null, i, obj[i]);
            }
        }
    }
}

function objectMerge(obj1, obj2) {
    if (!obj2) {
        return obj1;
    }
    each(obj2, function(key, value){
        obj1[key] = value;
    });
    return obj1;
}

function truncate(str, max) {
    return !max || str.length <= max ? str : str.substr(0, max) + '\u2026';
}

/**
 * hasKey, a better form of hasOwnProperty
 * Example: hasKey(MainHostObject, property) === true/false
 *
 * @param {Object} host object to check property
 * @param {string} key to check
 */
function hasKey(object, key) {
    return objectPrototype.hasOwnProperty.call(object, key);
}

function joinRegExp(patterns) {
    // Combine an array of regular expressions and strings into one large regexp
    // Be mad.
    var sources = [],
        i = 0, len = patterns.length,
        pattern;

    for (; i < len; i++) {
        pattern = patterns[i];
        if (isString(pattern)) {
            // If it's a string, we need to escape it
            // Taken from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
            sources.push(pattern.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'));
        } else if (pattern && pattern.source) {
            // If it's a regexp already, we want to extract the source
            sources.push(pattern.source);
        }
        // Intentionally skip other cases
    }
    return new RegExp(sources.join('|'), 'i');
}

function urlencode(o) {
    var pairs = [];
    each(o, function(key, value) {
        pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
    });
    return pairs.join('&');
}

// borrowed from https://tools.ietf.org/html/rfc3986#appendix-B
// intentionally using regex and not <a/> href parsing trick because React Native and other
// environments where DOM might not be available
function parseUrl(url) {
    var match = url.match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/);
    if (!match) return {};

    // coerce to undefined values to empty string so we don't get 'undefined'
    var query = match[6] || '';
    var fragment = match[8] || '';
    return {
        protocol: match[2],
        host: match[4],
        path: match[5],
        relative: match[5] + query + fragment // everything minus origin
    };
}
function uuid4() {
    var crypto = _window.crypto || _window.msCrypto;

    if (!isUndefined(crypto) && crypto.getRandomValues) {
        // Use window.crypto API if available
        var arr = new Uint16Array(8);
        crypto.getRandomValues(arr);

        // set 4 in byte 7
        arr[3] = arr[3] & 0xFFF | 0x4000;
        // set 2 most significant bits of byte 9 to '10'
        arr[4] = arr[4] & 0x3FFF | 0x8000;

        var pad = function(num) {
            var v = num.toString(16);
            while (v.length < 4) {
                v = '0' + v;
            }
            return v;
        };

        return pad(arr[0]) + pad(arr[1]) + pad(arr[2]) + pad(arr[3]) + pad(arr[4]) +
        pad(arr[5]) + pad(arr[6]) + pad(arr[7]);
    } else {
        // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
        return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random()*16|0,
                v = c === 'x' ? r : r&0x3|0x8;
            return v.toString(16);
        });
    }
}

/**
 * Given a child DOM element, returns a query-selector statement describing that
 * and its ancestors
 * e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]
 * @param elem
 * @returns {string}
 */
function htmlTreeAsString(elem) {
    /* eslint no-extra-parens:0*/
    var MAX_TRAVERSE_HEIGHT = 5,
        MAX_OUTPUT_LEN = 80,
        out = [],
        height = 0,
        len = 0,
        separator = ' > ',
        sepLength = separator.length,
        nextStr;

    while (elem && height++ < MAX_TRAVERSE_HEIGHT) {

        nextStr = htmlElementAsString(elem);
        // bail out if
        // - nextStr is the 'html' element
        // - the length of the string that would be created exceeds MAX_OUTPUT_LEN
        //   (ignore this limit if we are on the first iteration)
        if (nextStr === 'html' || height > 1 && len + (out.length * sepLength) + nextStr.length >= MAX_OUTPUT_LEN) {
            break;
        }

        out.push(nextStr);

        len += nextStr.length;
        elem = elem.parentNode;
    }

    return out.reverse().join(separator);
}

/**
 * Returns a simple, query-selector representation of a DOM element
 * e.g. [HTMLElement] => input#foo.btn[name=baz]
 * @param HTMLElement
 * @returns {string}
 */
function htmlElementAsString(elem) {
    var out = [],
        className,
        classes,
        key,
        attr,
        i;

    if (!elem || !elem.tagName) {
        return '';
    }

    out.push(elem.tagName.toLowerCase());
    if (elem.id) {
        out.push('#' + elem.id);
    }

    className = elem.className;
    if (className && isString(className)) {
        classes = className.split(/\s+/);
        for (i = 0; i < classes.length; i++) {
            out.push('.' + classes[i]);
        }
    }
    var attrWhitelist = ['type', 'name', 'title', 'alt'];
    for (i = 0; i < attrWhitelist.length; i++) {
        key = attrWhitelist[i];
        attr = elem.getAttribute(key);
        if (attr) {
            out.push('[' + key + '="' + attr + '"]');
        }
    }
    return out.join('');
}

/**
 * Returns true if either a OR b is truthy, but not both
 */
function isOnlyOneTruthy(a, b) {
    return !!(!!a ^ !!b);
}

/**
 * Returns true if the two input exception interfaces have the same content
 */
function isSameException(ex1, ex2) {
    if (isOnlyOneTruthy(ex1, ex2))
        return false;

    ex1 = ex1.values[0];
    ex2 = ex2.values[0];

    if (ex1.type !== ex2.type ||
        ex1.value !== ex2.value)
        return false;

    return isSameStacktrace(ex1.stacktrace, ex2.stacktrace);
}

/**
 * Returns true if the two input stack trace interfaces have the same content
 */
function isSameStacktrace(stack1, stack2) {
    if (isOnlyOneTruthy(stack1, stack2))
        return false;

    var frames1 = stack1.frames;
    var frames2 = stack2.frames;

    // Exit early if frame count differs
    if (frames1.length !== frames2.length)
        return false;

    // Iterate through every frame; bail out if anything differs
    var a, b;
    for (var i = 0; i < frames1.length; i++) {
        a = frames1[i];
        b = frames2[i];
        if (a.filename !== b.filename ||
            a.lineno !== b.lineno ||
            a.colno !== b.colno ||
            a['function'] !== b['function'])
            return false;
    }
    return true;
}

/**
 * Polyfill a method
 * @param obj object e.g. `document`
 * @param name method name present on object e.g. `addEventListener`
 * @param replacement replacement function
 * @param track {optional} record instrumentation to an array
 */
function fill(obj, name, replacement, track) {
    var orig = obj[name];
    obj[name] = replacement(orig);
    if (track) {
        track.push([obj, name, orig]);
    }
}

if (typeof __DEV__ !== 'undefined' && __DEV__) {
    Raven.utils = {
        isUndefined: isUndefined,
        isFunction: isFunction,
        isString: isString,
        isObject: isObject,
        isEmptyObject: isEmptyObject,
        isError: isError,
        each: each,
        objectMerge: objectMerge,
        truncate: truncate,
        hasKey: hasKey,
        joinRegExp: joinRegExp,
        urlencode: urlencode,
        uuid4: uuid4,
        htmlTreeAsString: htmlTreeAsString,
        htmlElementAsString: htmlElementAsString,
        parseUrl: parseUrl,
        fill: fill
    };
};

// Deprecations
Raven.prototype.setUser = Raven.prototype.setUserContext;
Raven.prototype.setReleaseContext = Raven.prototype.setRelease;

module.exports = Raven;

}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"1":1,"2":2,"5":5,"6":6,"7":7}],4:[function(_dereq_,module,exports){
(function (global){
/**
 * Enforces a single instance of the Raven client, and the
 * main entry point for Raven. If you are a consumer of the
 * Raven library, you SHOULD load this file (vs raven.js).
 **/

'use strict';

var RavenConstructor = _dereq_(3);

// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785)
var _window = typeof window !== 'undefined' ? window
            : typeof global !== 'undefined' ? global
            : typeof self !== 'undefined' ? self
            : {};
var _Raven = _window.Raven;

var Raven = new RavenConstructor();

/*
 * Allow multiple versions of Raven to be installed.
 * Strip Raven from the global context and returns the instance.
 *
 * @return {Raven}
 */
Raven.noConflict = function () {
	_window.Raven = _Raven;
	return Raven;
};

Raven.afterLoad();

module.exports = Raven;

}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"3":3}],5:[function(_dereq_,module,exports){
'use strict';

function isObject(what) {
    return typeof what === 'object' && what !== null;
}

// Yanked from https://git.io/vS8DV re-used under CC0
// with some tiny modifications
function isError(value) {
  switch ({}.toString.call(value)) {
    case '[object Error]': return true;
    case '[object Exception]': return true;
    case '[object DOMException]': return true;
    default: return value instanceof Error;
  }
}

module.exports = {
    isObject: isObject,
    isError: isError
};

},{}],6:[function(_dereq_,module,exports){
(function (global){
'use strict';

var utils = _dereq_(5);

/*
 TraceKit - Cross brower stack traces

 This was originally forked from github.com/occ/TraceKit, but has since been
 largely re-written and is now maintained as part of raven-js.  Tests for
 this are in test/vendor.

 MIT license
*/

var TraceKit = {
    collectWindowErrors: true,
    debug: false
};

// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785)
var _window = typeof window !== 'undefined' ? window
            : typeof global !== 'undefined' ? global
            : typeof self !== 'undefined' ? self
            : {};

// global reference to slice
var _slice = [].slice;
var UNKNOWN_FUNCTION = '?';

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Error_types
var ERROR_TYPES_RE = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/;

function getLocationHref() {
    if (typeof document === 'undefined' || typeof document.location === 'undefined')
        return '';

    return document.location.href;
}


/**
 * TraceKit.report: cross-browser processing of unhandled exceptions
 *
 * Syntax:
 *   TraceKit.report.subscribe(function(stackInfo) { ... })
 *   TraceKit.report.unsubscribe(function(stackInfo) { ... })
 *   TraceKit.report(exception)
 *   try { ...code... } catch(ex) { TraceKit.report(ex); }
 *
 * Supports:
 *   - Firefox: full stack trace with line numbers, plus column number
 *              on top frame; column number is not guaranteed
 *   - Opera:   full stack trace with line and column numbers
 *   - Chrome:  full stack trace with line and column numbers
 *   - Safari:  line and column number for the top frame only; some frames
 *              may be missing, and column number is not guaranteed
 *   - IE:      line and column number for the top frame only; some frames
 *              may be missing, and column number is not guaranteed
 *
 * In theory, TraceKit should work on all of the following versions:
 *   - IE5.5+ (only 8.0 tested)
 *   - Firefox 0.9+ (only 3.5+ tested)
 *   - Opera 7+ (only 10.50 tested; versions 9 and earlier may require
 *     Exceptions Have Stacktrace to be enabled in opera:config)
 *   - Safari 3+ (only 4+ tested)
 *   - Chrome 1+ (only 5+ tested)
 *   - Konqueror 3.5+ (untested)
 *
 * Requires TraceKit.computeStackTrace.
 *
 * Tries to catch all unhandled exceptions and report them to the
 * subscribed handlers. Please note that TraceKit.report will rethrow the
 * exception. This is REQUIRED in order to get a useful stack trace in IE.
 * If the exception does not reach the top of the browser, you will only
 * get a stack trace from the point where TraceKit.report was called.
 *
 * Handlers receive a stackInfo object as described in the
 * TraceKit.computeStackTrace docs.
 */
TraceKit.report = (function reportModuleWrapper() {
    var handlers = [],
        lastArgs = null,
        lastException = null,
        lastExceptionStack = null;

    /**
     * Add a crash handler.
     * @param {Function} handler
     */
    function subscribe(handler) {
        installGlobalHandler();
        handlers.push(handler);
    }

    /**
     * Remove a crash handler.
     * @param {Function} handler
     */
    function unsubscribe(handler) {
        for (var i = handlers.length - 1; i >= 0; --i) {
            if (handlers[i] === handler) {
                handlers.splice(i, 1);
            }
        }
    }

    /**
     * Remove all crash handlers.
     */
    function unsubscribeAll() {
        uninstallGlobalHandler();
        handlers = [];
    }

    /**
     * Dispatch stack information to all handlers.
     * @param {Object.<string, *>} stack
     */
    function notifyHandlers(stack, isWindowError) {
        var exception = null;
        if (isWindowError && !TraceKit.collectWindowErrors) {
          return;
        }
        for (var i in handlers) {
            if (handlers.hasOwnProperty(i)) {
                try {
                    handlers[i].apply(null, [stack].concat(_slice.call(arguments, 2)));
                } catch (inner) {
                    exception = inner;
                }
            }
        }

        if (exception) {
            throw exception;
        }
    }

    var _oldOnerrorHandler, _onErrorHandlerInstalled;

    /**
     * Ensures all global unhandled exceptions are recorded.
     * Supported by Gecko and IE.
     * @param {string} message Error message.
     * @param {string} url URL of script that generated the exception.
     * @param {(number|string)} lineNo The line number at which the error
     * occurred.
     * @param {?(number|string)} colNo The column number at which the error
     * occurred.
     * @param {?Error} ex The actual Error object.
     */
    function traceKitWindowOnError(message, url, lineNo, colNo, ex) {
        var stack = null;

        if (lastExceptionStack) {
            TraceKit.computeStackTrace.augmentStackTraceWithInitialElement(lastExceptionStack, url, lineNo, message);
            processLastException();
        } else if (ex && utils.isError(ex)) {
            // non-string `ex` arg; attempt to extract stack trace

            // New chrome and blink send along a real error object
            // Let's just report that like a normal error.
            // See: https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror
            stack = TraceKit.computeStackTrace(ex);
            notifyHandlers(stack, true);
        } else {
            var location = {
                'url': url,
                'line': lineNo,
                'column': colNo
            };

            var name = undefined;
            var msg = message; // must be new var or will modify original `arguments`
            var groups;
            if ({}.toString.call(message) === '[object String]') {
                var groups = message.match(ERROR_TYPES_RE);
                if (groups) {
                    name = groups[1];
                    msg = groups[2];
                }
            }

            location.func = UNKNOWN_FUNCTION;

            stack = {
                'name': name,
                'message': msg,
                'url': getLocationHref(),
                'stack': [location]
            };
            notifyHandlers(stack, true);
        }

        if (_oldOnerrorHandler) {
            return _oldOnerrorHandler.apply(this, arguments);
        }

        return false;
    }

    function installGlobalHandler ()
    {
        if (_onErrorHandlerInstalled) {
            return;
        }
        _oldOnerrorHandler = _window.onerror;
        _window.onerror = traceKitWindowOnError;
        _onErrorHandlerInstalled = true;
    }

    function uninstallGlobalHandler ()
    {
        if (!_onErrorHandlerInstalled) {
            return;
        }
        _window.onerror = _oldOnerrorHandler;
        _onErrorHandlerInstalled = false;
        _oldOnerrorHandler = undefined;
    }

    function processLastException() {
        var _lastExceptionStack = lastExceptionStack,
            _lastArgs = lastArgs;
        lastArgs = null;
        lastExceptionStack = null;
        lastException = null;
        notifyHandlers.apply(null, [_lastExceptionStack, false].concat(_lastArgs));
    }

    /**
     * Reports an unhandled Error to TraceKit.
     * @param {Error} ex
     * @param {?boolean} rethrow If false, do not re-throw the exception.
     * Only used for window.onerror to not cause an infinite loop of
     * rethrowing.
     */
    function report(ex, rethrow) {
        var args = _slice.call(arguments, 1);
        if (lastExceptionStack) {
            if (lastException === ex) {
                return; // already caught by an inner catch block, ignore
            } else {
              processLastException();
            }
        }

        var stack = TraceKit.computeStackTrace(ex);
        lastExceptionStack = stack;
        lastException = ex;
        lastArgs = args;

        // If the stack trace is incomplete, wait for 2 seconds for
        // slow slow IE to see if onerror occurs or not before reporting
        // this exception; otherwise, we will end up with an incomplete
        // stack trace
        setTimeout(function () {
            if (lastException === ex) {
                processLastException();
            }
        }, (stack.incomplete ? 2000 : 0));

        if (rethrow !== false) {
            throw ex; // re-throw to propagate to the top level (and cause window.onerror)
        }
    }

    report.subscribe = subscribe;
    report.unsubscribe = unsubscribe;
    report.uninstall = unsubscribeAll;
    return report;
}());

/**
 * TraceKit.computeStackTrace: cross-browser stack traces in JavaScript
 *
 * Syntax:
 *   s = TraceKit.computeStackTrace(exception) // consider using TraceKit.report instead (see below)
 * Returns:
 *   s.name              - exception name
 *   s.message           - exception message
 *   s.stack[i].url      - JavaScript or HTML file URL
 *   s.stack[i].func     - function name, or empty for anonymous functions (if guessing did not work)
 *   s.stack[i].args     - arguments passed to the function, if known
 *   s.stack[i].line     - line number, if known
 *   s.stack[i].column   - column number, if known
 *
 * Supports:
 *   - Firefox:  full stack trace with line numbers and unreliable column
 *               number on top frame
 *   - Opera 10: full stack trace with line and column numbers
 *   - Opera 9-: full stack trace with line numbers
 *   - Chrome:   full stack trace with line and column numbers
 *   - Safari:   line and column number for the topmost stacktrace element
 *               only
 *   - IE:       no line numbers whatsoever
 *
 * Tries to guess names of anonymous functions by looking for assignments
 * in the source code. In IE and Safari, we have to guess source file names
 * by searching for function bodies inside all page scripts. This will not
 * work for scripts that are loaded cross-domain.
 * Here be dragons: some function names may be guessed incorrectly, and
 * duplicate functions may be mismatched.
 *
 * TraceKit.computeStackTrace should only be used for tracing purposes.
 * Logging of unhandled exceptions should be done with TraceKit.report,
 * which builds on top of TraceKit.computeStackTrace and provides better
 * IE support by utilizing the window.onerror event to retrieve information
 * about the top of the stack.
 *
 * Note: In IE and Safari, no stack trace is recorded on the Error object,
 * so computeStackTrace instead walks its *own* chain of callers.
 * This means that:
 *  * in Safari, some methods may be missing from the stack trace;
 *  * in IE, the topmost function in the stack trace will always be the
 *    caller of computeStackTrace.
 *
 * This is okay for tracing (because you are likely to be calling
 * computeStackTrace from the function you want to be the topmost element
 * of the stack trace anyway), but not okay for logging unhandled
 * exceptions (because your catch block will likely be far away from the
 * inner function that actually caused the exception).
 *
 */
TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
    // Contents of Exception in various browsers.
    //
    // SAFARI:
    // ex.message = Can't find variable: qq
    // ex.line = 59
    // ex.sourceId = 580238192
    // ex.sourceURL = http://...
    // ex.expressionBeginOffset = 96
    // ex.expressionCaretOffset = 98
    // ex.expressionEndOffset = 98
    // ex.name = ReferenceError
    //
    // FIREFOX:
    // ex.message = qq is not defined
    // ex.fileName = http://...
    // ex.lineNumber = 59
    // ex.columnNumber = 69
    // ex.stack = ...stack trace... (see the example below)
    // ex.name = ReferenceError
    //
    // CHROME:
    // ex.message = qq is not defined
    // ex.name = ReferenceError
    // ex.type = not_defined
    // ex.arguments = ['aa']
    // ex.stack = ...stack trace...
    //
    // INTERNET EXPLORER:
    // ex.message = ...
    // ex.name = ReferenceError
    //
    // OPERA:
    // ex.message = ...message... (see the example below)
    // ex.name = ReferenceError
    // ex.opera#sourceloc = 11  (pretty much useless, duplicates the info in ex.message)
    // ex.stacktrace = n/a; see 'opera:config#UserPrefs|Exceptions Have Stacktrace'

    /**
     * Computes stack trace information from the stack property.
     * Chrome and Gecko use this property.
     * @param {Error} ex
     * @return {?Object.<string, *>} Stack trace information.
     */
    function computeStackTraceFromStackProp(ex) {
        if (typeof ex.stack === 'undefined' || !ex.stack) return;

        var chrome = /^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,
            gecko = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?)(?::(\d+))?(?::(\d+))?\s*$/i,
            winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,

            // Used to additionally parse URL/line/column from eval frames
            geckoEval = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i,
            chromeEval = /\((\S*)(?::(\d+))(?::(\d+))\)/,

            lines = ex.stack.split('\n'),
            stack = [],
            submatch,
            parts,
            element,
            reference = /^(.*) is undefined$/.exec(ex.message);

        for (var i = 0, j = lines.length; i < j; ++i) {
            if ((parts = chrome.exec(lines[i]))) {
                var isNative = parts[2] && parts[2].indexOf('native') === 0; // start of line
                var isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line
                if (isEval && (submatch = chromeEval.exec(parts[2]))) {
                    // throw out eval line/column and use top-most line/column number
                    parts[2] = submatch[1]; // url
                    parts[3] = submatch[2]; // line
                    parts[4] = submatch[3]; // column
                }
                element = {
                    'url': !isNative ? parts[2] : null,
                    'func': parts[1] || UNKNOWN_FUNCTION,
                    'args': isNative ? [parts[2]] : [],
                    'line': parts[3] ? +parts[3] : null,
                    'column': parts[4] ? +parts[4] : null
                };
            } else if ( parts = winjs.exec(lines[i]) ) {
                element = {
                    'url': parts[2],
                    'func': parts[1] || UNKNOWN_FUNCTION,
                    'args': [],
                    'line': +parts[3],
                    'column': parts[4] ? +parts[4] : null
                };
            } else if ((parts = gecko.exec(lines[i]))) {
                var isEval = parts[3] && parts[3].indexOf(' > eval') > -1;
                if (isEval && (submatch = geckoEval.exec(parts[3]))) {
                    // throw out eval line/column and use top-most line number
                    parts[3] = submatch[1];
                    parts[4] = submatch[2];
                    parts[5] = null; // no column when eval
                } else if (i === 0 && !parts[5] && typeof ex.columnNumber !== 'undefined') {
                    // FireFox uses this awesome columnNumber property for its top frame
                    // Also note, Firefox's column number is 0-based and everything else expects 1-based,
                    // so adding 1
                    // NOTE: this hack doesn't work if top-most frame is eval
                    stack[0].column = ex.columnNumber + 1;
                }
                element = {
                    'url': parts[3],
                    'func': parts[1] || UNKNOWN_FUNCTION,
                    'args': parts[2] ? parts[2].split(',') : [],
                    'line': parts[4] ? +parts[4] : null,
                    'column': parts[5] ? +parts[5] : null
                };
            } else {
                continue;
            }

            if (!element.func && element.line) {
                element.func = UNKNOWN_FUNCTION;
            }

            stack.push(element);
        }

        if (!stack.length) {
            return null;
        }

        return {
            'name': ex.name,
            'message': ex.message,
            'url': getLocationHref(),
            'stack': stack
        };
    }

    /**
     * Adds information about the first frame to incomplete stack traces.
     * Safari and IE require this to get complete data on the first frame.
     * @param {Object.<string, *>} stackInfo Stack trace information from
     * one of the compute* methods.
     * @param {string} url The URL of the script that caused an error.
     * @param {(number|string)} lineNo The line number of the script that
     * caused an error.
     * @param {string=} message The error generated by the browser, which
     * hopefully contains the name of the object that caused the error.
     * @return {boolean} Whether or not the stack information was
     * augmented.
     */
    function augmentStackTraceWithInitialElement(stackInfo, url, lineNo, message) {
        var initial = {
            'url': url,
            'line': lineNo
        };

        if (initial.url && initial.line) {
            stackInfo.incomplete = false;

            if (!initial.func) {
                initial.func = UNKNOWN_FUNCTION;
            }

            if (stackInfo.stack.length > 0) {
                if (stackInfo.stack[0].url === initial.url) {
                    if (stackInfo.stack[0].line === initial.line) {
                        return false; // already in stack trace
                    } else if (!stackInfo.stack[0].line && stackInfo.stack[0].func === initial.func) {
                        stackInfo.stack[0].line = initial.line;
                        return false;
                    }
                }
            }

            stackInfo.stack.unshift(initial);
            stackInfo.partial = true;
            return true;
        } else {
            stackInfo.incomplete = true;
        }

        return false;
    }

    /**
     * Computes stack trace information by walking the arguments.caller
     * chain at the time the exception occurred. This will cause earlier
     * frames to be missed but is the only way to get any stack trace in
     * Safari and IE. The top frame is restored by
     * {@link augmentStackTraceWithInitialElement}.
     * @param {Error} ex
     * @return {?Object.<string, *>} Stack trace information.
     */
    function computeStackTraceByWalkingCallerChain(ex, depth) {
        var functionName = /function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,
            stack = [],
            funcs = {},
            recursion = false,
            parts,
            item,
            source;

        for (var curr = computeStackTraceByWalkingCallerChain.caller; curr && !recursion; curr = curr.caller) {
            if (curr === computeStackTrace || curr === TraceKit.report) {
                // console.log('skipping internal function');
                continue;
            }

            item = {
                'url': null,
                'func': UNKNOWN_FUNCTION,
                'line': null,
                'column': null
            };

            if (curr.name) {
                item.func = curr.name;
            } else if ((parts = functionName.exec(curr.toString()))) {
                item.func = parts[1];
            }

            if (typeof item.func === 'undefined') {
              try {
                item.func = parts.input.substring(0, parts.input.indexOf('{'));
              } catch (e) { }
            }

            if (funcs['' + curr]) {
                recursion = true;
            }else{
                funcs['' + curr] = true;
            }

            stack.push(item);
        }

        if (depth) {
            // console.log('depth is ' + depth);
            // console.log('stack is ' + stack.length);
            stack.splice(0, depth);
        }

        var result = {
            'name': ex.name,
            'message': ex.message,
            'url': getLocationHref(),
            'stack': stack
        };
        augmentStackTraceWithInitialElement(result, ex.sourceURL || ex.fileName, ex.line || ex.lineNumber, ex.message || ex.description);
        return result;
    }

    /**
     * Computes a stack trace for an exception.
     * @param {Error} ex
     * @param {(string|number)=} depth
     */
    function computeStackTrace(ex, depth) {
        var stack = null;
        depth = (depth == null ? 0 : +depth);

        try {
            stack = computeStackTraceFromStackProp(ex);
            if (stack) {
                return stack;
            }
        } catch (e) {
            if (TraceKit.debug) {
                throw e;
            }
        }

        try {
            stack = computeStackTraceByWalkingCallerChain(ex, depth + 1);
            if (stack) {
                return stack;
            }
        } catch (e) {
            if (TraceKit.debug) {
                throw e;
            }
        }
        return {
            'name': ex.name,
            'message': ex.message,
            'url': getLocationHref()
        };
    }

    computeStackTrace.augmentStackTraceWithInitialElement = augmentStackTraceWithInitialElement;
    computeStackTrace.computeStackTraceFromStackProp = computeStackTraceFromStackProp;

    return computeStackTrace;
}());

module.exports = TraceKit;

}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"5":5}],7:[function(_dereq_,module,exports){
'use strict';

/*
 json-stringify-safe
 Like JSON.stringify, but doesn't throw on circular references.

 Originally forked from https://github.com/isaacs/json-stringify-safe
 version 5.0.1 on 3/8/2017 and modified for IE8 compatibility.
 Tests for this are in test/vendor.

 ISC license: https://github.com/isaacs/json-stringify-safe/blob/master/LICENSE
*/

exports = module.exports = stringify
exports.getSerialize = serializer

function indexOf(haystack, needle) {
  for (var i = 0; i < haystack.length; ++i) {
    if (haystack[i] === needle) return i;
  }
  return -1;
}

function stringify(obj, replacer, spaces, cycleReplacer) {
  return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces)
}

function serializer(replacer, cycleReplacer) {
  var stack = [], keys = []

  if (cycleReplacer == null) cycleReplacer = function(key, value) {
    if (stack[0] === value) return '[Circular ~]'
    return '[Circular ~.' + keys.slice(0, indexOf(stack, value)).join('.') + ']'
  }

  return function(key, value) {
    if (stack.length > 0) {
      var thisPos = indexOf(stack, this);
      ~thisPos ? stack.splice(thisPos + 1) : stack.push(this)
      ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key)
      if (~indexOf(stack, value)) value = cycleReplacer.call(this, key, value)
    }
    else stack.push(value)

    return replacer == null ? value : replacer.call(this, key, value)
  }
}

},{}]},{},[4])(4)
});PK
!<X*S*Swebextension/build/shot.jsthis.shot = (function () {let exports={}; // Note: in this library we can't use any "system" dependencies because this can be used from multiple
// environments

/** Throws an error if the condition isn't true.  Any extra arguments after the condition
    are used as console.error() arguments. */
function assert(condition, ...args) {
  if (condition) {
    return;
  }
  console.error("Failed assertion", ...args);
  throw new Error(`Failed assertion: ${args.join(" ")}`);
}

/** True if `url` is a valid URL */
function isUrl(url) {
  // FIXME: this is rather naive, obviously
  if ((/^about:.{1,8000}$/i).test(url)) {
    return true;
  }
  if ((/^file:\/.{0,8000}$/i).test(url)) {
    return true;
  }
  if ((/^data:.*$/i).test(url)) {
    return true;
  }
  if ((/^chrome:.{0,8000}/i).test(url)) {
    return true;
  }
  if ((/^view-source:/i).test(url)) {
    return isUrl(url.substr("view-source:".length));
  }
  return (/^https?:\/\/[a-z0-9\.\-]{1,8000}[a-z0-9](:[0-9]{1,8000})?\/?/i).test(url);
}

function assertUrl(url) {
  if (!url) {
    throw new Error("Empty value is not URL");
  }
  if (!isUrl(url)) {
    let exc = new Error("Not a URL");
    exc.scheme = url.split(":")[0];
    throw exc;
  }
}

function assertOrigin(url) {
  assertUrl(url);
  if (url.search(/^https?:/i) != -1) {
    let match = (/^https?:\/\/[^/:]{1,4000}\/?$/i).exec(url);
    if (!match) {
      throw new Error("Bad origin, might include path");
    }
  }
}

function originFromUrl(url) {
  if (!url) {
    return null;
  }
  if (url.search(/^https?:/i) == -1) {
    // Non-HTTP URLs don't have an origin
    return null;
  }
  let match = (/^https?:\/\/[^/:]{1,4000}/i).exec(url);
  if (match) {
    return match[0];
  }
  return null;
}

/** Check if the given object has all of the required attributes, and no extra
    attributes exception those in optional */
function checkObject(obj, required, optional) {
  if (typeof obj != "object" || obj === null) {
    throw new Error("Cannot check non-object: " + (typeof obj) + " that is " + JSON.stringify(obj));
  }
  required = required || [];
  for (let attr of required) {
    if (!(attr in obj)) {
      return false;
    }
  }
  optional = optional || [];
  for (let attr in obj) {
    if (required.indexOf(attr) == -1 && optional.indexOf(attr) == -1) {
      return false;
    }
  }
  return true;
}

/** Create a JSON object from a normal object, given the required and optional
    attributes (filtering out any other attributes).  Optional attributes are
    only kept when they are truthy. */
function jsonify(obj, required, optional) {
  required = required || [];
  let result = {};
  for (let attr of required) {
    result[attr] = obj[attr];
  }
  optional = optional || [];
  for (let attr of optional) {
    if (obj[attr]) {
      result[attr] = obj[attr];
    }
  }
  return result;
}

/** Resolve url relative to base */
function resolveUrl(base, url) {
  // FIXME: totally ad hoc and probably incorrect, but we can't
  // use any libraries in this file
  if (url.search(/^https?:/) != -1) {
    // Absolute url
    return url;
  }
  if (url.indexOf("//") === 0) {
    // Protocol-relative URL
    return (/^https?:/i).exec(base)[0] + url;
  }
  if (url.indexOf("/") === 0) {
    // Domain-relative URL
    return (/^https?:\/\/[a-z0-9\.\-]{1,4000}/i).exec(base)[0] + url;
  }
  // Otherwise, a full relative URL
  while (url.indexOf("./") === 0) {
    url = url.substr(2);
  }
  if (!base) {
    // It's not an absolute URL, and we don't have a base URL, so we have
    // to throw away the URL
    return null;
  }
  let match = (/.*\//).exec(base)[0];
  if (match.search(/^https?:\/$/i) === 0) {
    // Domain without path
    match = match + "/";
  }
  return match + url;
}

/** True if the two objects look alike.  Null, undefined, and absent properties
    are all treated as equivalent.  Traverses objects and arrays */
function deepEqual(a, b) {
  if ((a === null || a === undefined) && (b === null || b === undefined)) {
    return true;
  }
  if (typeof a != "object" || typeof b != "object") {
    return a === b;
  }
  if (Array.isArray(a)) {
    if (!Array.isArray(b)) {
      return false;
    }
    if (a.length != b.length) {
      return false;
    }
    for (let i = 0; i < a.length; i++) {
      if (!deepEqual(a[i], b[i])) {
        return false;
      }
    }
  }
  if (Array.isArray(b)) {
    return false;
  }
  let seen = new Set();
  for (let attr of Object.keys(a)) {
    if (!deepEqual(a[attr], b[attr])) {
      return false;
    }
    seen.add(attr);
  }
  for (let attr of Object.keys(b)) {
    if (!seen.has(attr)) {
      if (!deepEqual(a[attr], b[attr])) {
        return false;
      }
    }
  }
  return true;
}

function makeRandomId() {
  // Note: this isn't for secure contexts, only for non-conflicting IDs
  let id = "";
  while (id.length < 12) {
    let num;
    if (!id) {
      num = Date.now() % Math.pow(36, 3);
    } else {
      num = Math.floor(Math.random() * Math.pow(36, 3));
    }
    id += num.toString(36);
  }
  return id;
}

class AbstractShot {

  constructor(backend, id, attrs) {
    attrs = attrs || {};
    assert((/^[a-zA-Z0-9]{1,4000}\/[a-z0-9\.-]{1,4000}$/).test(id), "Bad ID (should be alphanumeric):", JSON.stringify(id));
    this._backend = backend;
    this._id = id;
    this.origin = attrs.origin || null;
    this.fullUrl = attrs.fullUrl || null;
    if ((!attrs.fullUrl) && attrs.url) {
      console.warn("Received deprecated attribute .url");
      this.fullUrl = attrs.url;
    }
    this.docTitle = attrs.docTitle || null;
    this.userTitle = attrs.userTitle || null;
    this.createdDate = attrs.createdDate || Date.now();
    this.favicon = attrs.favicon || null;
    this.siteName = attrs.siteName || null;
    this.images = [];
    if (attrs.images) {
      this.images = attrs.images.map(
        (json) => new this.Image(json));
    }
    this.openGraph = attrs.openGraph || null;
    this.twitterCard = attrs.twitterCard || null;
    this.documentSize = attrs.documentSize || null;
    this.fullScreenThumbnail = attrs.fullScreenThumbnail || null;
    this.abTests = attrs.abTests || null;
    this._clips = {};
    if (attrs.clips) {
      for (let clipId in attrs.clips) {
        let clip = attrs.clips[clipId];
        this._clips[clipId] = new this.Clip(this, clipId, clip);
      }
    }

    for (let attr in attrs) {
      if (attr !== "clips" && attr !== "id" && this.REGULAR_ATTRS.indexOf(attr) === -1 && this.DEPRECATED_ATTRS.indexOf(attr) === -1) {
        throw new Error("Unexpected attribute: " + attr);
      } else if (attr === "id") {
        console.warn("passing id in attrs in AbstractShot constructor");
        console.trace();
        assert(attrs.id === this.id);
      }
    }
  }

  /** Update any and all attributes in the json object, with deep updating
      of `json.clips` */
  update(json) {
    let ALL_ATTRS = ["clips"].concat(this.REGULAR_ATTRS);
    assert(checkObject(json, [], ALL_ATTRS), "Bad attr to new Shot():", Object.keys(json));
    for (let attr in json) {
      if (attr == "clips") {
        continue;
      }
      if (typeof json[attr] == "object" && typeof this[attr] == "object" && this[attr] !== null) {
        let val = this[attr];
        if (val.asJson) {
          val = val.asJson();
        }
        if (!deepEqual(json[attr], val)) {
          this[attr] = json[attr];
        }
      } else if (json[attr] !== this[attr] &&
          (json[attr] || this[attr])) {
        this[attr] = json[attr];
      }
    }
    if (json.clips) {
      for (let clipId in json.clips) {
        if (!json.clips[clipId]) {
          this.delClip(clipId);
        } else if (!this.getClip(clipId)) {
          this.setClip(clipId, json.clips[clipId]);
        } else if (!deepEqual(this.getClip(clipId).asJson(), json.clips[clipId])) {
          this.setClip(clipId, json.clips[clipId]);
        }
      }
    }

  }

  /** Returns a JSON version of this shot */
  asJson() {
    let result = {};
    for (let attr of this.REGULAR_ATTRS) {
      var val = this[attr];
      if (val && val.asJson) {
        val = val.asJson();
      }
      result[attr] = val;
    }
    result.clips = {};
    for (let attr in this._clips) {
      result.clips[attr] = this._clips[attr].asJson();
    }
    return result;
  }

  /** A more minimal JSON representation for creating indexes of shots */
  asRecallJson() {
    let result = {clips: {}};
    for (let attr of this.RECALL_ATTRS) {
      var val = this[attr];
      if (val && val.asJson) {
        val = val.asJson();
      }
      result[attr] = val;
    }
    for (let name of this.clipNames()) {
      result.clips[name] = this.getClip(name).asJson();
    }
    return result;
  }

  get backend() {
    return this._backend;
  }

  get id() {
    return this._id;
  }

  get url() {
    return this.fullUrl || this.origin;
  }
  set url(val) {
    throw new Error(".url is read-only");
  }

  get fullUrl() {
    return this._fullUrl;
  }
  set fullUrl(val) {
    if (val) {
      assertUrl(val);
    }
    this._fullUrl = val || undefined;
  }

  get origin() {
    return this._origin;
  }
  set origin(val) {
    if (val) {
      assertOrigin(val);
    }
    this._origin = val || undefined;
  }

  get filename() {
    let filenameTitle = this.title;
    let date = new Date(this.createdDate);
    filenameTitle = filenameTitle.replace(/[:\\<>\/!@&*.|\n\r\t]/g, " ");
    filenameTitle = filenameTitle.replace(/\s{1,4000}/g, " ");
    let clipFilename = `Screenshot-${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()} ${filenameTitle}`;
    const clipFilenameBytesSize = clipFilename.length * 2; // JS STrings are UTF-16
    if (clipFilenameBytesSize > 251) { // 255 bytes (Usual filesystems max) - 4 for the ".png" file extension string
      const excedingchars = (clipFilenameBytesSize - 246) / 2; // 251 - 5 for ellipsis "[...]"
      clipFilename = clipFilename.substring(0, clipFilename.length - excedingchars);
      clipFilename = clipFilename + '[...]';
    }
    return clipFilename + '.png';
  }

  get urlDisplay() {
    if (!this.url) {
      return null;
    }
    if (this.url.search(/^https?/i) != -1) {
      let txt = this.url;
      txt = txt.replace(/^[a-z]{1,4000}:\/\//i, "");
      txt = txt.replace(/\/.{0,4000}/, "");
      txt = txt.replace(/^www\./i, "");
      return txt;
    } else if (this.url.startsWith("data:")) {
      return "data:url";
    }
    let txt = this.url;
    txt = txt.replace(/\?.{0,4000}/, "");
    return txt;
  }

  get viewUrl() {
    let url = this.backend + "/" + this.id;
    return url;
  }

  get creatingUrl() {
    let url = `${this.backend}/creating/${this.id}`;
    url += `?title=${encodeURIComponent(this.title || "")}`;
    url += `&url=${encodeURIComponent(this.url)}`;
    return url;
  }

  get jsonUrl() {
    return this.backend + "/data/" + this.id;
  }

  get oembedUrl() {
    return this.backend + "/oembed?url=" + encodeURIComponent(this.viewUrl);
  }

  get docTitle() {
    return this._title;
  }
  set docTitle(val) {
    assert(val === null || typeof val == "string", "Bad docTitle:", val);
    this._title = val;
  }

  get openGraph() {
    return this._openGraph || null;
  }
  set openGraph(val) {
    assert(val === null || typeof val == "object", "Bad openGraph:", val);
    if (val) {
      assert(checkObject(val, [], this._OPENGRAPH_PROPERTIES), "Bad attr to openGraph:", Object.keys(val));
      this._openGraph = val;
    } else {
      this._openGraph = null;
    }
  }

  get twitterCard() {
    return this._twitterCard || null;
  }
  set twitterCard(val) {
    assert(val === null || typeof val == "object", "Bad twitterCard:", val);
    if (val) {
      assert(checkObject(val, [], this._TWITTERCARD_PROPERTIES), "Bad attr to twitterCard:", Object.keys(val));
      this._twitterCard = val;
    } else {
      this._twitterCard = null;
    }
  }

  get userTitle() {
    return this._userTitle;
  }
  set userTitle(val) {
    assert(val === null || typeof val == "string", "Bad userTitle:", val);
    this._userTitle = val;
  }

  get title() {
    // FIXME: we shouldn't support both openGraph.title and ogTitle
    let ogTitle = this.openGraph && this.openGraph.title;
    let twitterTitle = this.twitterCard && this.twitterCard.title;
    let title = this.userTitle || ogTitle || twitterTitle || this.docTitle || this.url;
    if (Array.isArray(title)) {
      title = title[0];
    }
    if (!title) {
      title = "Screenshot";
    }
    return title;
  }

  get createdDate() {
    return this._createdDate;
  }
  set createdDate(val) {
    assert(val === null || typeof val == "number", "Bad createdDate:", val);
    this._createdDate = val;
  }

  get favicon() {
    return this._favicon;
  }
  set favicon(val) {
    // We allow but ignore bad favicon URLs, as they seem somewhat common
    val = val || null;
    if (!isUrl(val)) {
      val = null;
    }
    if (val) {
      val = resolveUrl(this.url, val);
    }
    this._favicon = val;
  }

  clipNames() {
    let names = Object.getOwnPropertyNames(this._clips);
    names.sort(function(a, b) {
      return a.sortOrder < b.sortOrder ? 1 : 0;
    });
    return names;
  }
  getClip(name) {
    return this._clips[name];
  }
  addClip(val) {
    let name = makeRandomId();
    this.setClip(name, val);
    return name;
  }
  setClip(name, val) {
    let clip = new this.Clip(this, name, val);
    this._clips[name] = clip;
  }
  delClip(name) {
    if (!this._clips[name]) {
      throw new Error("No existing clip with id: " + name);
    }
    delete this._clips[name];
  }
  delAllClips() {
    this._clips = {};
  }
  biggestClipSortOrder() {
    let biggest = 0;
    for (let clipId in this._clips) {
      biggest = Math.max(biggest, this._clips[clipId].sortOrder);
    }
    return biggest;
  }
  updateClipUrl(clipId, clipUrl) {
    let clip = this.getClip(clipId);
    if ( clip && clip.image ) {
      clip.image.url = clipUrl;
    } else {
      console.warn("Tried to update the url of a clip with no image:", clip);
    }
  }

  get siteName() {
    return this._siteName || null;
  }
  set siteName(val) {
    assert(typeof val == "string" || !val);
    this._siteName = val;
  }

  get documentSize() {
    return this._documentSize;
  }
  set documentSize(val) {
    assert(typeof val == "object" || !val);
    if (val) {
      assert(checkObject(val, ["height", "width"], "Bad attr to documentSize:", Object.keys(val)));
      assert(typeof val.height == "number");
      assert(typeof val.width == "number");
      this._documentSize = val;
    } else {
      this._documentSize = null;
    }
  }

  get fullScreenThumbnail() {
    return this._fullScreenThumbnail;
  }
  set fullScreenThumbnail(val) {
    assert(typeof val == "string" || !val);
    if (val) {
      assert(isUrl(val));
      this._fullScreenThumbnail = val;
    } else {
      this._fullScreenThumbnail = null;
    }
  }

  get abTests() {
    return this._abTests;
  }
  set abTests(val) {
    if (val === null || val === undefined) {
      this._abTests = null;
      return;
    }
    assert(typeof val == "object", "abTests should be an object, not:", typeof val);
    assert(!Array.isArray(val), "abTests should not be an Array");
    for (let name in val) {
      assert(val[name] && typeof val[name] == "string", `abTests.${name} should be a string:`, typeof val[name]);
    }
    this._abTests = val;
  }

}

AbstractShot.prototype.REGULAR_ATTRS = (`
origin fullUrl docTitle userTitle createdDate favicon images
siteName openGraph twitterCard documentSize
fullScreenThumbnail abTests
`).split(/\s+/g);

// Attributes that will be accepted in the constructor, but ignored/dropped
AbstractShot.prototype.DEPRECATED_ATTRS = (`
microdata history ogTitle createdDevice head body htmlAttrs bodyAttrs headAttrs
readable hashtags comments showPage isPublic resources deviceId url
`).split(/\s+/g);

AbstractShot.prototype.RECALL_ATTRS = (`
url docTitle userTitle createdDate favicon
openGraph twitterCard images fullScreenThumbnail
`).split(/\s+/g);

AbstractShot.prototype._OPENGRAPH_PROPERTIES = (`
title type url image audio description determiner locale site_name video
image:secure_url image:type image:width image:height
video:secure_url video:type video:width image:height
audio:secure_url audio:type
article:published_time article:modified_time article:expiration_time article:author article:section article:tag
book:author book:isbn book:release_date book:tag
profile:first_name profile:last_name profile:username profile:gender
`).split(/\s+/g);

AbstractShot.prototype._TWITTERCARD_PROPERTIES = (`
card site title description image
player player:width player:height player:stream player:stream:content_type
`).split(/\s+/g);

/** Represents one found image in the document (not a clip) */
class _Image {
  // FIXME: either we have to notify the shot of updates, or make
  // this read-only
  constructor(json) {
    assert(typeof json === "object", "Clip Image given a non-object", json);
    assert(checkObject(json, ["url"], ["dimensions", "title", "alt"]), "Bad attrs for Image:", Object.keys(json));
    assert(isUrl(json.url), "Bad Image url:", json.url);
    this.url = json.url;
    assert((!json.dimensions) ||
           (typeof json.dimensions.x == "number" && typeof json.dimensions.y == "number"),
           "Bad Image dimensions:", json.dimensions);
    this.dimensions = json.dimensions;
    assert(typeof json.title == "string" || !json.title, "Bad Image title:", json.title);
    this.title = json.title;
    assert(typeof json.alt == "string" || !json.alt, "Bad Image alt:", json.alt);
    this.alt = json.alt;
  }

  asJson() {
    return jsonify(this, ["url"], ["dimensions"]);
  }
}

AbstractShot.prototype.Image = _Image;

/** Represents a clip, either a text or image clip */
class _Clip {
  constructor(shot, id, json) {
    this._shot = shot;
    assert(checkObject(json, ["createdDate", "image"], ["sortOrder"]), "Bad attrs for Clip:", Object.keys(json));
    assert(typeof id == "string" && id, "Bad Clip id:", id);
    this._id = id;
    this.createdDate = json.createdDate;
    if ('sortOrder' in json) {
      assert(typeof json.sortOrder == "number" || !json.sortOrder, "Bad Clip sortOrder:", json.sortOrder);
    }
    if ('sortOrder' in json) {
      this.sortOrder = json.sortOrder;
    } else {
      let biggestOrder = shot.biggestClipSortOrder();
      this.sortOrder = biggestOrder + 100;
    }
    this.image = json.image;
  }

  toString() {
    return `[Shot Clip id=${this.id} sortOrder=${this.sortOrder} image ${this.image.dimensions.x}x${this.image.dimensions.y}]`;
  }

  asJson() {
    return jsonify(this, ["createdDate"], ["sortOrder", "image"]);
  }

  get id() {
    return this._id;
  }

  get createdDate() {
    return this._createdDate;
  }
  set createdDate(val) {
    assert(typeof val == "number" || !val, "Bad Clip createdDate:", val);
    this._createdDate = val;
  }

  get image() {
    return this._image;
  }
  set image(image) {
    if (!image) {
      this._image = undefined;
      return;
    }
    assert(checkObject(image, ["url"], ["dimensions", "text", "location", "captureType"]), "Bad attrs for Clip Image:", Object.keys(image));
    assert(isUrl(image.url), "Bad Clip image URL:", image.url);
    assert(image.captureType == "madeSelection" || image.captureType == "selection" || image.captureType == "visible" || image.captureType == "auto" || image.captureType == "fullPage" || !image.captureType, "Bad image.captureType:", image.captureType);
    assert(typeof image.text == "string" || !image.text, "Bad Clip image text:", image.text);
    if (image.dimensions) {
      assert(typeof image.dimensions.x == "number" && typeof image.dimensions.y == "number", "Bad Clip image dimensions:", image.dimensions);
    }
    assert(image.location &&
      typeof image.location.left == "number" &&
      typeof image.location.right == "number" &&
      typeof image.location.top == "number" &&
      typeof image.location.bottom == "number", "Bad Clip image pixel location:", image.location);
    if (image.location.topLeftElement || image.location.topLeftOffset ||
        image.location.bottomRightElement || image.location.bottomRightOffset) {
      assert(typeof image.location.topLeftElement == "string" &&
        image.location.topLeftOffset &&
        typeof image.location.topLeftOffset.x == "number" &&
        typeof image.location.topLeftOffset.y == "number" &&
        typeof image.location.bottomRightElement == "string" &&
        image.location.bottomRightOffset &&
        typeof image.location.bottomRightOffset.x == "number" &&
        typeof image.location.bottomRightOffset.y == "number",
        "Bad Clip image element location:", image.location);
    }
    this._image = image;
  }

  isDataUrl() {
    if (this.image) {
      return this.image.url.startsWith("data:");
    }
    return false;
  }

  get sortOrder() {
    return this._sortOrder || null;
  }
  set sortOrder(val) {
    assert(typeof val == "number" || !val, "Bad Clip sortOrder:", val);
    this._sortOrder = val;
  }

}

AbstractShot.prototype.Clip = _Clip;

if (typeof exports != "undefined") {
  exports.AbstractShot = AbstractShot;
  exports.originFromUrl = originFromUrl;
}

return exports;
})();
null;

PK
!<
+webextension/catcher.js"use strict";

var global = this;

this.catcher = (function() {
  let exports = {};

  let handler;

  let queue = [];

  let log = global.log;

  exports.unhandled = function(error, info) {
    if (!error.noReport) {
      log.error("Unhandled error:", error, info);
    }
    let e = makeError(error, info);
    if (!handler) {
      queue.push(e);
    } else {
      handler(e);
    }
  };

  /** Turn an exception into an error object */
  function makeError(exc, info) {
    let result;
    if (exc.fromMakeError) {
      result = exc;
    } else {
      result = {
        fromMakeError: true,
        name: exc.name || "ERROR",
        message: String(exc),
        stack: exc.stack
      };
      for (let attr in exc) {
        result[attr] = exc[attr];
      }
    }
    if (info) {
      for (let attr of Object.keys(info)) {
        result[attr] = info[attr];
      }
    }
    return result;
  }

  /** Wrap the function, and if it raises any exceptions then call unhandled() */
  exports.watchFunction = function watchFunction(func, quiet) {
    return function() {
      try {
        return func.apply(this, arguments);
      } catch (e) {
        if (!quiet) {
          exports.unhandled(e);
        }
        throw e;
      }
    };
  };

  exports.watchPromise = function watchPromise(promise, quiet) {
    return promise.catch((e) => {
      if (quiet) {
        if (!e.noReport) {
          log.debug("------Error in promise:", e);
          log.debug(e.stack);
        }
      } else {
        if (!e.noReport) {
          log.error("------Error in promise:", e);
          log.error(e.stack);
        }
        exports.unhandled(makeError(e));
      }
      throw e;
    });
  };

  exports.registerHandler = function(h) {
    if (handler) {
      log.error("registerHandler called after handler was already registered");
      return;
    }
    handler = h;
    for (let error of queue) {
      handler(error);
    }
    queue = [];
  };

  return exports;
})();
null;
PK
!<ڪwebextension/clipboard.js/* globals catcher, assertIsBlankDocument */

"use strict";

this.clipboard = (function() {
  let exports = {};

  exports.copy = function(text) {
    return new Promise((resolve, reject) => {
      let element = document.createElement("iframe");
      element.src = browser.extension.getURL("blank.html");
      // We can't actually hide the iframe while copying, but we can make
      // it close to invisible:
      element.style.opacity = "0";
      element.style.width = "1px";
      element.style.height = "1px";
      element.addEventListener("load", catcher.watchFunction(() => {
        try {
          let doc = element.contentDocument;
          assertIsBlankDocument(doc);
          let el = doc.createElement("textarea");
          doc.body.appendChild(el);
          el.value = text;
          el.select();
          const copied = doc.execCommand("copy");
          if (!copied) {
            catcher.unhandled(new Error("Clipboard copy failed"));
          }
          el.remove();
          resolve(copied);
        } finally {
          element.remove();
        }
      }), {once: true});
      document.body.appendChild(element);
    });
  };

  return exports;
})();
null;
PK
!<ʋ@00webextension/domainFromUrl.js/** Returns the domain of a URL, but safely and in ASCII; URLs without domains
    (such as about:blank) return the scheme, Unicode domains get stripped down
    to ASCII */

"use strict";

this.domainFromUrl = (function() {

  return function urlDomainForId(location) { // eslint-disable-line no-unused-vars
    let domain = location.hostname;
    if (!domain) {
      domain = location.origin.split(":")[0];
      if (!domain) {
        domain = "unknown";
      }
    }
    if (domain.search(/^[a-z0-9.\-]{1,1000}$/i) === -1) {
      // Probably a unicode domain; we could use punycode but it wouldn't decode
      // well in the URL anyway.  Instead we'll punt.
      domain = domain.replace(/[^a-z0-9.\-]/ig, "");
      if (!domain) {
        domain = "site";
      }
    }
    return domain;
  };

})();
null;
PK
!<avݺ%webextension/icons/back-highlight.svg<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
<style type="text/css">
	.st0{fill:#009EC0;}
</style>
<path id="path-1_1_" class="st0" fill="#3D3D40" d="M18.8,8.5H4.2l5.4-5.4c0.5-0.5,0.5-1.2,0-1.8s-1.2-0.5-1.8,0L0.4,8.9c-0.5,0.5-0.5,1.2,0,1.8
	l7.5,7.5c0.2,0.2,0.5,0.4,0.9,0.4s0.6-0.1,0.9-0.4c0.5-0.5,0.5-1.2,0-1.8L4.2,11h14.5c0.8,0,1.2-0.5,1.2-1.2S19.5,8.5,18.8,8.5z"/>
</svg>
PK
!<vXwebextension/icons/back.svg<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
<style type="text/css">
	.st0{fill:#3D3D40;}
</style>
<path id="path-1_1_" class="st0" fill="#3D3D40" d="M18.8,8.5H4.2l5.4-5.4c0.5-0.5,0.5-1.2,0-1.8s-1.2-0.5-1.8,0L0.4,8.9c-0.5,0.5-0.5,1.2,0,1.8
	l7.5,7.5c0.2,0.2,0.5,0.4,0.9,0.4s0.6-0.1,0.9-0.4c0.5-0.5,0.5-1.2,0-1.8L4.2,11h14.5c0.8,0,1.2-0.5,1.2-1.2S19.5,8.5,18.8,8.5z"/>
</svg>
PK
!<31זwebextension/icons/cancel.svg<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
<style type="text/css">
	.st0{fill:#3E3D40;}
</style>
<path id="Combined-Shape" class="st0" d="M10.5,8.7L5.2,3.3c-0.5-0.5-1.3-0.5-1.8,0l0,0c-0.5,0.5-0.5,1.3,0,1.8l5.3,5.3l-5.3,5.3
	c-0.5,0.5-0.5,1.3,0,1.8l0,0c0.5,0.5,1.3,0.5,1.8,0l5.3-5.3l5.3,5.3c0.5,0.5,1.3,0.5,1.8,0l0,0c0.5-0.5,0.5-1.3,0-1.8l-5.3-5.3
	l5.3-5.3c0.5-0.5,0.5-1.3,0-1.8l0,0c-0.5-0.5-1.3-0.5-1.8,0L10.5,8.7z"/>
</svg>
PK
!<< webextension/icons/cloud.svg<svg width="20" height="18" viewBox="0 0 20 18" xmlns="http://www.w3.org/2000/svg"><title>cloud</title><g fill="#FFF" fill-rule="evenodd"><path d="M15 5.6h-.3C14.5 2.7 12 .5 9.2.5c-3 0-5.4 2.4-5.5 5.3C1.5 6.4 0 8.3 0 10.6c0 2.8 2.2 5 5 5a1 1 0 0 0 1-1v-.1a1 1 0 0 0-1-1c-1.7 0-3-1.3-3-3 0-1.3.8-2.5 2.2-2.9l1.4-.4.1-1.4c.1-1.9 1.6-3.3 3.5-3.3 1.8 0 3.4 1.4 3.5 3.2l.1 1.8h2.1c1.7 0 3 1.3 3 3s-1.3 3-3 3h-1.85a1.05 1.05 0 1 0 0 2.1H15c2.8 0 5-2.2 5-5s-2.2-5-5-5z" fill-rule="nonzero"/><path d="M10 11.414V17c0 .667-.333 1-1 1s-1-.333-1-1v-5.586l-.293.293a1 1 0 1 1-1.414-1.414L9 7.586l2.707 2.707a1 1 0 0 1-1.414 1.414L10 11.414z"/></g></svg>
PK
!<I4)webextension/icons/copy.pngPNG


IHDR``F
#PLTEFFF@=B>>A?>@?>@>=@?>AUUU@>B?>@DDD?>@?>@>=A?>A?>A?>ADDD>>@@@H??A@@G@@`@@C?>A?>A?>@?=A?>@@>@?>@NNN?>@fff>>A>>@CCC>>@KKKCCC?>A>>A?>AAAA@@F>>@>>A>=AIII??@>>@>>B@=B>>@>>A?>@BBB?=AIII??B>>A?>@?>A?=A?>@?>A?=A@@D@@?=A>>@?=@@=BUUU?>A@>@??A??B??C>>A??A?>@??A>=A>>@CCC?>@?=A>=@?=@CCC>=A@>B?>A!atRNSp|ȝ" f$Lg
&*3,olJ#m˽@ޯ`	[I=jz.݀TwIDATxb@{`Eaxֵ6culۜ$b\}NXq=?)EL<˃2U®v?*K|UUF"PpD+p(8PR1ZsW@Yt{
*`VU{P	طP
Xh,j5,z+mu?z
ܒ\ؒYC2Bd8BB4cL0L0@3D0@3D0@3tqL=&(@$ԀڡgΞOu^	0HK+[\rPHkocvƀ[-r6 K]ˀȽˀ}Pe V@<	@1.(-qr
q<Tx%Qs*<H_T*z	m^AˁPuw27ДOKX˚N˽ݕͤ%Ro ^﹎|E
]SIENDB`PK
!<Pwebextension/icons/done.svg<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
<style type="text/css">
	.st0{fill:#009EC0;}
</style>
<path class="st0" d="M19.5,4c-0.6-0.6-1.6-0.6-2.2,0l-10,10L2.7,9.4c-0.6-0.6-1.6-0.6-2.2,0c-0.6,0.6-0.6,1.6,0,2.2l5.8,5.8
	c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0.3,0.3,0.7,0.5,1.1,0.5c0.4,0,0.8-0.2,1.1-0.5L19.5,6.3C20.2,5.7,20.2,4.7,19.5,4z"/>
</svg>
PK
!<webextension/icons/download.svg<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
<style type="text/css">
	.st0{fill:#3E3D40;}
</style>
<path id="Combined-Shape" class="st0" d="M9.1,12L4.9,7.9c-0.5-0.5-1.3-0.5-1.8,0s-0.5,1.3,0,1.8l6.2,6.2c0.5,0.5,1.3,0.5,1.8,0
	l6.2-6.2c0.5-0.5,0.5-1.3,0-1.8s-1.3-0.5-1.8,0L11.6,12V1.2C11.6,0.6,11,0,10.3,0C9.6,0,9.1,0.6,9.1,1.2V12z M4,20
	c-0.7,0-1.2-0.6-1.2-1.2s0.6-1.2,1.2-1.2h12.5c0.7,0,1.2,0.6,1.2,1.2S17.2,20,16.5,20H4z"/>
</svg>
PK
!<1!webextension/icons/icon-16-v2.svg<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" fill="context-fill"><title>icon-16</title><path d="M8 2a4 4 0 0 0-4 4h4V2zm12 0h-4v4h4V2zm8 0v4h4a4 4 0 0 0-4-4zM14 2h-4v4h4V2zm12 0h-4v4h4V2zm2 10h4V8h-4v4zm0 12a4 4 0 0 0 4-4h-4v4zm0-6h4v-4h-4v4zm-.882-4.334a4 4 0 0 0-5.57-.984l-7.67 5.662-3.936-2.76c.031-.193.05-.388.058-.584a4.976 4.976 0 0 0-2-3.978V8H4v2.1a5 5 0 1 0 3.916 8.948l2.484 1.738-2.8 1.964a4.988 4.988 0 1 0 2.3 3.266l17.218-12.35zM5 17.5a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5zm0 12a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5zm10.8-4.858l6.034 4.6a4 4 0 0 0 5.57-.984L19.28 22.2l-3.48 2.442z"/></svg>
PK
!<P!webextension/icons/icon-32-v2.svg<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" fill="context-fill"><title>icon-32</title><path d="M8 2a4 4 0 0 0-4 4h4V2zm12 0h-4v4h4V2zm8 0v4h4a4 4 0 0 0-4-4zM14 2h-4v4h4V2zm12 0h-4v4h4V2zm2 10h4V8h-4v4zm0 12a4 4 0 0 0 4-4h-4v4zm0-6h4v-4h-4v4zm-.882-4.334a4 4 0 0 0-5.57-.984l-7.67 5.662-3.936-2.76c.031-.193.05-.388.058-.584a4.976 4.976 0 0 0-2-3.978V8H4v2.1a5 5 0 1 0 3.916 8.948l2.484 1.738-2.8 1.964a4.988 4.988 0 1 0 2.3 3.266l17.218-12.35zM5 17.5a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5zm0 12a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5zm10.8-4.858l6.034 4.6a4 4 0 0 0 5.57-.984L19.28 22.2l-3.48 2.442z"/></svg>
PK
!<(+webextension/icons/icon-highlight-32-v2.svg<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><title>icon-32</title><path d="M8 2a4 4 0 0 0-4 4h4V2zm12 0h-4v4h4V2zm8 0v4h4a4 4 0 0 0-4-4zM14 2h-4v4h4V2zm12 0h-4v4h4V2zm2 10h4V8h-4v4zm0 12a4 4 0 0 0 4-4h-4v4zm0-6h4v-4h-4v4zm-.882-4.334a4 4 0 0 0-5.57-.984l-7.67 5.662-3.936-2.76c.031-.193.05-.388.058-.584a4.976 4.976 0 0 0-2-3.978V8H4v2.1a5 5 0 1 0 3.916 8.948l2.484 1.738-2.8 1.964a4.988 4.988 0 1 0 2.3 3.266l17.218-12.35zM5 17.5a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5zm0 12a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5zm10.8-4.858l6.034 4.6a4 4 0 0 0 5.57-.984L19.28 22.2l-3.48 2.442z" fill-rule="nonzero" fill="#989898"/></svg>
PK
!<&77)webextension/icons/icon-starred-32-v2.svg<svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32"><title>icon-starred-32-v2</title><path fill="context-fill" d="M8 2a4 4 0 0 0-4 4h4zm6 0h-4v4h4zm14 22a4 4 0 0 0 4-4h-4zm-12.2.64l6 4.6a4 4 0 0 0 5.57-1l-8.09-6.04zM21.86 17.44L9.9 26a5 5 0 1 1-2.3-3.27l2.8-2L7.92 19A5 5 0 1 1 4 10.1V8h4v3a5 5 0 0 1 2 4 5 5 0 0 1-.06.58l3.94 2.76 4.46-3.29a9 9 0 0 0 3.52 2.39zM5 17.5A2.5 2.5 0 1 0 2.5 15 2.5 2.5 0 0 0 5 17.5zm0 12A2.5 2.5 0 1 0 2.5 27 2.5 2.5 0 0 0 5 29.5zM16.51 6H16V2h3.34a9 9 0 0 0-2.83 4zM28 17.49V18h4v-3.34a9 9 0 0 1-4 2.83z"/><circle fill="#00feff" cx="25" cy="9" r="7"/><path fill="#005a71" d="M25 4a.89.89 0 0 1 .89.69l.4 1.65.07.31.31-.09 1.64-.48a.91.91 0 0 1 1.11.54.87.87 0 0 1-.22 1L28 8.78l-.27.22.23.22 1.24 1.17a.87.87 0 0 1 .22 1 .91.91 0 0 1-1.11.54l-1.64-.48-.31-.09-.07.31-.4 1.65a.92.92 0 0 1-1.78 0l-.4-1.65-.07-.31-.31.09-1.64.48a.91.91 0 0 1-1.11-.54.87.87 0 0 1 .22-1L22 9.22l.27-.22-.27-.22-1.21-1.17a.87.87 0 0 1-.22-1 .91.91 0 0 1 1.11-.54l1.64.48.31.09.07-.31.4-1.65A.89.89 0 0 1 25 4"/></svg>
PK
!<k5webextension/icons/icon-welcome-face-without-eyes.svg<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 64 64" style="enable-background:new 0 0 64 64;" xml:space="preserve">
<style type="text/css">
	.st0{fill:#FFFFFF;}
</style>
<g id="Visual-design">
	<g id="_x31_.2-Div-selection" transform="translate(-575.000000, -503.000000)">
		<g id="Introduction" transform="translate(250.000000, 503.000000)">
			<g id="icon-welcomeface" transform="translate(325.000000, 0.000000)">
				<g id="Layer_1_1_">
					<path id="Shape" class="st0" d="M11.4,0.9v2.9h-6c-0.9,0-1.5,0.8-1.5,1.5v6H0.8V3.8c0-1.7,1.4-3.1,3.1-3.1h7.6v0.2H11.4z"/>
					<path id="Shape_1_" class="st0" d="M63.2,11.4h-3.1v-6c0-0.8-0.6-1.5-1.5-1.5h-6v-3h7.6c1.7,0,3.1,1.4,3.1,3.1L63.2,11.4
						L63.2,11.4z"/>
					<path id="Shape_2_" class="st0" d="M52.6,63.2v-3.1h6c0.9,0,1.5-0.6,1.5-1.5v-6h3.1v7.6c0,1.7-1.4,3.1-3.1,3.1L52.6,63.2
						L52.6,63.2z"/>
					<path id="Shape_3_" class="st0" d="M0.8,52.7h3.1v6c0,0.9,0.6,1.5,1.5,1.5h6v3.1H3.8c-1.7,0-3.1-1.4-3.1-3.1L0.8,52.7L0.8,52.7
						z"/>
					<path id="Shape_6_" class="st0" d="M33.3,49.2H33c-4.6-0.1-7.8-3.6-7.9-3.8c-0.6-0.8-0.6-2,0.1-2.7c0.8-0.8,1.9-0.6,2.6,0.1
						c0,0,2.3,2.6,5.2,2.6c1.8,0,3.6-0.9,5.2-2.6c0.8-0.8,1.9-0.8,2.7,0s0.8,1.9,0,2.7C38.7,47.9,36,49.2,33.3,49.2z"/>
				</g>
			</g>
		</g>
	</g>
</g>
</svg>
PK
!<$webextension/icons/menu-fullpage.svg<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 46 46" style="enable-background:new 0 0 46 46;" xml:space="preserve">
<style type="text/css">
	.st0{fill:#00FDFF;}
	.st1{fill:#3E3D40;}
	.st2{fill:#004C66;}
	.st3{fill:#00D1E6;}
</style>
<polygon id="bg" class="st0" points="7,42 39,42 39,5.1 7,5.1 "/>
<g id="frame" transform="translate(0.000000, 6.000000)">
	<path class="st1" d="M40,5c0.5,0,1,0.4,1,1v24c0,0.5-0.5,1-1,1H6c-0.6,0-1-0.5-1-1V6c0-0.6,0.4-1,1-1H40z M7,29h32V7H7V29z"/>
	<polygon id="Fill-4" class="st2" points="7,7 39,7 39,5 7,5 	"/>
	<polygon id="Fill-6" class="st2" points="7,31 39,31 39,29 7,29 	"/>
</g>
<path id="dash" class="st3" d="M38,11h1V9h-1V11z M38,14h1v-2h-1V14z M38,17h1v-2h-1V17z M38,20h1v-2h-1V20z M38,23h1v-2h-1V23z
	 M38,26h1v-2h-1V26z M38,29h1v-2h-1V29z M38,32h1v-2h-1V32z M38,35h1v-2h-1V35z M38,38h1v-2h-1V38z M38,41h1v-2h-1V41z M37,42h2v-1
	h-2V42z M34,42h2v-1h-2V42z M31,42h2v-1h-2V42z M28,42h2v-1h-2V42z M25,42h2v-1h-2V42z M22,42h2v-1h-2V42z M19,42h2v-1h-2V42z
	 M16,42h2v-1h-2V42z M13,42h2v-1h-2V42z M10,42h2v-1h-2V42z M8,39H7v2v1h2v-1H8V39z M7,38h1v-2H7V38z M7,35h1v-2H7V35z M7,32h1v-2H7
	V32z M7,29h1v-2H7V29z M7,26h1v-2H7V26z M7,23h1v-2H7V23z M7,20h1v-2H7V20z M7,17h1v-2H7V17z M7,14h1v-2H7V14z M7,11h1V9H7V11z M9,5
	H7v1v2h1V6h1V5z M10,6h2V5h-2V6z M13,6h2V5h-2V6z M16,6h2V5h-2V6z M19,6h2V5h-2V6z M22,6h2V5h-2V6z M25,6h2V5h-2V6z M28,6h2V5h-2V6z
	 M31,6h2V5h-2V6z M34,6h2V5h-2V6z M39,5h-2v1h1v2h1V5z"/>
</svg>
PK
!<~7*"webextension/icons/menu-myshot.svg<svg width="46" height="46" viewBox="0 0 46 46" xmlns="http://www.w3.org/2000/svg"><title>Screenshots</title><path d="M11 11.995c0-.55.455-.995.995-.995h23.01c.55 0 .995.455.995.995v23.01c0 .55-.455.995-.995.995h-23.01c-.55 0-.995-.455-.995-.995v-23.01zM11 25v-2h7v2h-7zm9-5h7v-2h-7v2zm9 5h7v-2h-7v2zm-9 4h7v-2h-7v2zm-2-18h2v25h-2V11zm9 0h2v25h-2V11z" fill="#3E3D40" fill-rule="evenodd"/></svg>
PK
!<**#webextension/icons/menu-visible.svg<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 46 46" style="enable-background:new 0 0 46 46;" xml:space="preserve">
<style type="text/css">
	.st0{fill:#3E3D40;}
	.st1{fill:#00FDFF;}
	.st2{fill:#00D1E6;}
</style>
<path id="Fill-1" class="st0" d="M5,12c0-0.6,0.5-1,1-1h34c0.6,0,1,0.5,1,1v24c0,0.6-0.5,1-1,1H6c-0.6,0-1-0.5-1-1V12z M7,35V13h32
	v22H7z"/>
<polygon id="bg" class="st1" points="7,35 39,35 39,13 7,13 "/>
<path id="dash" class="st2" d="M38,19h1v-2h-1V19z M38,22h1v-2h-1V22z M38,25h1v-2h-1V25z M38,28h1v-2h-1V28z M38,31h1v-2h-1V31z
	 M38,34h1v-2h-1V34z M37,35h2v-1h-2V35z M34,35h2v-1h-2V35z M31,35h2v-1h-2V35z M28,35h2v-1h-2V35z M25,35h2v-1h-2V35z M22,35h2v-1
	h-2V35z M19,35h2v-1h-2V35z M16,35h2v-1h-2V35z M13,35h2v-1h-2V35z M10,35h2v-1h-2V35z M8,32H7v2v1h2v-1H8V32z M7,31h1v-2H7V31z
	 M7,28h1v-2H7V28z M7,25h1v-2H7V25z M7,22h1v-2H7V22z M7,19h1v-2H7V19z M9,13H7v1v2h1v-2h1V13z M10,14h2v-1h-2V14z M13,14h2v-1h-2
	V14z M16,14h2v-1h-2V14z M19,14h2v-1h-2V14z M22,14h2v-1h-2V14z M25,14h2v-1h-2V14z M28,14h2v-1h-2V14z M31,14h2v-1h-2V14z M34,14h2
	v-1h-2V14z M39,13h-2v1h1v2h1V13z"/>
</svg>
PK
!<;kk#webextension/icons/onboarding-1.pngPNG


IHDRx*:kIDATxacyZ]Œ4۶--aw7ۼzzeIR_gu厖厾n=_7K҇r=	ʓr~omUV*[w\/V.y[xk=Pj@UL~x=	U\}gEuIj8Z$vJ@xxx^^^@@@xxxx^^^@@@xxx^^B@xxx^^^@@@xxxx^^^@@@xxx^^^^@@@@xxx^^^^@@@@xxx^^^@@@xxxx^^^@@@xxxx^^^@@@@xxx^^^^@@@@xxx^^^@@@xxxx^ee_,ݘf/̆/Zfɾ9rB@~oyiؾg]̬YA@v502._Wo̞wOѱyǟ܎=wIm۶mܶylm۞:9NwJLUOEo @Y>W$='O~(	`x{?
qCIˢ$3VT$wqQo~ϐ"IF͏c4HR?)R<YXÆ$鎯7R<v]Æ$@A:lHnHf`n7R<+$x/`$x/`$x/`$/`$/`>!Ұ-oIcF8+Ra9^[3(R׉ΌcJ60H}fF6)RjZ
H顟6ϤiHCUnTS#ƹGDZ5-RQ-dHӶF|"ҎsOl7E=
󮍴StWF4iǧS"aWڲ?R}/ro?G"_nȥ]?hH?E(R@/`t;+r&o?^34T)1Pu^ћ}0@Xtc/`2`;Ƽ~x-˿_?kbGSU-Qsҟ
?R݈-lW^[%[7q(G~o=Q5wO_z=WcWeэc޵c:/``*wɛkShƆb]~=zwo9aU_W%<"m93DnSc<Wfgq~3a]{gUG8j=>S~j9w̪sP1
^[[6n\I4K4觖{x'n/@xx?6scO-]3Z]isU{[mUs7l+Gw{Z
t[Ƹ'm9PscJuL{z0osUU{i1Ic\9XsqLio?2{d:0ެ;{үzXeCyg%?ITc,0v"m8Rug#ݖNn8]ÞO2&1.U;ٛn,ӶfWE/`Kw]|t<Rٗv&"u_fX#V'4U
3<|F;H仾087=z–ӑ4vuv¥_?bF,?b{l>Yް%Y{ۿi⪦}:4yS8`HsGɑfl?c7~6=XCce`jU=r6`f-"Jܼ=E:xWWFj;2E_
^x6CCRx$x$x/`$x/`$x/`$/`0J0^I0^I0^I2^+I2^+I2^+I^x%I^x%I^x%+Iޒ^;hFV*x/`]1RD'I/`$/@
$x/P$xRx%xx%+I^+I^^I2^8^I20JW0>|adxE~^I2^9
fv&h$/	^{ڶ<Q_,^I2^Yث9dٰxVu2J06`=}]8Qϯ5J0=go6>{T+I^x7
讝md@7~>tOe$/`*qݾ)o>{w3J05_ڋY&w3J02̀gWlm_׵W	$x/`<K6ޖ:x%xx?ؿwQ)ݛj$/`o7~xU6ؖ_.z$/`xIqMm6w?>VoԯWWFK[;oWll=uCFx%x׈/OF7wu{^I2^<ahD]|b6H0c.88OpX/^IH ~\wQ~>saeՑ"7WKǭ16hzGWoWK1,#/-vhaVjw"DboQok#-N+!(#/hI0R|:ZН*Jt	B8xhEɿrkXW#W5U"UP
ؕ*O.+U!X#h(R.H(PfΈ3zVc	0E"FXjyTbcx4Ɣx
YCu2B,b4/&-_!52#Gˆgei\j!1NxvHԧE"|؍I_&mġN#hZ@KH~^uZ
!#/04sHv#?$iHxs\"wZ֜-dIbx}x@!~	57}CXǛWY}e\Jbg#h4dӸ;y\nx*ߔOZ1/C#9qJ/у>|)甸6b8A1F~
Y"z%Z‡ʵ""ܑiq`紞:]Ѣ[Zhxnh=~csD+[D3I.zK{~\ѪwU{{dwvߞ__=W|Eܛz)9>R$A%/`;8ɣqq0T0Lݶ*Ꞷ
	뙩@&ۥ	-pؓ=~yDk4w~:t)__=_Quo8Bz^knᑸۼgn$x/1ıwwAmsQLm]ݰwW6wQ]F7#{^EW'ݻC]ÒH~E\߲ӯN4qbpm0]T0T/us;\A2(T{ͯT'q]~;tVzTsr{_ͶίbsD:_TW=b=xN8x†NO"ˁwU0\MCsϸqsOZJkwi=~ջeݻ!ZvYϟIQuT{4b[{v}K{+3RK^"ŒY7w?y:
xRiU۷E0z#x/𪭞=Gq7uH8b!zǮ]gQ^^@xMDնMuSBc'w}}Ǔ&_g{yKVV]q1/xs]AhIugń[[7W_oGw+z˕sx#x\}v`Nn2xCURn^
'2F%/3F-[wx|&u&=mf[[:wx	^@Ϭ|X,50%v,a-:B
b޽k^5@EoѢx};F%/@iF57ߐI*ֺ4u?)c^/ oX2֏<%Z‡yc&2*Ra*ֺߖ^^#xxfp)wcտnGKHf,{N	#g@ƫ*zdŖ2c^/ 5aȩnHUU{cK^@}-Ǩni?TQ-}c^/ %M޽^~4q땩SߩO!'^@f;d+Tڒ}W	,4}"x	diX3DEXomp	Bckε	@=Z%9ܑ?xf	]}qs`.1/&!x6ٸ*eeDBX@)KWկ/+A#hT`
5|;# oEVG=$/k`̍x
xwQv1wޚ?`x4	!{Ms$n
=}E<<KD'1F%/ bT@Ԡٚq'# ݙome_MnG}OՐv=1 ^l)BiPy )#hbP;tHRlmpRqc^Mx/o)cT5מ's?~c^Mxv'MiX3DP/bou	hx=xӬJB00¥*|+z˜rus>!1/ wʯ-J7ȡ?R3g]O>t\b6#
x@.`K|K/`@GLDR~IU'zPDXc8ԧKus=N31o@^EMWi;~BuqukΖ&+JoApcP#r`ȑD
AxUCexIW<Y}\@.V# $vO]kAxl)-_'h}Y85EObf/
 sO#E-AxM~+<k5һcEmH x)s*2DWtåW ;6'DN%/(!㸫NPwbw6Y^o4fx?p1wx	Ṕ7֠m;V'c˜R\vpO剔5%Lt##z`g;uyNeIyj#v ĻU=r3[EFume_bmVJy#T/-WJAA-$]'/脵ZEW4o]hSKlGߦK^
[x`bJV6vxe۶~Nϛ#G}{ltz}0FF3.$S˫^t]9ϐmM%gWB6+dQզlBAZ<9MNVVx`߲٥ФBn{kV3l:@-*voy
xWɌb݅!w.jНgY9}_Um7gSy; mYӃթVC
<g~[W/Um?Y,~Wo;ۃ-yo n_m|޶*u%o[6YX&$*&^3nxEeܗmwެS֥}v:-d/ $m{WC.wZT5iޢWȟ*8n>.g媀:"}6'["W9vz==oM^@i/<FՄ\mۿL[Ĵ+"ȹMOloeqhsEoԟӋmwȧlmW dŖ29Av+Y<n.ghۣmJHRg]pJv]7/_hH^@XbnqZC6sZ峸IAwמ')=KT3ўWqc۰zoH^@&kUu}!xvWꇕtMmJSND36vwON,j;ʧ!xr/O#KĶo@ݸ?!oUu{JL<O/ofm
ߑ\{
x6^HǴIZV
we!;n	I	esqVTW5W8%'T'`"9D{%3[YmZQIoIh+cD[+Zim}V5efȅ7k,s[o~]C_˗M!7o^<(CѢVg5DH]/n+
x,PQֳ(	'¥~k(jC$n>.˓U,,Vamsƒ{wۿwxjEƪ(#Y<lJ.Pdc*Tmv6H%7wx|bwsn곸ۼzPM֧ukQ1k?MohRg[ua/ *zo9xۭn}{~EC,pVUՅ&x/w@4ː1wxো$ݧ"w1\1nZ*de^
/~8'"HnMhlV7	@3mT7KGDv[u+q7vI*EW@l\lx]\E%p=xjT|Jx;ثIx<6,_k
ɦ=Guq7/ _VշSAZEm~N$nGB4p%S|x#bjn
";|xJ{UpϒgNm_TLjsE/=+qo=KF7}k,/ t,mfߊWx;	wȷ/^]/טԫuK+x5
"Rտ)ҔMmmubZ[م("D'{0PWl?}'6U`nz

.xM;ո[<8{[^AZYL|ſ@o]Ae3
k6Se@{>X4x@}HWgYoxۭ-t)N_p:mNHRo{;=ϡŢj@lUAxX+EboQQ5fHm1E+zw^.}f˾t}ϣm(
x^@NH*"F_O=iaK(4!xek@w3<ΰ?Wx@^
+7O"t;lR
˾ܬk@
|&lUU{蓥^Ё-U5(f5{l}tn[U
~Z0Ӕt=]->X*&>6"Â&m?F#큌W
kYBe?mhTq5`:?b愋6ui%,)Yox@@^Pmim٧J^slb^5^9*jˢB0p76T<9a9X8jSA5%^nL5PyIivʘSfNPp4Ʉml  i7{i%Lزz7[W$elҸ?>U^<[=9(܃׈7R٬12OWxVI#iGNW}͟XkhM3>a\}L<~qkdM+4&/ϰhHkZk9d]\~Ͼ16GRzӸ4u[	ʥ(p{Ӓ:{y!'jxc/jvOۧw[g7#/ ^y6{>>y[^?(VnAcъj;;2>kT#3#^Е.edGЄ+O{oXk: >RpAc/#M1OnCOn$^жYJ_`Ϥ٦gOq']tަxپ
1:AL}F
t{zWx@/KugRxY%]=iվ[/_;1.w j-Oؙ;Wzz~YVR|3nMm~ޘRvLum]]0;=eakU63wzk{R{{=w	4J̛z.,^H't&ttxpH}~wӻr^@ ҤS:ٿcN$x}&n`\
>Ԡ.xT~;*^;Q_?</퍌5ncfg#wj2D`ed`)ugjW^ac<-	yo06npu	@R+R	l/XoeޭyzϗP~KeMm(x*`6+n;SYBeIo}FOB]k;b/ 1!)}AC't9X%z71NɲTl3j	@DtH9D(r2=Y77t}nO=QW{zFGt9x:Y{ٺuay*2;aL{Q{ec˞xΎ^@ ljc:Y}_}ȟ8oɱ<uZM7>On}?~Kp`ظ[UӠv5xT>߀\JWPoG@i'l%"sO|N/K=JR{5!]/ _"
%mܮAbSe]88lluC^fIEq:YW9w7!KEl>06WwfsO>rS!H
/H4tBCuofJ{z>{gM]\3Fpi^RF9wt/՗>16[coFS;GRZKqw]
^@`Wj&-e_VkCqlSWE=yӻߺnK_
'qd-9_O7bF,9;2aO.(17f;lI[:o9^@Z9琡^}p+n[;)H~m)G+5onzY3X2͑?6cJ椏eluFG

x7{z7Y9/"/\=ؗݱv}<c2:>]^5r߃YῇȘѧwO^@VƬx'7.Z^/2:~ep(m`QelolQ'^J= _*eLrlI3rH޸[it]RViѧw/i>d%/#MRI2<EWJ,WcGX^w}}\ޭhj[{	S^_VXJ?șͻ@OMu(kb(D5{J+N39@P|RgTv7WH4ώxB^ǎ,mtyb{qU	@H&WEYw}uPNxs٧x-.-P6>a@،4Hu2L(*^2tx	=v߯MNOg{ Ǹ/,gyGс^/ !ɳ6Mdׇj#揝nt}TY6=Ru@&/:S7tWBHaU'ђc~mqy5gY`EjoFxΒ\WcS찫'wʱ2Krt-Y;Dsd_׫Vc@&/QgI;c7iy2Ǝ5S'wF->e_4/RR(6BaVbͳޏz}r|z7C%#/ T6Bt^1Ǝ=/{Z[{}F=ehD(Oi
,اQ	K$ץD0mt|:bx7teE,~Sw<:RjuUnjTx<!lsg'=ro#S紴E,orrK^eAlu,K
@
Rڽ3F	/c3܅MFB=Ww˚}/ `]JOƊ֝/.<ώ^B[^2}+p{>?vĕ*/uJ9q'g=v\K
?Ż5R;~U6{z׾/{}&ZU0{Jqy}^?.0=rH^@ v	a70Uv>sNȌ+=F^Gc{;d_,ۚx[)$MRƉIw7?wzvx FpsbB⽪)yMߠѧwC"/	D>3)C9/7
c&oJKndY*2oOx3"坟4aןv.嬽1	6w!x4-.MM=^gp`7xr\vsmIvOG@BHW'l5_\^b+=it佹>u٧wtjD^oD*^pqw`҅v` 2n0:c<GJ5ãr$I^O;c{Q x>06lOQ9wp踛ܮ#
|#	qqkGqy2>{Ix4PmՁ{xcSxﭪs>4bt-ijqxxw~]kvP :nuxȤԖ}rHIxJgU3C^_`죣4oJF/4lV'/_"eqoOJ yX"sir4tES7mҼet]z_iA{-F޻z=xm6>|͟q| Z+RX+59}=>12,OyEʾ߃7=zqU[C`q߹{T1x@3޼]^J| {]{/G5Ψg{0kϾ28t{jݧz同Qؒc?qx_*ɼ'iحY_D%8ۧGK+_w}m|":$/x_9Ǭ۱S6/5:w}B{ElGꕾQρfʇd#xYCVǣƟ踱]98ߐe	DO{!&@e-mFݭrHWv	!3+_~4P._2:\EƟޝ?<J^F)e#&Ne쑊jcoU踛ܮx@<wx,2!#is //Kx/2DEqӻEMm:Ʋ3`	5OFM
_XiE!^w/ '#wsΖ|C-)4&_nqU	Bόl)7/c4"~ON^к1rqz^GiEF]wc>xלF&G;x-G6
cpǂxodoYrA`t3؏)nܝer޿vfї7]rH^@aԙ[zlQз"UޏF7SFmSg尦qM-G[ԟQe)3{/g_ΐ?g%37ei?e]{_ /+wKCx^w~{B{WSF |SʖО{ԟٴ^chϟWgx|JH/lGx@/V< 7J[4[3,K	!L[fŚ'H]3gX3.MQ1RzBs,՗Cwgzc^@Tx}xNxќ}ԭr쓻rL~j4)O#٧Ww7Q1P$݇wXm%2{Z{t˱ۏϫjC~t]_ޭϾ~:]5nOnjC"/oٝxK͒|Qo4VVVe?xD_ʻ _Le=Q99.~͑嵙݂Eڋx_**98,Gi,7b	x>Q)봙ގ^ؾ'q7;ӻ6m)nㅭrŭ^{iq7wd}-ieaIoIIw/Cx|q-n3zo*iC^hK97/c]=:1:V6m~+{/(>;Le9V$[zbunu1p{ӻuG^#!)716WҺrO>'D^CNw3N^aw|GWd| ƺwk*^\ҫE!ޢ"O.C"/1qoV;3ӻuuJo<ϗ&zc뮢Nw7u!x
o";cƁ1AMx#5ؑ nawS[:4["xCށroct୩U۷tPAAUXX
UV֪9"9^Pปs$?71ƎYݒi֊9NDpXo(4dz`m~U3Ee݆պa7eg穴2,!9^0T+U< "mV(c~mqLa
zN99)gר87-~'xc紴tzƭlt޼7!x@^/cX_[&?r
׊˃zOx:ipK\Ec¾ʺ}rH^|{ϧy8[tDdNgoc>=%
^Cunjzx#Dx|ڑh'n~LDWTT6	/ /1vqS[YY?e]%D^@%2jWnaO+-xW_9x{ѣ<*iآYx{蔷F(*}]V#,޽c=;e-)Ju}::^Ƙx}r7Nx#%k99""7:uO^@%22ګkx-((9kvͭ^܁ϯi,h୨=떖V-y:'
^]=ӎk"|{^>/x@r^/c=~87G$UMyzGx[{땝޸tNzyyF$W 2T8;٧mwn琯SYYw|%	^
}ӻ*,qqp|k	 9/1RiS[ȁ7p¶V99b{{+<OjK ^v@
TTT޼UTLvn,;xcYw>>*((#'{qٷZPqq}*wZUSi9.| d;&1f.+,,
ֺMz	,^s/!1w%<ݺ{jN}xl,׵ 碑	jݢ
;hwUE"/HkƘA;RRnwnόN]fS޵o^@	xZBTc̠=wKKPumK0/#1fIh0>7+'rvÑ<c]G^khqb:4w˫@=VQjx@^{g_/Ge]cla48kjYr,_kF^ނKxE9zc'Eܭ
kܵTyUxîT^#/0?Fd+7ʱ~+c,g*qx°^{ܸspݞ=^e3uѸUU]{_!~v^@^θ.Wq,?xcCqwkk"w-_?xcwE-((xk!x1k[WkWht2"G-
xUwEܭ(;m3"xcoN[ZZiGר&x1nkY991	k7x[ag\޲j;l'_tk\]{yy1
oM.!x1dݶvdN'	b79.YhDݸ-MGx)x@lxcqΎ{o^N,c#*;>NxܭcO65p`8[_qfv{aK^{׫=%Co>
#>80Eqcw>>.nmmSݥӸg/US^.~8cg\ƸEEeFޝz۟40e(ihq

;jyeoSظv{C[2c~ƿIL;l+38eяh9JVnoV^P_lE1Y}]SP Z;zcwV
KC[nfݨڊ݊un^6ԗu3g}ʽȘfxu:6(tϭ_e̿X],O3fekuĂKnIRo<Akuuy(}:_iGgК ,ǕZZG_ݮ떮֥ϼKy1mY񇙄C޾apj.{7kϢWo4"zJ~e׮{Y<VTUK):kφJm%xeYr
cv+v>_ٵ[5K*A%/ֿՎo`#x'&OQ6<yu?܇kr:q7GU;OU?./CkeĨηɼIa	cc:ȅlUoK#>khi^ (^lĘͿ8]"OkqK	-sR5CѹNY	@ށލU4T5WxGFt8ͭa	YYvF~ gli\xT>dDf_dnKKW0󰛙ؚd)/kBA;HxF4-݌roNkj4X%/ɽZ5G=72z<.ϧiݜݪ߲HaY(/]ih7H=?`x<-S45rM~a\iNxfø[OnSS,R0S>[5{y /?kvUof۲I
H+qWcc|>fpmw /qx5V(=vU9R /riլ
o~fV!
E |Hԙ&5 U?!U'*^XRٝRiev
cm
g߮+T)9Jm7ԙ*U=*e-mzcߗ\JKFG$F>7u(Za7.JRR#21RRkRK o*p*7c"6~\ʿRj&Y^MĈֿU!iߖa1 ;#W >#/m3[,+U?8kOq,Ns&w*$'εtMI
I^}go!+Kc/бC}jyo%I/qmVHLkXiSR:ic{MJ}Xǭ_/B>XuB8Gbd3T_{y׾t˒U/дJ-
Iĺ$MȦ)*iqey&@u쒶}ˤ(/_!_xץ:_mD|
 ]RBcyZ!v'etIڷ70̰̌23333319ْ,[x VU9ѭ>\fxc/%q/YUŲDZϰGK#"xƧRO\VT?bq|
O6d2;L:va_Z:oeaҶJ,^ba_'W?aulll|R$fU^4#U=5>&/N1q~udOv
{bTUw5
S?[mP;vb=A#mM<累꼲8*ER))@흣-v3ԡg"2կ53nư0oM
7bV&q\1v@OyXD[:R#eTIwoJ;F`$-'{4](
 8
[?ޚEpu;Ɂ*/|0,BS\l+ς)_͜3U 'pM4
]%Ry"s<J˵;/_;O/?u,HgHvOyn=pp==I_{n @5z?nX4wD.SXF+<J$F>+]?dQӥ^PC17rF4X1?w*WNùRbggL58#nPT.3W&dw|'ʻc(axAӹLw*6B\iZŏWqTh{m/Sq3Tj}j:%gGK?fS%rP(]fŒ
YƎ-6W<RWMʯ*so85@l7f.OZiӥeO?Tj@/Rd愓kZ8B)\cG穰f:*7}(g|_Ƌk+͐<J,ףF6I-mx|I>S|^@fD]椓\+`n,VNviWabyɾ̽JU)ۥHmwJ㳵\.<QԇV+ս5W=/Vy:Ui0aU[JI"ͻ.Ϲ^n:&V2*-(}Wa[qz?>}1W1̔?!ӲRom
d^b1B%3IiKs]Bb#ظQ~߳5x\^+T].
ҦxURqTv@%N{:ȫ?S=2k
K|&q%d~s{k55l}/yd2ij_]d^^džt1y
F;.yC]w=͎;V>3)fHvU^r\1Lnm>r۾>xSOD7.z='l&;̉Z^7Jd2I0NOVݨdeTωL,ϿosΎ\58tϗLseþJM^]nӻ/wU/DU$vH]4u<g&TRsv7P͗1&]<:Dj?	+>IXoY	_gL2b/.Q7MϤ=*z6~0^,|S)?nGm$@(D
3mN:A-Ǝ
>՟;v©~`5	h@\(Ya̽N"PicHDzWG2B6},'[\i}>so`
j{5IxRq*Ô?z2zF?SN֟nNFrɾf={uʟFnpT7ΕJ)/B00ɞvG/Z<v6/PEºFuݻ1}gm`ڿf?ͻ#YaszJl>Kvx:WhTr҂{يi
 r9B%3)>zI)V;K9<wĶ$|[CS?'M>V'~
V7Cvj
 I0}֣	ȱPghN_BY	%OҝZj{/ysbdvz1]㸻R#C!־)47:z#DiPTdN%r2F%y1Xmigfdyvondz՟&R^PN2Lr/.grկ
\q
Ew3O|uCPQpZrHVGbѦ@#df\vo2/8t
5Avw	/\.<lLfF<o.@\P|Y`6^/NsZ׶C?å ˈL~0X/9t,xŵom4,u\T1zt˔>38szB%c|^)ޝQ|oT J%s9IT.wJzuܖOѝ;ŻkÿãPx@q9uX;
祉{Lѫ??]S\`+{,h^{leRmv_{NWx}G5r{;\|/)_so&	L-VYgkyɚ9-mg&{_1p7\;0?"ߡ.c5_>L5aW^i߉5LnۗkFDZ5W[`~o0H9>Żu	cqT5/ S,ǯzfz`>l-ꔖ>6";eOߴoyBCkOTMH찻a^<){S\šaiS\3>;G\<%mrx%U
=l֔@ r9eowsSXF{wŮzuw82 oNbcoU
+ݞ\R{;X.@JG`_$p]QX:{w[#MBcf]Oon}VMhZ`EpO18WCV^]aN"ce
JW崭yv6϶yͳnH_.xjBev"@+"lhpa[yv~ڻ)ۉ<noL)?kbX@sxb"P<X_n{wcwSFy̝C-Zݝ='^hXS''c?؏ǥퟵR`q`Oc?+<{ǺVPVfY|Q]6
?@We<ϻqÓh?,6#t&ϖ}\%vx`
;~*7aqGXH7+F]C솝劥owsj4sL8&7w[7]%'@
c;YiY7T?M\Xi{;kL[4{qY??_X-EgdkKmϲ% ΖYņW]o?$z0AYRbε
 o:oUltdsW.Y^|׷~CnYrBiLw1TT{{*=?a#@Mӥ\/!TaSQ)H-UCۑgYv#Eca?6_:}`/
\poߓy(:n+\^`s톞RRdNϽOt|Ws#Oupx?v|:?M0)TIֿ͗Nտ~VERǞӤ~Eʦߋ?k_&TɎOL1w3vHUZh?x"agEB3*vPptzԻ@r_./n؞;U5щߍɮ!ww*<iǧ]3#*;(vh:N敥gvׁXG'	ߕyił%[sݿTCn!A^?Ű
ҒG9	亥9gNIsgvpGA^+Jsr{ⱧEIj}5Se>wR%P}w°@P-!nkWSi+fLH/iiu|Nj.%v{ϸ̛)d	B1lcnYg	
gwt$8=k8vE*gTKZTX3+GE|=fNn~ڪK{a
6Y*/;7]ʲ"|	55xRJj"S_#/i*R]3fAlr^ґJ=eq۶mFal۶mm۶vw$kUc~ާr~ՓhÙ˔q@Ela5'lqrt	cgr`rɬ%nTNʱ{puy'g{O+5YT
PK&߯ztХˏu2$cnR*
UUAĬ''k?Q\tqW+[Uj-K_|D gzhN߹9̐+ïUSW\U
칞7+KިS<^gʈ	@}g?)V-	⹾
/M*0	`WHL
蹜 ,v-΄_iIF83@ qwCXwLΨ)
/MkKow/lYh&utЫotm֓v_.Ќjɒ׹×bϰ/ͮ֝|g5Ӳ5vdOJ@@DJ:9&_I]ƽ縻^ZM?Y_
-f߸d"^&/lJjy?B:!Cv/>o<YrhFE/o;ɑi' @dZ{W'}f5(~StN;%CZkCҶ(s3Z{m^8)^#ljR
ž1ɘ[Vw/lf\T5j''a,~_cI;{l_$˥nd{8p&ޟjcX¤s[NS-3,)LF1@dJ&_prmY4捋]coHrjc&;~L}Hn%IǖGȂdII]d×kPɄ6&|2Ɏ_/\$}Ǔ}cH<rų{důN|/9(cksqaIE-c@Zҵ+98?>dϓ?L,dԆԆrW'dlQ'zJ]&6xh#e>ɡƾɁ)9zH///   ///   ////    ////   ///   /x?c2F x/c xUD}IENDB`PK
!<6{v{v#webextension/icons/onboarding-2.pngPNG


IHDRx=PLTEGpL
N^lneeeffflllLoka4sss```___ddd҆aaa^^^}}}zzzccc]]]\\\bbb[[[yz{}{~ZZZWWWY׬R}s]M\PVfcZ	r@%~3ߡvhKΘjaQڿټx,~Boy7w
KhnVdg S_b n69Y
(\yNMO/Ki&ղEDG>=@jwk@^[TXC>`tRNSlMN)uHsIDATxG00g'-G>I ?Jm}L1z%^}&:{şkL7Q JzsLJ5&IƊ=H#ʙ9% Q6HԢOD#& ^ ^ ^ ^@@@@@@@////x/x/x/xxxx ^ ^ ^ ^ ^ ^ ^@@@@@@@@/@& ^ ^ ^ݺ (x4`Z?ΥZON
fMi9=Wvt^&2+3ط-»KmZ-+	oxws'wBx_/]z.˺u+xX~ ..]:E/^^  @x@x/
/^^ +0@xWx /@^^  @x@x/
/^^@xةc  `CPu_|2D@/WR+^@/W+^x+^@/W+^@/W+^x+^@/W+^@/W+^x+^@/W+^@/W+^x+^@/W+^@/W+^x+^@/W+^@/W+^x+^@/W+^@/W+^x+^@/W+^@/W+^x+^@/W+^@/t"^xA/ ^+^zPd"nWuŋ{+Žo]b^7wga.(6!]5;QjisT+=N$"-~
״]X6S#T8ji<x~6[Ig8^%9FhF9e+x^>BZ$JIydw鄯>^:7Eh_enƻxlb|+gK$x޳8[!>L:'q^]@kP	2^Uthm)^,P2^a{6 %eNvH`=o`T1^IF/.ډ?읅vFFߡ\S81.J
‰!̌Ng<U=v]]%=mR?K}&-cFEx__ץ@} =#9,g8aPx^7A,b@c0Yb'gNx^#Eb%v{5,۲%395=#ʅ
\}yۄ((ʕy{cᄑ9{\ wi5&<q,ʹa>&%xp>Ex^Vcıl١vyWՏ!tExM	ovBQ'	ףwI?(‹]Ij3|x]JD<wž7D׈c]?|8!ADXYIbƃo{5'1lK,7NEx
Yf$vg~!=3xpjRx^7Gz\oXݵ
Mƃ|ڤ"Eұg'(,`^emy8\[ǃok^:ͦQ895VEbpEy&xp)&^&} 熺-Q jZx^7;>LmVzv"P߉6|8^ᭌ(])zz3xT^ˉۜqpn4σjC‹޲`0}OˑB)p_6||MNL~Cx^[~Z?ؑxBg}i3u9^}xս7TEx

oEv]3V\Z\?Uup6v޴vKoExZ\X'oEx
_v|ܛ

M^״f}CD璝%×^e^^s~xP78^)^VQ,O8^Y5ś!"W>Y XGx>Y<8/kxxk*G=px7/kxx/́Gx޾	o6q9"}^YpxEx%ߝ8
^_+{S{_^_+"J g@?Ɋ	`!0c˥kd[^ӔUwpOx#M{!^Wx;NwE?
o۝]C`08~Bɶe0x!^!7ޝxsz(M~`0
0p7\`p/E/+{w37t
{å*7.ׇxňyME#T`p
	oZ[xňT/%vh!^Wx}pRǸV;~/+GCGi>e@FONw2pv6q>'#q_dJ[m-&NWScJ@wpuRK֧Frh#HNoo)ivޙ&作Fp4kY
!DЛKڹM*`bc̆9{SJ<7t.]?*+s*U4mQ䫝??:U'[vxJ>ޱA5
ZρMC2_~W:Ֆ@ŢCE~6x9	?Tsw{X@j`:ىC!+YCH,2f>ux/Քz5Hu,qH0GMg|&3^o??@@e}:xB0GMz6.s+S]vF_xdsvuS&īW&G^2f:vR-<{%Sg@QWK[딭j@c7]C\p)璉$ᅮ`օbXǏPzۦx!&Ui}2
>z/1-R֗R
@&xپxK20G-r.?ޢǛK/Վje]RmK`y.|]Qxsgo.4au2ūkuګ[*>0GDR*c¸ ?R&=GX/W0sp)k5G҅1Nũꑁ+I0G.%LW7VǍmE(^wrmP}\%a0
\ta83/擾//';Eu2:F)#̆Ky+?[x`7{hu~
x:Y@xoUu2t_YhHu]a4O)4L+؂5lV'PZ2𣽽dO}ĥLL:&q.NK-jC(^Mj-<}\IlN`&K86Mql&^/wHUe:Y9. K,5f-dtYqFxuEQ:x%9l+ɺ͊.^fРHPWSZ|6eXst&x'Sx@:~Lgשq
@ye=ku<!|$WSmFyoz@C8;A19lTo81ی8-Za
flz;/߀	^γG?Ӆ9̼Oz^Rg`u2oz̛x)^61G-2>-))P<ZxER7s~'N9,Ƨ?n`u2o_Q}'T/ao9Lj*&gL,L9Ĥ?~ErP}D^+;;_p!SOS]NV&ll10LBO9Km*V'Cjf>;OYu2iҍ1.%
6^uau2f;{H<<L$ٿa*n?:^fTi	潻|A?^5cfޭ_JE/3b(ŋՌ5Zʃ=;OM:Oj\`OEٺkWaE(^f0жzApUзiu2v!P3"ee*RN:ūLe+iIG(7@/c=HE|e?P(^^֔^n}5p5cvB2;SƷ*ŋml)yHnk5w>8f3wm^'ro\kZū݀Xkϼ;_NF<V!f0/ƅ?:Wj8*w'x3f,bF	BPzQYlC|<E6)8˘
n'R'rv|MXū5Mdѧz/aW!2$/J%I&Eq?}n"p],qɆ}ȱk_Cl(?.L%T-d(^HlTC(^Vs£A<${"zR:W	^Κr{;GU'&0
[_,FqO||oϤxm?Xūەd"k*xMCOt5&޼g̖^['Jm=l:ap+?x/WS
!ob7V?
=Ϙ-Ю{V_hϤSŰŋջBhcV3lxr\r.fLI_lٶj-@5z܄ͮ-?(^$*n%^Jb ^^vqȥőcpn>q\IqE6+Axh)VR_klk ҟR0[8Ω.w$)
XP,M'Axuބ&
nㅢ"ϙwFl,<ȗ5ɖ
.,0_B/7l'Zhki̷QR$_=r2]k0,484FFEƛ:D*z77kC(snvJɼ^\d|Y{~Bxc=UiWbkj_vx-zh=-mlc.|ͥؾ(1aJ6zV'CƘZe}*kWxpcQ.ɢ+s}.SU 5P#lӅU%NxczP*x)2f9\.eZL1UsR>[0]jQ(8lOlkz?XcA$ށ|{xr
F܃V#[EFs/lyIj9s$ȺgPes;z+UxYu26Tnge*bT<:[
|f]pZF~u_Лd(B߃ZBxyu2?As1,XIrQo)GY}{V/.:7$ֶOd#Ѓ'$q)l,[M0QJN\ˏ"l]Wf[=/ūI6ЮRRu28?;N]Yh쁲Uz<4`3N9GѶ
k:=//7ljX#@r)}Q)W>@!9
W_`3c33

-MLۑ̸H
//W9JZru2xq織T	G>o\@f	Ej@B=蕇^oy:җ1d9S<`f$LD_?0@1]/x)Gࠪ@&S~0?}!f^>4g母˱oxё$Yѷ\B(3xypg%Gzs8Y~%^TIf:;?\aGZ//ՀMw#āI66\h3##t
gǤ r֑y2JW(^
hwx=¨@ro$

Q戙o>/sфaƙ33gf8tSmOf\b:]/(^=n
(^'ҽ\ʤrsa$lȯ'\d݉j	at	vLn~]lTdKd(^Pe]dHPz9u!ruP0(tšmuTY~}e;M?CٵiNρh` ~<mu:Յx=o`0#58tͦ:
K,ɯ/\`'\p\fƷx?nUs_X@j€xm+q$؈@!o/czs%QXⶌ꾸N6-t:Շma!xYu2֧aXd]nC+37)
ى_@l?`^Fau2ū	`@ɲNs95\MXnn.ɯ?l0,SmY&oL+z^xaM!ЈׯNָ#N:s.ǜoJ;3驀‹y365]?/Յ
`#oAu2lAqj3/7Վ?wn	7[6[ڀiu(^ū|t?]xCզˤeFa- BcH'lY-Wg*FP0fy/ŁAîq&f0u0ܒ'l٩iL-T.C(^K8p)f2V.6}k(3 4m/m,v(^ūp-oPee&`74Ɇ|<aE߻(G(k~[@jDZ,^/>R#{\eeG<p2[_UK8X^N؀Iau2ūi8䈗X2
YPm!>VۀxdW/6+É+!lр<ڔ_
nҶ;dau2ū#/i<sٲ_G.D(^	Pl!+ָ6*z{m$Siպ
?Nx5'@u2st066f,M/eE&
Mk\WvdWsT'sg+nvYR Y6_J7:՜v?̇ʋ
\1q)Dۢ`5ocS(^	PY!!#̇ɾw?q!5mOEroڸ7xxN0FWtq0"ڵ)# K_;oq߼E&#ޣ߾r%_g݉{o7Qfr~OO/5o~g8,=|sHq痋0$_m:9( ~օp'P&S
ϬȋJe	56ٰ̻e'^ŋso)Jl";܅\j9;kV2ғ/FlbQ4&z'h?VHP:ˋWMfa5
ٸ|$]m
8Nkߟ}]ŋ}3j<=vy>y0my;L0I$I[ճ1B0yF.uIQ gpOd/ؼ%C/Gz\5
@uwsP?sLQQxed	P4{\Z>pN&luw8L^ھF<z2AV
Nx9u@C*ta])3G:7}aR%nOd
ލ#\+T:lJ<f>_Fe#KsG,C
x	ާv[U\	?yk=gpQդjJt3Ϸt_krO]
>	Gq߿Լt+^oN+@#	)H	]jnS>Sw?6tp^
?V'=V.ݹ^f4iPS-i71
JTݸ:yRLަZo8W+v=-;`0
*Ώ[}~m'{om˨{F*%PWqìNmuO	xan+X*-QFЧWEDhzV5?zuIAc?
mL٤H}2
x_zkwJsgCJw{Zn=~d(Ǽ?3|K23?A?6^J&gOWKNzz]ɐL֤x{֯w|Λ&
_Z輟V>&
x.V±uZ&ZZp[sm1W,tHtڥ5("?ʻ<i+H#o
^xY4jzjY)k֩yYT|/cG(~>K^V[t+e9%W&лJvkjNUo0oBϯr
t$4|SU|?S#=>w,F+md@{jcN5(2
ٖq
>/g)PI[O&
xX3c%]@Ҹs}s[Ԓ.9`߿>'3ZC":bshPW+}%S"w݌$-)߿>IIh+b??k԰z!W꥔i\C
;BCPϏY/N
<|QL5_	xާG`}>I|{	-y5,wO[&BF
4B}dw^&
x^5 j:jbn
S4W+8g3|!S9="ok=3PW+UkHepB	л~޻!B
PnZ/?
yuEϯX/rK*5x4w0}Nvk#dw?J K8;|+SV/=&
x)H
?S>?S1ߧ޸QHz3nI:^]t	XD
Fz*^iwzR{߃I:1I|@%
xQOf%W}>gb
EovTp|Nw>P?bKnxgv[ZyuLT+(Cxcǣ{8m~~I&@4O@¶HW{39oVUI
=1y~e{c{c{H?ߡx…ĽeH/Ye!cOyG_UsI%F
7nm>xt9w^7p$>VSO^;Ue
G$axs{͟rzC{/P1w͔մZcrb:ac FWyC?^;vߦ1rWtG-3_m3~/w~H(xkã"$ſӝo.ދ/>W2s};vmOW_~YU]$*;PW7O*t	m@]O^/O@.^:>¦ƴoۿo~['?Ajgvg-S9ᄃ^9xދNzб=7L~z.j&,ՆG
9xާ[wTM;`pI҃x|A텅	3gH0``7mK|d^xٰW+/qo
tnt
|_v/Ōo, 3giT4gFcMH|@{f{hs/^ŝd$5jjDOo	zjD6&?FۨAMyAi~qUfD$BOğ&O}ti3ǎ$x%Z	]~NW.$$og+~zZ-93	D^䘀7wd$N}6|A]z%NWU9~zZh,4

ƙG!3,ވW2%N:՜SMh\Êqz{@p?d#֍\ǫA*>_VLKP;@d@Z|d	~2y~k򷜴}D6HLu$F^w2>On@`pPo@9io˹W1Xza?e@u$;LB+xV9M ֿہIWES7ӏ\ˬ+žPؽ77#x8ŌҶZ+x@xJ.5@H{v&jd實^k(aTABG46t$Ǐd8=M/ŁIڀx?E[ J܌kG(p(C=fO~g^o&\t"iGw<=]sH}8z	IQe<%FqpLUevs[ɮWPL+)_]f7@`a1;;>=	vn8܆/_,oD+y39c2K6Ӓo"N>>\hfy׃	ۇBj)^Nvu1,۴W=\0\Y^7<>(efK]E`aywM#;xϲ</xeu2TR3N
*D l)zn2|(xL`\T/g>9C&Z,^WgHWOpCmh7+To^[1`Fg5Ǘu"q$ڿxxӓQG?⋀b`^n'L5Puo5ɦCtF!GsC'^h^)22G 4pP}͍NjzQi׻OV_K.ek:#mSֆݭ+^d/K9=/E	h+rnG~YM1Okw}a25;5<<[_xc.ћPUۋ++mf6b7xupķN9or
}&tyC<cKWҪ1 ݪM<k#tzIq=~&qOTUfBMA%^+xsםM(xA3L4{HcǷH|tadʻa$|LmVўK7JRC.]m?kꦨ9:N-\qoT
E Ao׺Ieu2od[Pnλ]-/:{?=%ݏo~)s
'״^nXďdQ@7_Ae쥘o/xMcw58$hGqw#:W2^(2.=#<OQywVA'%`P %>:xϥ\Z)/h`|ʻZcQo
x
%0UEˏoZeAK#Pc%>2	xju]05·P}704.po	sÂd ?n4V'
x_ډୠR*Į
}%78ֹaJ`%"+R}qduNe ԼOjF暐}M‡<֯]65x x:Y{v΀$"4y<Uݰmȳ,𪄦),V@>*wiclLϳ?3dGz{$w39N6v$ٗu?ܙ׻hm{ !r{f/<wO\6>!^5_[[\_,B!c.IR~+xK;^΀CS~X52D_qbC-7_ĈfPZAhl&
qReW:-`EmOE?/߹䮵PmN;y$L߷U>$1LePFx_Ŀs,4JcK+lw3k2{ѿ<U*xx4xb_&$qBkmƑ%DMоyAmy\įL}gbb>ױQ۾DܻTŢt^47 P9_}4)xC#35տw4	14۝ ȬNU1hhX듴M|.;{LܲgvaK`.QdێrR)en?;k1wQrQŕ%P_
+R@Wo'6 3Y z6u_C(@7Ez)~+XvWId-sVM,u4W_c{|xc
BW̯{l5@*xvjW`Z}8k"&y?&nfl]4>|*1/f~;^^N,
pz:Kr5E-j[}pw.	La|HMVewDq``@	~^o2{z;= ^A9JgCk:o<;\dY~lI`\s*WoiUdTԗ#ˌJDŽ] H¢_[
^3%$Q(=`ӍwJ!+9Tد-[rU]fM0vG{?(Dܝ]SAca{JyuW{Y;_UΝnGݾ勳i@0!
<#OOISK4]EWZ*:B~8fsE㧗(g|;Yz
ުrGo/kr&

̐5Ogb?P\kF_qPuU*x#_#`QUxMُ`ȯs^ޯηzUQ!-nh)C\Wz!>j7P+r^>/W//2~Gj;W
215brv4=:ZziKWWHzz;a~'&.-1	Ŝk&n'[S7_M^Ny)
ְ
~x1-Ȁ_n'q}SN:*xv

('e8?rw_q}{L8U道)bD+RON0iUYT,c;Imf43iriwOy[la4ꊋU;dS{n6obfɥkɢߕmqhjM^$J`V{%k>D8GtFtccpw	-oLzM^)C]CQxt>DDx4z
;gWQy~W^2!;4.}KkuӠi=lޒ"	H7e.D_{I~*a)^oAreIGxx˯cCUnv{#XU.ݻYsB~~5xYR<19OkyPO#]aۧwY~YWsemu |\*Pk5f7#H#T2T$[YC<9Zm~7/;B#]1|f@.A5Z130cv?]yn4d ݖ 
En
{E:=/~V?y
51&[$SE:_^|v͛O'HI8Nie^;mFFv&*^
~I^6H֡Ç6:r0}o:$?	DlnOeoV@lxX\mF9s*~yU6Ȥuޤ2c2OͲk5N]M>B	%=fb~@p}{XX3}t2O]͖$\qJU%j+E/[5d7T\2g<bEXqmx۞s%-O_;F/=hWUy
FjGFyI"ӏG<C
nVem[ZyQ7-2dj琷x
v:cL~[z):57я6JqUF~K7%*nWG}-y
(>PjI?̮0vˀp7I1~m.Cnpkɘfqk(.y{XmB={
<)ݢ"ː}m^_GtwXG.ܧ4m_W+jx|Mi]]<k5f7v@'w`bϞh3Lzߌ{i4")~\^o>xc_4ũKD{w?M߯&Xjxϔ6ԭ%W^o>x񾟡ǯiL⫳^gLÛ1'
T7Ujx5v.rPQg5nu
/Z
\}Ƥ(d΅*>LNJS,6Co'Ç
c \@`_~3kZcq~
^hh+k*^x
XT4R4X󅁉u_>	AT7Y@XX>
<yu͊^/Cm0BAsYa#ݎ{N7*ʫ
so~Z%S ~~~f,Ѱ%ᔼ^odS DSI*s$ǧ0'8uX6w
296nk5NƤ\*ȟ'wVFB\kۡȓׅv~\
r69R5xt'x&KfNr!ѝtiEَ(OS^R!pDw~ikPuxsN)0ƈ'_v$C^T7xwhqF,xDkDY5dk
*Kh'q,	tI_>XYgϰUx%k%rm4,iO
܏rkP6㐰K7dLCr.~b'
݋LS+/wT7%oz
v:෡kA9CJ:/anW|.R/tՋ9+q

k~#>UZ<WQgb?~?TRhibRYBXhWBBBȩhfe{lTfK۞42hH @8mo=x̛o3u>ʿEI:rrxͽ;ͻ+/c^7(#f`^'^{8
ܽCmk$vˢC̻ɰ;[@-%M0XPgnh`嬆q.^]ի׉׉r^7{Rcґ
f( Y粩wI
oI|
wA2RFֻ./r]uj]8"yxx	DŽ5ƾFh\,ԻzTj(e$KdIg͍4 5b<y
Z
DEޏi6ïwNbڤlgTyzErm"3PÿKSXw]d]6Խ"F^żN.wn79e̥Y鵮MP/(=C	¼ޕo=RaWep}dzzxxg3$EP[geN-8곫xeVKE(%wjvM1OH׉׉w\l!H2 9`3un崶Z`XWvHow
nA. ͆uuO'x_6,9u@/KgZ/(8b>')4<d!^ػCw6ގuyk׉=~m2 Nwق1Y]}fE1.Yۢ+4dȽ^V{~:Ç}q}B&uuO'TZٞKdROq<.z CL@.k[1-FR7&^
ȀO;
A]Mzջ<E^SN
r-i6hĠc>z2oo}WgKkwa^N	ʕeM=Nu.Cݵ.xio@y/=g34CfPc02w^ɯpwy95ٽ?p`ޏXy%b'>$Շ^'^tK1McU˿n,%e]Eb@%-	]{ɴܺ53
3&:WʼnKIn)k"yx<KJ:xUe;]>o""v>֭ùާ2.H5l::"z*ɠqؕͶ"κI/[_PB=9D:*7mrwɶT6oFɎ!	cnM8=m^+!`l؇5p=/
J杅z]!s:JgfxaV]IK>l3tc>WߣByT"KJymL@ūe`Cu=ͳcǂ_q}fK@@[eE޶GÖ"^ˑ.tNz
$^B<!cMvlNu=oLBcтOeh3DυNC?E/w=/ʼnw.Po+ヿ}QNbm/xKhP&4n{:؜xxRw(ٽn3.	Wߛ[B-^¼hs2LJȼ/ѻCgnp=BTifTc|5W>OfPP>?
W߻A`
x[aDG$Cr^5ջύNdռ܈$iI=nJ]Ե|#/"vm	rIBЖON|l6z=57}:^UEyJ$B§%$-pxR%0y{rA ͻܼNdy͐&+%m'^4R{:2/c톹3T]N`#s4Ļ_ċj򅮿bdv╼B~xW	gFa.&44/xln^'tb2|p3XEBG-Z^7b/]m^ZtxB
)7w&7׉=ʔhe,׼u}|4B>ԻzY/SBa4׊xC!^FFtrC''#މ<*)^|]o3BIzW/;ǽy3'lzAD:)Qīo4Xh
6
̻l28=q*wkW/zHCoQ$#"e+W_-z!^2/E8RRxGWPx+U
h4Xm0Vu=|C͗X'|،"7ͱR#6#Wzh_AF^2/#.]DhXo^WO׉S%6U&>1p\mś.~mC\~>aF:457_}#5Wěh@w7]D׉ _
  TI42
qߴo6)Biaana-lS防6z
#Z8f-eP$T]%{8jdB
XK7j^xx	O<WgIl:\!@pMM34aM6,Y8,Z
y!fFPBG!^m:l_WVo{MN'fP[C%5lК#q}Տ$.Z"un=xoqy_1)fF+s35KRvWBo{KNGė)H%FMz)2H^G.[88ժNv;U^nfъ\0jl}$^'N{]P[7]z(,	ք'l_י)o'^ׯguV$[
ŝ50br
z?u0ǟ'^;`?Uׅk%oS
WܨI^^KS85skr<!^0!Y3o4X

̫7Ž"^'ßyݸxk&mN0?_򋚠1[m@"`٪ו,zNZȻr
Gx<ԠW{gmp&뿤Ũz'usq:V`+^W.X8K&6&Uy_f:Wv6QzUju=urqŅ %*ث/xݙpejS>2rrr*xGJew$^?JSj~/S?n"|ߛa;/Z8b<2oxY%6
Ip&borJ|g;k7zթ׉ĘFq7֭]1{{l?WKᚅ___	o]([\|@KKs'{;k7C2/
PN[׉81W,(UU؇m}ziY8i.i&^v7yQ7yuuЫCEA<,>[|M8+7]Nx4WzX	5zWq۾4ԥ`~K㎅X?=MK+4M^pNNJxEat)-nW>k>?ly^/xg8QM4ǾJ~w_'q1ǣ{f|4/.x$1cHdڟA'4%BvXy^*I$BKϯCHcҹP;È|wF#;S<9r_qaO~5D[~iKyO pLq.JgyW_7{# HrD[w"_h)q-±\" #4tS@TvSs(00	J1S}NtE_|{0>П.Ounך,;s?s_~ZMo^Qc}Լpnpmޣ#ooNhEק=..
յxcekipj4CeR
MvSW8F4}L]?z{z%^:\+T.~]h2{}j?ӕغ<BT2IaW+ED58A&^`: xC.^8YI"<ތ-Mm-/ED
^Gm{{\F?S&f8l?zK$k4~ȷ?^ۨ0Μd!Wqm4!=kNg03duX`λ\K= ^ 2T0g]Wf$\fKV4+nx!puFлăήh=o\$޲@5EQ/YzkV8H3ĥRu\x;GW]tKieP=x}9gNmjw
P?=ebؼ#^oxe!D7~D6&gkWO ZWiXl+}C)h7WE%kysi7[I(2<[b/0:Tx0I|̋WKY<J!|h"_{k{lx!qş󵕵>w6	yC/^/REJ,Mf6{/ޞK<abּOǓLtހ{`%2{)n҄fcbϾVf2x׶=#xx}m3\)fNC@=$3TĶ^U)Y
f+7vO:_-xWX!9_>Q=xcn8/KBm#=B赊
?@ޕ\453 x'&|bvTגS#M`eU/+zI2@cxR/H:k)$3/7V]=؞,i|\ɕ/UH6w<^Ȼ!;5xCD:1ԉ8YKȪG{?QoTwMᣵc,^硭MimFx"	I}O$eGlx,85<K6鮼t	3tH"K=$ yc7
m@Y3Y^:w
$#z̛2DY	/ZrsxS+;C/mA%x
3f+DY,`<ZV tv>
%$!╡nDM}Y/O-kxS/^2/Ļ#$^MV~Dު
5
u%;}0t{hHG!"*	Iyk!juQ؃~&yI{{024bsȋp
%/K%[Zނn3֚^qi=+obi{xěNVx!^`B@q⭓xoxŬj0H6]h\e.>xmP'9/heaa>NmyWF+=]BUk $^	7ω\`n]6,09M%H;B⭃xᾆSrs4ٚi∩Wͫ-VϯØv@OqW@%HCMEku-WExօ'OAͻyyLx	/.o
1Iօ۸i57*;%!$^Up
&9ל9`ٻix6A/A%xb+UfQ.i؞te+HAU=%Hސx%iP7CxMwc
	%
x/+g'w|+y+\GۈjRCK^?L}=dWgTͿ޹FW](;(/Dn٧~mqʟk]vi 1r5@
Wc{D%"޳;|{wa,r0ɵxyw=i')]=/V6.F@y1
䆜C/ޝ *$jr#;Ca޼fO&iZ;OOoc3A4
ڃox	/W]λxKE3D%E^K.⭌D#a/HA..S>-^>fXڅ|iݚz^/A%J;Ԋvr3D6yox/~PO߻icB%$hϺzեբ"yMU\:ZŋinE^/A%"62E'@=iw98Lmx=nZw,
xwJ\t}[AAM|v\o_#MMEau谥l[P	猄tGb;@ޛq_f37O~~3&7Sn.Wmx3>.K#ʝ[/[K-0YixcfzK«jxŧw~8c~-?.[Km;DZML/^}.qWX4hxg7
7#.qUYӑɇ]W1xㅃk6]M+讆W4[Y"+/
(/
>L曫<"??Qv%43
of^u]nf.X֣awq&!TEtmBxq\؇xO|]X3KFëyx2[f^yv]xEz2z6`kVcan&J(?|E[jkZ]:jxu^l/
/qWT/|ߢ/wb0vq@G^;׾
-i{mY讆WxwY$L%S0N3J[`\Δ^b&2oK#1uWwsW4kxa{3j'O^BI<
^w%إ/woTQvs)^/,_[yUqzWwEw5Oûҷ(}kQi]ށ`ÇQKq(xCuSV,xG/Wͱ@JvKrPÅ2,av$殆7ixd\^LdW#\56
㠛frۤa/-cι :xWRV)3YmW5om&O~+oGuf%3of+Qw]tWëoDoGp1w۟
#cHv"{e.T-JeE U,W+BR)GqښnP.>]7]P^pV
Lz}nKu	E%UJWV>wzy[	a`:%ҳRwxaUV#&ac^.w+|tPc:%tO5鋶oJm+P4('c>[V `Рgٟ.x2"x^2*V=EA>wbN5&㣵;`v]
ok>6FV
sxm~خffܮY/lԈ^=y<*N?Ηoa_Dw51OB<p,0xӫ쟖:wI7
ބ{_{v{l?DoXU쩺r]iOʦ#檟%]:jx]^*•k;x}üZ{.w|;NVBWa;r*lxMˤ'yMkߓȄEw5OÛ^Y*#
0/(9kw
]vȁ}^E=}@0/O+oM֫m"!=\a
-q>
/gSeB޵xPKq9xg`20_Mw}Bs]<Q.dvد6[m7}ɠ#:$wA^x}V/dulbɃzm2#7]VqRՉeei8^ԙmBxOсW]
.>MrwByz}bM/\ĉ`eqt;^p^ar6B˽âFūO{O
k9>5Ys8)jxukxW^FO/ެR&8oÇo|Ըw%<dӪ{YtU+U=o1f?:qԵ=^8"JGc/.`v55]r%ʕkk}w';[[7h𙁗w'^%͡P)p49;vxš7,zy]G0/$w*/sy{l!|
"୎땻7಴9VFΕMRIy[j<LhxMާCwQ^.fTrl\}a%7r<*lANBxu?Z#^q ~.ʫt?^b1D$.{uDi.Mڶe]&{;jxua) TLm|vmyPȻykw/;uhBy^kαK4O^/|fZբEI!߫#J.}\I<7H6}۝96^q}὇ixaW!fe|f!|;DYkvrk_Hf
^'non8aRjϰ<PU".	N$I[<.`JwsTZ'w%ޞ6xO*wm=/+4~^ci_BrwD|gLb[ͥekKx)BH+~
Ne]Bk8#낷U=t[gIFńwo4Wȹa7VAC/+GēĻu˓ֻvzoUx%.xO ^B$xxgGEͻ"=􋗾sC6Ok/xK/b?KN)4xʯvp
^I"5@(^*^݌wnW';Z~ZxNL7?zy.	škx,Ug{uiog:j-1
^B.RoytÎD\hĮṁ^2@7 
t9Wq>5/o~Ax}G׾}$xŤ5@\+y]wJ[/Iu@Y9&DO6<
Gw˔YC5!k%J˼Y#dcS.
o9Wdn÷y}e-N̢S$.Sy9Cџ滛/k
c>4PTꞲ yUUyQk9ydQ&Ã/ּ^Kn!hˊ+:p/ ^^Cf
p14\
Y1cjW4}HBBK򁄌+˲{2^ ^W$/7e@a30lh	޲ ^$u7랉ī5,x!^B:K͡?QF5p94@=ΞSmn'9GBxenCF ΌHE˳5s]x=9l(sYH?Zsv"3^@6yIn1ZyC%[%x!^
BOcJ}Z󪋮޲>KBxe
f>4urљ?`N}Ǽ۠#J_cɴELVFKȊB.Eہ[<	-o)S[gI\iq'_ʏ6GoV4Qޅxg޻CÔ(
05[k,[$OR!8w
Fh/<d*+%֕7/{+Yux yyz[|)Թz5{v7ػq(Gʛ=sI&ʁPزN	z,-[>J߇K6^+|KܽVmu^%^[^+{UG'wwEVvyʫDk˻J3]ڭ)f']K6x^"F^ɫO8>ۧW
)+Dd^#\g?}[ͽnjˠ><D4f^$A^zR~[=&Z_w&;zgT$aJuv8K#BަU*=k}B$ŮǠxhbʻ_Q[y5;VrWkKW~6S*=$q!oY\]LΒD+yEvVgp6wdvMxd^/[fװWηo]n}6Q|۵/vװ ՅoY|fMx3"^+{ᬕ9yW]u`ɮz7
;<"=P
޹
oBf06
/*Z3x׭\7^/?$S^;<;mm_JuC깹4L;^^^55waR/1UV7
KKƺa|.ђ_]iU/]+iwKK7ߖ~(1*?R֊x{Dj2n`wʅц^g5x=^^'-kFUk
~>nmx	xW]דTS*?v-7
px	xw|{mެ*N0fGRnN«X$"Zր7?^0~HU)b`K)Gcdk\NfB(z?/x(V6r޼M&%р*E?z!u]mdS%ـwG.izWUF1M?*}|\^~-cYZW/-ͻoH]|F)lorJg^#Ma^;	xSAf/pm
762\հȇ7ge,Z	/xw߳ѥ/{g-OUl
bɵ_4^qR\g1FTQٽ/]9ߢ7KKJ+xx,`DQ]H_S2y1./:K^W͇?;7+%j/x+	ޞR^_,@]IENDB`PK
!<q<q<#webextension/icons/onboarding-3.pngPNG


IHDRx=PLTEGpLMᗗ׿ﲲY-kHѫÇߣӖoϐG1\Cmrژfff';}RpwJu	"i`ik69Y,Rqv2Bb&Ymrkkk-3oooiihX}|~	ȳM{srrrmmnvvwhzzzQۓbڇkݤpZJReؖ԰2ԈbbbTTT	<&O[Ϩ%pkWJ{R]?QQQ>=@xY\]FEHccc/RYLfNMPUUWI]`/jOeGqvQUWGfiM3@F^^^Z___XvpcجR}`ȣVPJJJVVVLLLUUU{{{XXXaaaKKKL>2tRNSlM4֠9!IDATx؇0@AdˁL݀5-~Tuvڦ«5E*]/-î@w?3 ?nnawb&tk kUdPG2CȨ	m 6tJx@x^@x^@x^@x^@x^^@x^@x@x^@x^@x^@x^@x^^@x^@x@x^@x^@x^@x^@x^^@x^@x^@x^@x^@xth'o??Od-HOw~{ޟqy{Mm^`>T|xn\+oxwZKL_i"̟ܭx>عHR 94Ikf-@x@x @x@x@x @x@x@x7`sz}RncU#]|U|::F|5?4;OxuWy!OxuWy!Ox-ވQǾ:Oxv&7`Ƽ Ix:Nx‘7 Qpud
Y7)@xvaހY5F‡
 Q!/o(yAxf?tި]ZoTa	5Z#	o,l@xv
7jk I]፺o@xfaC^ޤp7jnF¬7if
 QO^oR+ፚ#/'x٭
	oAx7
Y)7ŏW3o@݈:Fxu5ހ1{t^m(yAxEԾ;Vp?{F	qgzWkoW^Wx^Wx^^@xN	a݃J~?dthBhsq6)u@oMxs@o&)Z8{um}duFX1b,'
 ^})~Ư(;%$_*d;%gjSxC ^RNn?K^j
ԿNx_"RxUyԻ]/F
U^xR7(r"{OF;5yFCZNos/񚺼Q'>@gQ2˹˧KyZS?ػDg>gmm
;b@Ohlcby>‰C%B1kXu@[ZjG%ֿW=z[x9^8N_usăG{X8шnD-8i7f,!c
biP 1ВC=n3V6qapFǗ$݆[w%n דyqOޖf-!\2Y4;

w]yq|ŧ9). ƍb* .o^ɟ=hm{Wt;oxد3mb!qv
덱0HkI}xeƪ6
_gÛbiX$f,5׊6Ȣ°okZIv~/c&VGBkҬ$ DM	z/o^C؝M#ױE__Û@=1*+`lA`c U7`}>NoxMamP&ʩ/B?$n	,?uR u	SxIRrx-a\Wֽw(X5EJ,4I`mxqa8zJ|+…>Vuc9qݰhx)
/)~<V=kfXkKS
غ!Syx12MvceXp"r
G^oK?4ӆ,f~kRzc@6)+ÂGoA ]i txs>Z'\E枞?I6hz͙x`InX:ر2,ľ*1)tqjÓHתJ
--=
o8ƞ]9uim`.u)ˑ*JjVr'%卯u7-Њbaj'\<ac/_֝M3e.
uBuH$9VfY8phР~#e,U޷0ËTJXjHuR!}fmb\jl`.jf6]jॆ7Y޻WSZr/?^ZXkRvxd˛.ڢ\;qb2-ys7z5\cuO
ULfo>|iExXSvx[Ȗ7]
'K
p!UBdV9'cublhmRG7N5jp\:U/ҞH8$o(:po5@6z寏F/0H~9u\3KXWB?]TaRh,pv$$0c_g?`bHi8ϭSM/yÚ3'XQAnU9U
X_!9}S;}ϟ~ϧ?қYޫK
.U^BkH4'RN1&Q;p/+oXH0\1j<Q2w޽?:tgWHݲk40h.%bCZY5x5٬w_z%on%/FGzdC	`[#](?8޳;କwRUUby!Y
X01*T\~,;A8K^4<*"RWZrL^jywwgY	}'SމA!r^E$jB^KQ8wtݬ-grߞ?{=v8AW.

լ41/P^Vk5CڃG}V%N^~V~ϻ+n$'U^h
$
BBW !^/Yje=jXUޞ`ݗ2+I.^atw£siQn''tZ.U?뇞ŕJ~]BxlMkCM7T#"$jmZhVMu{Q$WR
Ex&Ze(WTq:Wކ}!^3kgq`WTtŋqxƅP\:p݉oU^Y]:Uʂ$]W^gWyx{6ά|_^n(	2€U^ru[k
̺|t4?I=W}xsujZYe,NrC@%dqc-u#th(| 	ރڂY;:טE
0*gt'Mw^7gu˚u16PMtG1#Cx^h&h{̦V!EGo	+Fj6.J5fR}v7Y#ꂧzs{g-‹*UMlBת7BuCefff0ɐ׊cwu
wN=n&&%|~Qfw~%ڗ*rjЗ^`ʘ=";^%c,M%iq"t"5h/^<^C/PWʇ.	/}N24`!{=
LxN3ץr
|_^UW].]V[P
sKAsKxrކ^̪.3OKxdWl.I
z8;/ cNx3^`AuWbfbMŸl5^,=vjc
k⎯[X/
Kemqi^Vkɻ/w9^šl}l/7<2qA.pwmF@x	/`\[;ִ֞NKx7쵴hyCoSjKxZdqG]G`G(/
wяER
!߰ϓ^:Y{toSe؁֌5^1OhxjZHkҰX^|TFJoVFXpMz@x	/Z49zkDpmKxyIz^[|B7 87(W+V--t3Kx+;OVkھ2`^v8c5=&KxvlP5^=x
ݍV\5Ț^5?6JKxXZx^`to]+x]?]z\Be4+ /8l
j(%zxלsO<jJۻҲ\=[3[8=%1pjކ'_@xObxǜm}('l/,p-e	o<y7ornn饚MuV?TmI@x+^gkb2z#ePutxO=OMF@4T5އ$',ZϙUA6Fji&[V8=g7a2@x^`AsxeiրoB^‹iJ%&N~x~tf3vKqGx!V(n$eg`=:w~)%j&]\,R=ŭ\*~[q^[%=J>ܽ_s9mg{>uEQb>q0b^‹>[K}rMȻh7ΧvyJ1@x^7%!On/y/?㼄"'v_Cԃ2bQ|ɛTA֌^L7]2fK:GSe^‹u}7xx]RvROP3FO54Ta3[]ޮ#sPgy"U$ {.=;
6;h;(>Mk9}OtQ$9R;{K
ܢ /p$uy^񚯇6{
m$YLx?3e+7{;MH.Q*x+ɺ=PxԞ@O,TM^{$ޏsRKwbJ1PFx	/NS,-y]uV]@x	/vĶ|.-_(V"I	/IrN#k%4T56"ǻ?y
arٷd׍(k}̳D'=UpXlAelsLiged!bƿ:|B_&7wE0ӭZ|Fw]
/5T}J(|/ۅJ'4^x"] VJV
axYi^x/**{q0ҒSx.#^Z>dJ:Yjje	x/rX93\(.hWc^+kaX.*4p/W<05mlnm,JMwwDvĸJFse^xz-&4$틨E5+"]kH$+n&n[tb]8#?^xzwø7{o\Ϛt^+o_yq-1K/4/V\{)?x)tJx/w9WVt>)sJΟS)7^x:bԾ؟?|muNw}^[KK1
_@<^x]}7U1fo_t\^ۨQw%$GpsR8.[<O^+u[~[۠A
?>Gg4#|*7^I4OJ}(4ۿ_x>Mq^xw([Nqt^xy_[^qŤ&%)~SI'x/ͶUQo?z/,I͖IɻQo?/sg(DRx/EgmnRu'$W6hTcGUbuvbRx/EjOL}c[7hPslqOd'/^|&mS}_Q{4QD->.M'Fx/EGm1=fڠ}(5M++3^oSQ$Y0%<=z.J/\♸<ǟj
\unl.30T*Ŀt’Ix'^^-JSuxNVn-)xxiĮb+_)o6-xxF̽v_)]y!YKgVksL6^^ॄV*/
1^^।[,{/oQcǎq3:ݤU.GZ*w8귬Ԋ*eFkJRfxK'drS</NBޱsϼvjt5æRftjaKk޲;	/oKY5y6g^^ިxݐKKo></FQ:H*\^%&uw^#)ywDLTZ`DbQ-xxWȄon=I-{/Wm+No`p(9Exx5ވWJKCw폤>NP6_׻yTDmxC_?pgدЯc8	#!/-DO8Y
xx@_~{.υC7$/=x/ZXzPLT)jEﳧ~?S^^Oنb*M-Ħ^ޗf,{xxFA1aZՔ#x7򊙪[ׄY;ܹsgMfn3;(;B&^SP,	{1馕~Z]TX7QS[xw@{IYRމ7$棭 1^>fSkjv3s&52/oCYK{#{I;j8y2/0//X,/xWYxx
xm+k^^exw^^^^^6PXZ(x7ع5`x	xjYk6Ƃ7<^exx	xxxx/ZZe^^e0/M={xxYjXY԰2AK
{XUZm4//6;L;oRt/F[:	xxx)uxM}~=+޽
xx+YK/;׀xw%-R/.Z.;<e-xw-'uOixY^4szsN=c3;~`ޏfީO`dkdMtXNwWV݁xxP[J/o$ҽ-//ZxE<uEHNuxxJk*jS JJ^އHnق--ex9ޝSf+Jگ(BsR./[xiִֺ.Be
//0,$;w}ӻhZl.5/o9K"V`/xE^"4얉^/?^ن.RҔ3VSYj^^mxEMʫ-s
xxihk-xxxySxx7‷//F::ښMxnxx6/5ިaB
xx7\-&݁x#xKo
;s
xnOˁe+^7uXn|
ss/XSr)5J5Mfrzxxgʢy'X-D,6(xJŮPeݴ3V/de[([xc7/#U,5kbKwG)̣~?yt|GM?6s7ӽpxxg^QaC={xxC%^q^-S},3u,$xnz:KՑ6PN۹vBL_o]wrE%R&o[o	oBD2P,vBm;"7wـOe$|o7/N'IMy,鈲1}}rׇnKK[NnI;B7/xK;G䄉5^^-)9a2//
oMWyEx^^ॱMJbP)i*
^^ޒ"ņ^^uuoona][_g^;5Z1æRftRU3h0f^^DZo*/_bHx:v-w5UhG .,-^Vw_y[y7__6m\1ë_!xxxzkقSrA/u\B/-e^/Ҹ:#2!xxiLx+Y=NuA/ҘݑuxƃMݿ\M]xz[*]dw۔dg|Zo[&x	xN]ɲ ^%쾝Cs//ݧvD///~FX.4oǪ^^^^kJ//VF屮 ^ovz	xx7Oݒ^^vL%u5/Bæq[l`l}A߸o)"
 Sn(f!޾	YWNw11yL؎%f)"#Ǜ=pwtgSx;d<s9ûRD:z_v;Bj0%j(\)eI$C":`:䝌[«~R	>uW'Q
^};$\w):$yC/I=Rv D[ûc::>s{7-#18slDT1`:lW/T1#^}@D
/v(ȮmL0f*- =𞑔ý[0tJ#:watxnkkLlL7n'"V2LIxuxjk.W&wv	f6kv)Q:_/*g8:/,U@뮿1KVU!5\0FRgL9XUa†^eVO)k|v6:#K9mB!FhZ!:ڧXxwMνKpHHu0%[mnGtj8;
}_I`!,jCj2+'XR{A3%Wp$X~	oi@V2LЂ#K^k
ѻ޺RH-$	טUx#HA
\B~T]p
oaf.Ro-85ԿIކZ
4Hl*2u"
o΀ëûtD^^QiJ\Ҡㄷal3c1p-sVW~?ky;U!aw6ʭ^{pj'z{GE]6"{3.{::FD~?2we~XED*Zm9dxSZqb[cmpQ91SG;q˙;]4x\&0
#,'2t	`R',#%˴{wW8c?ۘ0ͦ!61fDeWW#WDŽ|%XxDԨVyS	텉h'%;?Oؔ;
e.*\Qҹ=mqL$*0EL`ȜBA1)GpQwxĭ&!{>!gK'|FD
&LpIoo*LIؔፀ%g\Qp=:{7l$b#e.U
kn/=`7ި嘔+(C¥'|xkJez<^ϗ!+M0Y;7
}+]73LtvT].'o7*Ɔ5^r.R@0#NxSc_IIp8᭺. Xd.YV)tx^,<'֖^s,	[jqCWvxD@uemm>*
MpW.8-h[}ⱶs61W 5
`Ϻ\x۠Z~xux5;52\%!҅"rԲ]m8/OxG{*jnsR	/MwxDVT`zޜ%ng>Wp::>	lP
OyUC!v.jc8/}qRVӚR!_Z'k"^
1ŪErn۫)^^)RV";:[Q{
%8jd{hMekJ\b}r^!o\f\^R}x;w	oySsSR޵,Es
yJrkd\]

p*+QIx?CWzfK$Dž|
3ꪆ-8u'j4Gޒ2׃^jA7$z;p5y3 ӏHuInŗ^^ǧ
o GDGv"ۗgRVK D\=Ľ|xOq/RD=5S^ wBTޏRWZ^W9kQ+>.`::KBRZ>MxiFxdxw3>dx
t(̓VrFk%|xN"dܦ78ٚ@Ts;maPKmpM/{m@쟤EMKp5r&5hG^;˰XeG::퇧oMq]6M`kexDd
K^e
5GwgB	Vx+:4޲.zpWݖkڣM^^[[jf_=.T5ؼë>,A*ﺫr2͇\n7n_g=W4o
etH&lFI	/MH'YiK.=6LmTxO[;1R8#(RyǮJ;]'ox\&\BZ,S«̇7ጼNdzjup~~{L։[)zZ,VH臔7bW6VX
.f:	U
*X8ʬESIPsE[eXoV<_&!auAZ::g:OOW5I~Έrತ9J
!ës:	fës_#9SI5f.=^W
f%wIM{Ѵ(+d	.{`;;(C4\VRu~8/52222^^kx72222^^kxexex
52^kxex
522%05^ukx
S^kx
&`5^a5^旍I^kx.	^kxD\\U'S^kx
0_g(ofc5`#zPKGG@5z:^kx^kx
oq;P7^ޕkx
5w'~8-^kx/d(M35=2uSH9kx0cxR>Ǡ'574ҿ*P8+2ҿ+ww%^U<'kxEÎ^H^iI^ihkʻ258Юldx
R忖^5w+۔
*vS>2W:+~ތtGH:PTNǕՃ:zFW޽Θ
^kx=Pof
5}<5W'Bܫ+n^ëwzo5jKJ5WK;>kx
>+}S;6kx
/ao
5'wl^m5WρW^agUjxfx
*9nmxfx
&u\/fcxfx
Uh=>pc^ë$F9ʭy^ë9#4ܚOYdx
9F8B^M10vƖdx
խiLu;+kx
րp>&_xex
U(⇋wiW+kx
{5L]D%P?^^kx8ъ|5WK/+5[@^^kxրuI^ëۨO1`	X^^kxu^Fc
iތ5ګ֊77xE^kxUǀ`NH׿5W(c9M^%ЌT^+=c@Je5	PD_4SYdx
4lǀR*/|G$2W:^^ʙ6SYdx
ƀOl*vz7RRYdx
䮥ש,2Wb. DJᥜPIe5]K9^41Wr)
̥^iFG%kxRa|יSydx
4ĭyN5{؍Y**j&MHZ:<) kx}V_^ëyz;m
5ׯZc,/Vtl@h@T+wCܾNL"^+^"ފx/EW/E!"^ċxx+^ċxCE"^Wċx/Ex/
"^ċx+^"^/EWE7$^ċx/xŋxoK"^+^"^+^+^"^񊗃ۚx/x x+^ ^7 ^@-Wxu)|yTM|Vm"^W/E"^ċx+^Wċx/x+^"^/EWxŋxoH"^W/E!"^ċx+^Wċx/x+^"^/EWxŋxoO"^W/E="^ċx+^W/x
M/W/x+^xoċxAxAEEӻ Կ;f~ċxx/W/9"^#^]&(n0IENDB`PK
!<OP<P<#webextension/icons/onboarding-4.pngPNG


IHDRx=PLTEGpL/Y^8X\FVX```fff^^^TTTeee]kn>fnJu~aaa[[[bbbccczyy{||}}~뉾zݵYYYrrtBBDNMPIHJSTU>=@jjlzy{VVW___\\\̨[ݯSxaMͦU^NPh"EnjbtQ~A+˓"5xp`9$QXM666&&&֫TMZ\H^c+w6nz
tRNSlM`>9IDATx؅$AEjƥacmJ62}SMkJKz@7oꐹXۻA`'U؟w0T>TSIm6u} ԇ@x@x^@x^@x^@x^@x^^@x^@x@x^@x^@x^@x^@x^^@x^@x@x^@x^@x^@x^@x^^@x / // /  / ;n,*K&Ƹtw}x`khy]_(%<qMww/9#?.ϛ|@xGw>\רɛ
/;'C^YEr+\	o&Wx9C&N @,47Dac^W^^x^^/x^/x^/x^W/x^
/x^
x^
x^
x^x+
x+Wx+W/x+W/x^W+W^'	x^
x+
x+x+/x+Wx+W+W^W^
^W^^7㩫^{:xho/x+7x^x+/xx^x+x+/x+7x^x+/xx^x+x+/x+7x^x+/xx^x+x+/x+7x^x+/xx^x+x+/x+7x^x+/xx^x+x+/x+7x^x+/xx^x+x+/x+7x^x+/xx^x+x+/x+7x^x+/xx^x;xJ^wL&O/x+/x^W^
^W/x^
<x
^
x^y:x+x^x+tWo7/x+W/xp/x^W^^^
^/xx^/x+O/x^v/x+/x^W^
^W/x^
<x
^
x^y:x+x^x+tWo7/x+W/xv/x^W^+O/x;f1CHm)ҨS9{EDK";s z\TCg鄗2TTU<.o<<vNx	/sL}cg9^Kx쾨ߊҳ 5K-x,^昂1T6^›u>^S8|౳tKx _<vNx	o7;K'9\g΍	/́~]^›᭵4ϋ_x,^Bm6_cg鄗2UƎtKxc
~hĎtKx }}bY:%91~{8=v^ScqNx	/sLaeN,aqbY:%154:_,^昂e?g鄗2zο7;Kρ^wΙwa5!1.a]`n7-wIn{K{EzldvZcC/_.\wvwa+xP_.-;ݝ*
7X/kwPٽnn7=7X/kޚU$לTAgax
PZ5Ry~뭕wS ^mֵV'׽Ք{/U_VXFx!^7Z EMnJwɕW{alnO䱗3>V ^ⵃSPaerw0dX25B1yehtxhLE"bt[j"Q?j|t#@/q߶vZ]r[޿ǂMx+/V栰"9<G^I7q!^oO=ҫ߼_g]kbC ^֊[+-A<HevѯayBfxa:pl~]J]s7ۇ
t5	v.jd{r6/BxgB/0UF'dG"[K!^rMd!7G'y]gc}̦"!^5ĻM\2ݰO:W88>~x|ҍBoGн9$VoW>wk܇hmtC@/A
d'guXB<j	qR^Y
{+0/ƪZl	bz3g+/λj3MO%ex0SoY3>V! ^rb=xiMHzv!^@/[ȹ]9
NYS*xe\-{	YR/
nxm6RgKDB8I5&ONU+/ċG
zɳG<yT85gW+/ΞcYr琬)^$yZ0]a|/}_8.ޜ
cxOc[^3O&Ǎwk+/ċoNę4DOI9d{Ka
B߬b,qؗs%^%\htIs`J7B\Lull7nb*EIV	*:Ǩ!,9t3@/7x!G9)y|~:{(a`x7&.vL;nGn6
ߊ*:_%~a`x?$`ĕnø_7DyrZ
]6%x!^#Q!;
O~Pxzgr:rzuNo;Fa`x񌗷vC:S.#_>[$I1)KX垷| ^c@/v~e]2w>힁/-?WS~-=d^~[x>XFx!^B{ego RGf粛߿TWa\HXy+/ċ2ev|7=~0dJ2+}P/8t#@/;`⹳DS7\'FK$/GGBE| ^c@/~N6
qȼ7W׺y&L%ϴȔ
Ωcv`5Bp=f1'[QW{Re2t<ΠL *ax
B2qrU(;
M~Cc4vg˨~dz%_[惕nxqlSeM^nl6vww3ٞB_!ׅ2E"1?ZJ7bo_\TQU_:D9=R9bT;uM,?uk5ws`Q82l+=gM
YK+/ċP*Ǧb;CɥyuM~2?u*t,F`x{e2rg<qX~2[ѻztߺ; r惕nx!%?v!іU-dcjV7D|jd/z烕Bx_M}}vn[r/6un/lywI6,V:❹%;KT)~
%锏Pξ`?y;x!^S5]gCsP@ɄQU\*hD<^@/kbt?~gF|Mシ'H
՞GF?Wgo x!^3@
˥jLSgZ/֢;sBդ#G$ށ:o~/?';VÏV2|mdd8l懕Bfxg4W _s>m$WVo$zuݵ#+Vjs%Z@i*08u$mõM_}3L`c3"xޛ7я-+%N'x	^u2̯ï	NʋY%+R) M/Yw:KzUh#`{c	r|/GoVU*8}(܆hN.p	^דxGwdv'䶩x,X]3^(f
1Aq~PKcQ})^>߷BA_oZFyqKJT	.'9XN#ߣ_9C@HdCnI3ǿףq':%SJ^qRUx_~?C#dlԐn׳7}֣q1צ"?UQKگWq?f/Go*~W#~'9[jK\zTmKYbƘkUqڝ S:tFtخ̷F)N2Jvj%L
\:N'x	^/"xqkVHGqN{?ӠXgnTxDW;>t#>\Ia^~(#7~v?,8XmlxXG71
j5~V8-ЫЍяʘϊRՐc<?W?Wq'Z?$t8d
q|:,џ$4rg
ޯc4F	^ןY
}凕$/aCIxγi%!ϤS|)o%:[w:Ke
Q%yzȉNx;~
7E_|[׬G
/I/r9)@P_,'yb&7QMx7b֞fmZ/nTج/KrMV},0~MW!%%o7)y6n>kJcRVS]3ZY/w:KzY 0nkjjt2g+!!1!M
r|/aRzy%x)_U)OJ$T2RBU9|WE8 Z}{OOs
^t#fYU+Q5@|W*+;ߕn-mlVz	^חx7R.n?%jm<g`∸tj2\Q	^t#>\~FRO)y$z]߻u{iiAÞO{͙NoW^t"WQ"Jbw#J`m)Kw|fq~
Ýxm674's̝N3^`]>x]̑N7}Hֆ?Oc)͆b7g/I/؇O`Y 3wG?ᱥ|MBRِTvBXGJ^#x	^׏Ӽ3*C]Cߝ?@"gQ?whɋ-Ӧlonv76}7Hy;%x=	U0
v{i?޻{|bO5~A)d 9Y~2w:Kz3HXeR*5_]W]DI%Ĕ1rº{$Edž6`	^דpM10SLsKg(V;FX)E)7X{Q?9Ckk4#DxI)Irt&~VC^#u
Y˶ƴCF=̚k/trvWRVM;l
CZ	3^$7Lu5>^Ǟ}?5'z_HD?@_/M<j,
}&E
ОSTdEx(Win`aa `'NBWGs;%x=CH_j[khvlJ/C=x=i	:^=Y52s%CNNNtl{no	^׋0B8z!@jv;P͏0BTOXZH~.۝9s1 z@OuK1绥Hp#@m2>s'x	^׫񦉨0\7	tlGKnbˋBOGotDZxi/ke&0{	:Z?QZ?Y__]B+<	^׏^䡋eSU|izJLg
~kѪ!vO/p\:@=èpPZ:r5;%x}gww00Y+,T|wK	^
p1Pm@BR2&n/Io::QU5daAooF\7SR3%d vȅ$FsN$QCRx_aOXYTCPT/K㋻vHq͕{DoYU4^u#LlmAR}3Weif&AFֆ$u}MtMb޿f]u6k(oի(?egK4<Oz(^}+kxS'IϬ3hRᅲZI0OƁx)/')Tra3vݺDžW{}]:<x?p+uOo\17ߣU@P7wIy)^7IݣuJκo&^۶iZQ;d'xcA)NHTk/fYo6λ_'</	ө>HB}"]dd:JL`>[9U-?h'x#Ac.MgLi?l:ͧcnoY/%rXI3y)^7"G	#.=
%$X	h cUJhϳ\InCGx)ޟc(~)l?=mCf(0^e:<x?@{EnϊsgWE~E:%Bѹp'=
/K.$0+n8CIýo(^Nqp⺷+Z5v?0<	卷 [#,l
<]O]<_7xw0vey7/KºQzZo/9wUl@!aO%9<Oz(^⵶$[F;qns…wo%F@fBgu/<Oz$(^5V$kʚ[(4Dvؾ4<Qx)^W<kBjYC'9yң@R5D-F*?{fHt3XX[M
v&@ +tq.}5#fGP
^MEX؏=w˘{q(<o+Jڋ)9w_,BBu+Ao+mC=h|(D%^W⭃m5tS#ւu%^
Ks2uq]h;ekȼn+A/^bkQQL&ݻEXI[SmQuf<synw
7OQzy:Hk-T)RT-C4O.ݳ,32/y+BggP1szmSq_Lϻw%bdʼnz$^WL!@B(p61wjې	M̼[	Wxxt+PYδx%^i$q0D7؛>M+JEٓ:5emeP`f4&)sȼnz$^WM=~SR'+Jg$Ax%^$AZv~_̃y[WxC"ZMx%7EkЏk6,ּ+Jop@v~%wx%^ḥ\jkف%ܼ+Jo?'=+rw)i1yWxwi؋w;U7tϺEB;pX6^	WxXTy>ݢqy*HĻ	n[[
#a 7~]$,y+ҮѪ#s>i-ClX,,3i~ybunmԳ5^[
Wxp6nU΍9VoJFj}$s
gVuӫ JYzq~Rns>۝M+Juw?#X?;Qf~l}۝M+J4WͻDSjns^7]xB/^xQVeɁ(:^+A=773[sz6#mKoe$^\gOǥE?kH+VB
%q~(XGbytW⭄^.׳X7X}ͼ[nygq;+𗸊w5q
wMNtwrQ9v^Mt?f?KkyEs^۟MoKx_aq0+U
$;M4[)	q^?XmD+x#d?';$ߓT޶"ϤzxWXbW7gҁx[xyOZy8/rl?r;gҁxx5-PeYlY~t~yx<iϤ/6	d2}1rt%t֛^tަzm={;0뭗~&x}wovOQ^xhۨ}t޶E;czؖLXZѝt6`zUspvwc3<BrI^m
,yv|}gtRWt)sAkrWP킬|t{߻9bJy;}3
y>JwE~Q꽳~^ZwMHB]~I^V7;{^1nwo&we^AE;C׶@M)Q뫟I^m_yh	i>٪C'TϤ/6	Kݧ߻^'mw;dQuϤ/6
dmn~pNt&_C?ñx{"^+^"^"^WW]xxŋxŋx+^+^"^vWE//xxŋx&^WWWE/xxŋxŋx+^+^"wArE2tvoꀅK`EqOmM@{C/FmWMխOX?׃$F[sI_^ͥ|KO)|^{0OL\OY2v^Fx	/=O{ )$v~"/Dx	#g:lx%GxotTY1Lqu*	/%CK_N|dEx	/V7e(o^;oB&f	%wHޣ0=4==^Kx-LQYuoo/%l8#QS8:țҲP*nR"Kx	/݉Qu7v
Z	^ˆWW&y^2^Kxـ`)2K[wH	/%lXЩ@W]!k{ky0	/%lXB&rG`I%me^2
7t܆Q.E0MJ;F^x+m	ҭ@:5imEBx	/e;Y
oؽ>^~ Dx	/m`JWaJFd}Ax݉^[c_s^/Wy-eם/%ؗf-J5ם/%m=Uxݑ[PS]?N=7ExtD.T^")Q}8D0ש/%{*i}~SDፊk-.V^̱?:oe-o
]c]@x]^+¾_LYtha~Ү
2\^#R@+;i"Fx	/E)VvxW0qw]Ax]^	z6b3d`{&/û,~"Dx	/ᵿ/}1gxOIn^G#JRM];`Ʌ0y^W#pl>^js\/%Fx{xuwqy~^Kx'
qyt%o-k	/%MxM"6b} 2g?bi
LM^6(x^o+mwtrXwӆ^܂wRoJR]*-CzkZ0M	/%)xWwҪwKa-/%%x_sU%Ҷ*!2mp_DZ5ǝͥuք^5+U#R#i]PR&^wI6evNy7?鄗L78_,fiKL@2cﮑ0
_t
sfvzKcC:ofhAR{$h-ϼtk^K'^빮	/99^{S/u\tKxo%Ή;rtKxo%~N>K'^xa鄗^9~DxǎG,+ExEj$# Ej&(7TuuK%k?e=.Yv jY^n'
mt^KxC*:<@]_:%͇7TBYGLAxww䝬KrZhwwjDVⵐi/%{%|z__S DDxG͟X_%1,.\%PHx`(@x	/&"Uτbb_6RŒ5.%r#iOp^sLyEr'<;4n>Ы^‹ػԱ(MУ&Nb2xUP&Ez3n0=h][+}go0ItSEv#IEfn.NMue	#M;p-l._[OC^ޖ*/;w0
 48PEdfg9jaͥ1OA7T'	TǾSWwO6NG@xAxѵ"W3;0e}SE<	AxAxZnE  Av|.kC.lp~78{[9'{#3mBqSYx[/eA*@x	/|/"]Ϻ1KxoW5ƺ"јw  |{_VVB
ӵ_EޑY@x	/vUV-EO4/Q* e5/W(JbI%ۛ	/I7urh^~+<tVQlRKxͷݝh%nE{R/2^-ܓuWͤ/2:G9d"Y(</osF`ǔ{]WQy&.^u}!v/E%p[7Rcbha*{R%[;	!uKxo9m3}Kxxխ+	v_(# {xS1m
Qvr^{=]#% |&k.#i^X8#u@x	/%{n	/BoͶkw]B̷e啧kBͷ˲r?]Sjȸ# :}++S_6^‹֬t/
Gt^4ͷ˲<]プuBoMYYl,y?p@x	/U>nj%'ig# {Q[Qm%Lҳř^Go~w*6[4^([ޛ&Kޖ%mX/E#|ɒw"ɹh m]_5Y%0i̓5Kxќ>ߞ֫S%/x	/E3|ksP
km_p|.~a/r mM56?䤁3DV5oI^{DSiaKx	15m. 9w
_Y^/
;2g1ҏGދ}v/^~sǶ0FĿ"@jnqRE῟μ^7f~vEox+?w^}W/x++{5
ߝx^7~exޢ7Egx^E]W^
oѓW^
oѯ^-:y/x[tw+uo/x[6ޟW/xV]x^lܳy/x[tex^h^-+eOVF^-
xޢ'ˎ^6^y;^V3{?^W/x<^Y6/x[4^Yw~xޢqex^W/xVnFx^}-ہW/xl/x[t5^-gx[#*^6rQ^m6dn^-:rW/xVu/x[˽~wW/x^W/xǼ9WԁW/xVvQ^WvQ^୺n^=3;c_;uTBAŁ׿A6oѯaY8fBx{!>-vx+ު	We;2/xfdv/x?7/xKz#mxBt3{<IENDB`PK
!<1webextension/log.js/* globals buildSettings */
/* eslint-disable no-console */

"use strict";

this.log = (function() {
  let exports = {};

  const levels = ["debug", "info", "warn", "error"];
  if (!levels.includes(buildSettings.logLevel)) {
    console.warn("Invalid buildSettings.logLevel:", buildSettings.logLevel);
  }
  let shouldLog = {};

  {
    let startLogging = false;
    for (let level of levels) {
      if (buildSettings.logLevel === level) {
        startLogging = true;
      }
      if (startLogging) {
        shouldLog[level] = true;
      }
    }
  }

  function stub() {}
  exports.debug = exports.info = exports.warn = exports.error = stub;

  if (shouldLog.debug) {
    exports.debug = console.debug.bind(console);
  }

  if (shouldLog.info) {
    exports.info = console.info.bind(console);
  }

  if (shouldLog.warn) {
    exports.warn = console.warn.bind(console);
  }

  if (shouldLog.error) {
    exports.error = console.error.bind(console);
  }

  return exports;
})();
null;
PK
!<[{HHwebextension/makeUuid.js"use strict";

this.makeUuid = (function() {

  // generates a v4 UUID
  return function makeUuid() { // eslint-disable-line no-unused-vars
    // get sixteen unsigned 8 bit random values
    var randomValues = window
      .crypto
      .getRandomValues(new Uint8Array(36));

    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var i = Array.prototype.slice.call(arguments).slice(-2)[0]; // grab the `offset` parameter
      var r = randomValues[i] % 16|0, v = c === 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  };
})();
null;
PK
!<55webextension/manifest.json{
  "manifest_version": 2,
  "name": "Firefox Screenshots",
  "version": "10.12.0",
  "description": "__MSG_addonDescription__",
  "author": "__MSG_addonAuthorsList__",
  "homepage_url": "https://github.com/mozilla-services/screenshots",
  "applications": {
    "gecko": {
      "id": "screenshots@mozilla.org"
    }
  },
  "default_locale": "en_US",
  "browser_action": {
    "default_icon": {
      "16": "icons/icon-16-v2.svg",
      "32": "icons/icon-32-v2.svg"
    },
    "default_title": "Firefox Screenshots",
    "browser_style": false
  },
  "background": {
    "scripts": [
      "build/buildSettings.js",
      "background/startBackground.js"
    ]
  },
  "content_scripts": [
    {
      "matches": ["https://screenshots.firefox.com/*"],
      "js": [
        "build/buildSettings.js",
        "log.js",
        "catcher.js",
        "selector/callBackground.js",
        "sitehelper.js"
      ]
    }
  ],
  "web_accessible_resources": [
    "blank.html",
    "icons/cancel.svg",
    "icons/download.svg",
    "icons/icon-256.png",
    "icons/back.svg",
    "icons/back-highlight.svg",
    "icons/menu-fullpage.svg",
    "icons/menu-visible.svg",
    "icons/menu-myshot.svg",
    "icons/onboarding-1.png",
    "icons/onboarding-2.png",
    "icons/onboarding-3.png",
    "icons/onboarding-4.png",
    "icons/done.svg",
    "icons/icon-welcome-face-without-eyes.svg"
  ],
  "permissions": [
    "activeTab",
    "downloads",
    "tabs",
    "storage",
    "notifications",
    "clipboardWrite",
    "contextMenus",
    "<all_urls>",
    "https://screenshots.firefox.com/"
  ]
}
PK
!<		#webextension/onboarding/slides.html<!DOCTYPE html>
<html>
  <head>
    <!-- onboarding.scss is automatically inserted here: -->
    <style></style>
    <!-- Here and in onboarding.scss use MOZ_EXTENSION/path to refer to local files -->
  </head>
  <body>
    <div id="slide-overlay">
      <!-- The current slide is set by having .active-slide-1, .active-slide-2, etc on #slide element: -->
      <div id="slide-container" data-number-of-slides="3" class="active-slide-1">
        <div class="slide slide-1">
          <!-- Note: all images must be listed in manifest.json.template under web_accessible_resources -->
          <div class="slide-image" style="background-image: url('MOZ_EXTENSION/icons/onboarding-1.png');"></div>
          <div class="slide-content">
            <div class="slide-content-aligner">
              <h1><span><strong>Firefox</strong> Screenshots</span><sup>Beta</sup></h1>
              <p data-l10n-id="tourBodyOne"></p>
            </div>
            <p class="onboarding-legal-notice"><!-- Substituted with termsAndPrivacyNotice --></p>
          </div>
        </div>
        <div class="slide slide-2">
          <div class="slide-image" style="background-image: url('MOZ_EXTENSION/icons/onboarding-2.png');"></div>
          <div class="slide-content">
            <h1 data-l10n-id="tourHeaderTwo"></h1>
            <p data-l10n-id="tourBodyTwo"></p>
          </div>
        </div>
        <div class="slide slide-3">
          <div class="slide-image" style="background-image: url('MOZ_EXTENSION/icons/onboarding-4.png');"></div>
          <div class="slide-content">
            <h1 data-l10n-id="tourHeaderFour"></h1>
            <p data-l10n-id="tourBodyFour"></p>
          </div>
        </div>

        <!-- Clickable elements should be buttons for accessibility -->
        <button id="skip" data-l10n-id="tourSkip" tabindex=1>Skip</button>
        <button id="prev" tabindex=2 data-l10n-label-id="tourPrevious"></button>
        <button id="next" tabindex=3 data-l10n-label-id="tourNext"></button>
        <button id="done" tabindex=4 data-l10n-label-id="tourDone"></button>
        <div id="slide-status-container">
          <button class="goto-slide goto-slide-1" data-number="1" tabindex=4></button>
          <button class="goto-slide goto-slide-2" data-number="2" tabindex=5></button>
          <button class="goto-slide goto-slide-3" data-number="3" tabindex=6></button>
        </div>
        <!-- FIXME: Need to put in privacy / etc links -->
      </div>
    </div>
  </body>
</html>
PK
!<1++!webextension/onboarding/slides.js/* globals log, catcher, onboardingHtml, onboardingCss, util, shooter, callBackground, assertIsTrusted, assertIsBlankDocument */

"use strict";

this.slides = (function() {
  let exports = {};

  const { watchFunction } = catcher;

  let iframe;
  let doc;
  let currentSlide = 1;
  let numberOfSlides;
  let callbacks;

  exports.display = function(addCallbacks) {
    if (iframe) {
      throw new Error("Attemted to call slides.display() twice");
    }
    return new Promise((resolve, reject) => {
      callbacks = addCallbacks;
      // FIXME: a lot of this iframe logic is in ui.js; maybe move to util.js
      iframe = document.createElement("iframe");
      iframe.src = browser.extension.getURL("blank.html");
      iframe.id = "firefox-screenshots-onboarding-iframe";
      iframe.style.zIndex = "99999999999";
      iframe.style.border = "none";
      iframe.style.position = "fixed";
      iframe.style.top = "0";
      iframe.style.left = "0";
      iframe.style.margin = "0";
      iframe.scrolling = "no";
      updateIframeSize();
      let html = onboardingHtml.replace('<style></style>', `<style>${onboardingCss}</style>`);
      html = html.replace(/MOZ_EXTENSION([^\"]+)/g, (match, filename) => {
        return browser.extension.getURL(filename);
      });
      iframe.addEventListener("load", catcher.watchFunction(() => {
        doc = iframe.contentDocument;
        assertIsBlankDocument(doc);
        let parsedDom = (new DOMParser()).parseFromString(
          html,
          "text/html"
        );
        doc.replaceChild(
          doc.adoptNode(parsedDom.documentElement),
          doc.documentElement
        );
        doc.addEventListener("keyup", onKeyUp);
        doc.documentElement.dir = browser.i18n.getMessage("@@bidi_dir");
        doc.documentElement.lang = browser.i18n.getMessage("@@ui_locale");
        localizeText(doc);
        activateSlide(doc);
        resolve();
      }), {once: true});
      document.body.appendChild(iframe);
      iframe.focus();
      window.addEventListener("resize", onResize);
    });
  };

  exports.remove = exports.unload = function() {
    window.removeEventListener("resize", onResize);
    if (doc) {
      doc.removeEventListener("keyup", onKeyUp);
    }
    util.removeNode(iframe);
    iframe = doc = null;
    currentSlide = 1;
    numberOfSlides = undefined;
    callbacks = undefined;
  };

  function localizeText(doc) {
    let els = doc.querySelectorAll("[data-l10n-id]");
    for (let el of els) {
      let id = el.getAttribute("data-l10n-id");
      let text = browser.i18n.getMessage(id);
      el.textContent = text;
    }
    els = doc.querySelectorAll("[data-l10n-label-id]");
    for (let el of els) {
      let id = el.getAttribute("data-l10n-label-id");
      let text = browser.i18n.getMessage(id);
      el.setAttribute("aria-label", text);
    }
    // termsAndPrivacyNoticeCloudServices is a more complicated substitution:
    let termsContainer = doc.querySelector(".onboarding-legal-notice");
    termsContainer.innerHTML = "";
    let termsSentinel = "__TERMS__";
    let privacySentinel = "__PRIVACY__";
    let sentinelSplitter = "!!!";
    let linkTexts = {
      [termsSentinel]: browser.i18n.getMessage("termsAndPrivacyNoticeTermsLink"),
      [privacySentinel]: browser.i18n.getMessage("termsAndPrivacyNoticyPrivacyLink")
    };
    let linkUrls = {
      [termsSentinel]: "https://www.mozilla.org/about/legal/terms/services/",
      [privacySentinel]: "https://www.mozilla.org/privacy/firefox/"
    };
    let text = browser.i18n.getMessage(
      "termsAndPrivacyNoticeCloudServices",
      [sentinelSplitter + termsSentinel + sentinelSplitter,
       sentinelSplitter + privacySentinel + sentinelSplitter]);
    let parts = text.split(sentinelSplitter);
    for (let part of parts) {
      let el;
      if (part === termsSentinel || part === privacySentinel) {
        el = doc.createElement("a");
        el.href = linkUrls[part];
        el.textContent = linkTexts[part];
        el.target = "_blank";
        el.id = (part === termsSentinel) ? "terms" : "privacy";
      } else {
        el = doc.createTextNode(part);
      }
      termsContainer.appendChild(el);
    }
  }

  function activateSlide(doc) {
    numberOfSlides = parseInt(doc.querySelector("[data-number-of-slides]").getAttribute("data-number-of-slides"), 10);
    doc.querySelector("#next").addEventListener("click", watchFunction(assertIsTrusted(() => {
      shooter.sendEvent("navigate-slide", "next");
      next();
    })));
    doc.querySelector("#prev").addEventListener("click", watchFunction(assertIsTrusted(() => {
      shooter.sendEvent("navigate-slide", "prev");
      prev();
    })));
    for (let el of doc.querySelectorAll(".goto-slide")) {
      el.addEventListener("click", watchFunction(assertIsTrusted((event) => {
        shooter.sendEvent("navigate-slide", "goto");
        let el = event.target;
        let index = parseInt(el.getAttribute("data-number"), 10);
        setSlide(index);
      })));
    }
    doc.querySelector("#skip").addEventListener("click", watchFunction(assertIsTrusted((event) => {
      shooter.sendEvent("cancel-slides", "skip");
      callbacks.onEnd();
    })));
    doc.querySelector("#done").addEventListener("click", watchFunction(assertIsTrusted((event) => {
      shooter.sendEvent("finish-slides", "done");
      callbacks.onEnd();
    })));
    // Note: e10s breaks the terms and privacy anchor tags. Work around this by
    // manually opening the correct URLs on click until bug 1357589 is fixed.
    doc.querySelector("#terms").addEventListener("click", watchFunction(assertIsTrusted((event) => {
      event.preventDefault();
      callBackground("openTermsPage");
    })));
    doc.querySelector("#privacy").addEventListener("click", watchFunction(assertIsTrusted((event) => {
      event.preventDefault();
      callBackground("openPrivacyPage");
    })));
    doc.querySelector("#slide-overlay").addEventListener("click", watchFunction(assertIsTrusted((event) => {
      if (event.target == doc.querySelector("#slide-overlay")) {
        shooter.sendEvent("cancel-slides", "background-click");
        callbacks.onEnd();
      }
    })));
    setSlide(1);
  }

  function next() {
    setSlide(currentSlide + 1);
  }

  function prev() {
    setSlide(currentSlide - 1);
  }

  const onResize = catcher.watchFunction(function() {
    if (!iframe) {
      log.warn("slides onResize called when iframe is not setup");
      return;
    }
    updateIframeSize();
  });

  function updateIframeSize() {
    iframe.style.height = window.innerHeight + "px";
    iframe.style.width = window.innerWidth + "px";
  }

  const onKeyUp = catcher.watchFunction(assertIsTrusted(function(event) {
    if ((event.key || event.code) === "Escape") {
      shooter.sendEvent("cancel-slides", "keyboard-escape");
      callbacks.onEnd();
    }
    if ((event.key || event.code) === "ArrowRight") {
      shooter.sendEvent("navigate-slide", "keyboard-arrowright");
      next();
    }
    if ((event.key || event.code) === "ArrowLeft") {
      shooter.sendEvent("navigate-slide", "keyboard-arrowleft");
      prev();
    }
  }));

  function setSlide(index) {
    if (index < 1) {
      index = 1;
    }
    if (index > numberOfSlides) {
      index = numberOfSlides;
    }
    shooter.sendEvent("visited-slide", `slide-${index}`);
    currentSlide = index;
    let slideEl = doc.querySelector("#slide-container");
    for (let i = 1; i <= numberOfSlides; i++) {
      let className = `active-slide-${i}`;
      if (i == currentSlide) {
        slideEl.classList.add(className);
      } else {
        slideEl.classList.remove(className);
      }
    }
  }

  return exports;
})();
null;
PK
!<iج||webextension/randomString.js/* exported randomString */

"use strict";

this.randomString = function randomString(length, chars) {
  let randomStringChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  chars = chars || randomStringChars;
  let result = "";
  for (let i = 0; i < length; i++) {
    result += chars[Math.floor(Math.random() * chars.length)]
  }
  return result;
}
null;
PK
!<--'webextension/selector/callBackground.js/* globals log */

"use strict";

this.callBackground = function callBackground(funcName, ...args) {
  return browser.runtime.sendMessage({funcName, args}).then((result) => {
    if (result.type === "success") {
      return result.value;
    } else if (result.type === "error") {
      let exc = new Error(result.message);
      exc.name = "BackgroundError";
      if ('errorCode' in result) {
        exc.errorCode = result.errorCode;
      }
      if ('popupMessage' in result) {
        exc.popupMessage = result.popupMessage;
      }
      throw exc;
    } else {
      log.error("Unexpected background result:", result);
      let exc = new Error(`Bad response type from background page: ${result.type || undefined}`);
      exc.resultType = result.type || "undefined";
      throw exc;
    }
  });
}
null;
PK
!<gs*
*
)webextension/selector/documentMetadata.js"use strict";

this.documentMetadata = (function() {

  function findSiteName() {
    let el = document.querySelector("meta[property='og:site_name']");
    if (el) {
      return el.getAttribute("content");
    }
    // nytimes.com uses this property:
    el = document.querySelector("meta[name='cre']");
    if (el) {
      return el.getAttribute("content");
    }
    return null;
  }

  function getOpenGraph() {
    let openGraph = {};
    // If you update this, also update _OPENGRAPH_PROPERTIES in shot.js:
    let forceSingle = `title type url`.split(" ");
    let openGraphProperties = `
    title type url image audio description determiner locale site_name video
    image:secure_url image:type image:width image:height
    video:secure_url video:type video:width image:height
    audio:secure_url audio:type
    article:published_time article:modified_time article:expiration_time article:author article:section article:tag
    book:author book:isbn book:release_date book:tag
    profile:first_name profile:last_name profile:username profile:gender
    `.split(/\s+/g);
    for (let prop of openGraphProperties) {
      let elems = document.querySelectorAll(`meta[property='og:${prop}']`);
      if (forceSingle.includes(prop) && elems.length > 1) {
        elems = [elems[0]];
      }
      let value;
      if (elems.length > 1) {
        value = [];
        for (let elem of elems) {
          let v = elem.getAttribute("content");
          if (v) {
            value.push(v);
          }
        }
        if (!value.length) {
          value = null;
        }
      } else if (elems.length === 1) {
        value = elems[0].getAttribute("content");
      }
      if (value) {
        openGraph[prop] = value;
      }
    }
    return openGraph;
  }

  function getTwitterCard() {
    let twitterCard = {};
    // If you update this, also update _TWITTERCARD_PROPERTIES in shot.js:
    let properties = `
    card site title description image
    player player:width player:height player:stream player:stream:content_type
    `.split(/\s+/g);
    for (let prop of properties) {
      let elem = document.querySelector(`meta[name='twitter:${prop}']`);
      if (elem) {
        let value = elem.getAttribute("content");
        if (value) {
          twitterCard[prop] = value;
        }
      }
    }
    return twitterCard;
  }

  return function documentMetadata() {
    let result = {};
    result.docTitle = document.title;
    result.siteName = findSiteName();
    result.openGraph = getOpenGraph();
    result.twitterCard = getTwitterCard();
    return result;
  };

})();
null;
PK
!<,RR webextension/selector/shooter.js/* globals global, documentMetadata, util, uicontrol, ui, catcher */
/* globals buildSettings, domainFromUrl, randomString, shot */

"use strict";

this.shooter = (function() { // eslint-disable-line no-unused-vars
  let exports = {};
  const { AbstractShot } = shot;

  const RANDOM_STRING_LENGTH = 16;
  let backend;
  let shotObject;
  let supportsDrawWindow;
  const callBackground = global.callBackground;
  const clipboard = global.clipboard;

  function regexpEscape(str) {
    // http://stackoverflow.com/questions/3115150/how-to-escape-regular-expression-special-characters-using-javascript
    return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
  }

  function sanitizeError(data) {
    const href = new RegExp(regexpEscape(window.location.href), 'g');
    const origin = new RegExp(`${regexpEscape(window.location.origin)}[^\s",>]*`, 'g');
    const json = JSON.stringify(data)
      .replace(href, 'REDACTED_HREF')
      .replace(origin, 'REDACTED_URL');
    const result = JSON.parse(json);
    return result;
  }

  catcher.registerHandler((errorObj) => {
    callBackground("reportError", sanitizeError(errorObj));
  });

  catcher.watchFunction(() => {
    let canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
    let ctx = canvas.getContext('2d');
    supportsDrawWindow = !!ctx.drawWindow;
  })();

  function screenshotPage(selectedPos) {
    if (!supportsDrawWindow) {
      return null;
    }
    let height = selectedPos.bottom - selectedPos.top;
    let width = selectedPos.right - selectedPos.left;
    let canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
    canvas.width = width * window.devicePixelRatio;
    canvas.height = height * window.devicePixelRatio;
    let ctx = canvas.getContext('2d');
    if (window.devicePixelRatio !== 1) {
      ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
    }
    ui.iframe.hide();
    try {
      ctx.drawWindow(window, selectedPos.left, selectedPos.top, width, height, "#fff");
    } finally {
      ui.iframe.unhide();
    }
    return canvas.toDataURL();
  }

  let isSaving = null;

  exports.takeShot = function(captureType, selectedPos) {
    // isSaving indicates we're aleady in the middle of saving
    // we use a timeout so in the case of a failure the button will
    // still start working again
    if (Math.floor(selectedPos.left) == Math.floor(selectedPos.right) ||
        Math.floor(selectedPos.top) == Math.floor(selectedPos.bottom)) {
        let exc = new Error("Empty selection");
        exc.popupMessage = "EMPTY_SELECTION";
        exc.noReport = true;
        catcher.unhandled(exc);
        return;
    }
    const uicontrol = global.uicontrol;
    let deactivateAfterFinish = true;
    if (isSaving) {
      return;
    }
    isSaving = setTimeout(() => {
      if (typeof ui !== "undefined") {
        // ui might disappear while the timer is running because the save succeeded
        ui.Box.clearSaveDisabled();
      }
      isSaving = null;
    }, 1000);
    selectedPos = selectedPos.asJson();
    let captureText = "";
    if (buildSettings.captureText) {
      captureText = util.captureEnclosedText(selectedPos);
    }
    let dataUrl = screenshotPage(selectedPos);
    if (dataUrl) {
      shotObject.delAllClips();
      shotObject.addClip({
        createdDate: Date.now(),
        image: {
          url: dataUrl,
          captureType,
          text: captureText,
          location: selectedPos,
          dimensions: {
            x: selectedPos.right - selectedPos.left,
            y: selectedPos.bottom - selectedPos.top
          }
        }
      });
    }
    catcher.watchPromise(callBackground("takeShot", {
      captureType,
      captureText,
      scroll: {
        scrollX: window.scrollX,
        scrollY: window.scrollY,
        innerHeight: window.innerHeight,
        innerWidth: window.innerWidth
      },
      selectedPos,
      shotId: shotObject.id,
      shot: shotObject.asJson()
    }).then((url) => {
      return clipboard.copy(url).then((copied) => {
        return callBackground("openShot", { url, copied });
      });
    }, (error) => {
      if ('popupMessage' in error && (error.popupMessage == "REQUEST_ERROR" || error.popupMessage == 'CONNECTION_ERROR')) {
        // The error has been signaled to the user, but unlike other errors (or
        // success) we should not abort the selection
        deactivateAfterFinish = false;
        return;
      }
      if (error.name != "BackgroundError") {
        // BackgroundError errors are reported in the Background page
        throw error;
      }
    }).then(() => {
      if (deactivateAfterFinish) {
        uicontrol.deactivate();
      }
    }));
  };

  exports.downloadShot = function(selectedPos) {
    let dataUrl = screenshotPage(selectedPos);
    let promise = Promise.resolve(dataUrl);
    if (!dataUrl) {
      promise = callBackground(
        "screenshotPage",
        selectedPos.asJson(),
        {
          scrollX: window.scrollX,
          scrollY: window.scrollY,
          innerHeight: window.innerHeight,
          innerWidth: window.innerWidth
        });
    }
    catcher.watchPromise(promise.then((dataUrl) => {
      ui.triggerDownload(dataUrl, shotObject.filename);
      uicontrol.deactivate();
    }));
  };

  exports.sendEvent = function(...args) {
    callBackground("sendEvent", ...args);
  };

  catcher.watchFunction(() => {
    shotObject = new AbstractShot(
      backend,
      randomString(RANDOM_STRING_LENGTH) + "/" + domainFromUrl(location),
      {
        origin: shot.originFromUrl(location.href)
      }
    );
    shotObject.update(documentMetadata());
  })();

  return exports;
})();
null;
PK
!<N-UUwebextension/selector/ui.js/* globals log, util, catcher, inlineSelectionCss, callBackground, assertIsTrusted, assertIsBlankDocument */

"use strict";

this.ui = (function() { // eslint-disable-line no-unused-vars
  let exports = {};
  const SAVE_BUTTON_HEIGHT = 50;

  const { watchFunction } = catcher;

  // The <body> tag itself can have margins and offsets, which need to be used when
  // setting the position of the boxEl.
  function getBodyRect() {
    if (getBodyRect.cached) {
      return getBodyRect.cached;
    }
    let rect = document.body.getBoundingClientRect();
    let cached = {
      top: rect.top + window.scrollY,
      bottom: rect.bottom + window.scrollY,
      left: rect.left + window.scrollX,
      right: rect.right + window.scrollX
    };
    // FIXME: I can't decide when this is necessary
    // *not* necessary on http://patriciogonzalezvivo.com/2015/thebookofshaders/
    // (actually causes mis-selection there)
    // *is* necessary on http://atirip.com/2015/03/17/sorry-sad-state-of-matrix-transforms-in-browsers/
    cached = {top: 0, bottom: 0, left: 0, right: 0};
    getBodyRect.cached = cached;
    return cached;
  }

  exports.isHeader = function(el) {
    while (el) {
      if (el.classList &&
          (el.classList.contains("myshots-button") ||
           el.classList.contains("visible") ||
           el.classList.contains("full-page"))) {
        return true;
      }
      el = el.parentNode;
    }
    return false;
  }

  let substitutedCss = inlineSelectionCss.replace(/MOZ_EXTENSION([^\"]+)/g, (match, filename) => {
    return browser.extension.getURL(filename);
  });

  function makeEl(tagName, className) {
    if (!iframe.document()) {
      throw new Error("Attempted makeEl before iframe was initialized");
    }
    let el = iframe.document().createElement(tagName);
    if (className) {
      el.className = className;
    }
    return el;
  }

  function onResize() {
    if (this.sizeTracking.windowDelayer) {
      clearTimeout(this.sizeTracking.windowDelayer);
    }
    this.sizeTracking.windowDelayer = setTimeout(watchFunction(() => {
      this.updateElementSize(true);
    }), 50);
  }

  let iframeSelection = exports.iframeSelection = {
    element: null,
    addClassName: "",
    sizeTracking: {
      timer: null,
      windowDelayer: null,
      lastHeight: null,
      lastWidth: null
    },
    document: null,
    display(installHandlerOnDocument) {
      return new Promise((resolve, reject) => {
        if (!this.element) {
          this.element = document.createElement("iframe");
          this.element.src = browser.extension.getURL("blank.html");
          this.element.id = "firefox-screenshots-selection-iframe";
          this.element.style.display = "none";
          this.element.style.zIndex = "99999999999";
          this.element.style.border = "none";
          this.element.style.position = "absolute";
          this.element.style.top = "0";
          this.element.style.left = "0";
          this.element.style.margin = "0";
          this.element.scrolling = "no";
          this.updateElementSize();
          this.element.addEventListener("load", watchFunction(() => {
            this.document = this.element.contentDocument;
            assertIsBlankDocument(this.document);
            this.document.documentElement.innerHTML = `
               <head>
                <style>${substitutedCss}</style>
                <title></title>
               </head>
               <body></body>`;
            installHandlerOnDocument(this.document);
            if (this.addClassName) {
              this.document.body.className = this.addClassName;
            }
            this.document.documentElement.dir = browser.i18n.getMessage("@@bidi_dir");
            this.document.documentElement.lang = browser.i18n.getMessage("@@ui_locale");
            resolve();
          }), {once: true});
          document.body.appendChild(this.element);
        } else {
          resolve();
        }
      });
    },

    hide() {
      this.element.style.display = "none";
      this.stopSizeWatch();
    },

    unhide() {
      this.updateElementSize();
      this.element.style.display = "";
      this.initSizeWatch();
      this.element.focus();
    },

    updateElementSize(force) {
      // Note: if someone sizes down the page, then the iframe will keep the
      // document from naturally shrinking.  We use force to temporarily hide
      // the element so that we can tell if the document shrinks
      const visible = this.element.style.display !== "none";
      if (force && visible) {
        this.element.style.display = "none";
      }
      let height = Math.max(
        document.documentElement.clientHeight,
        document.body.clientHeight,
        document.documentElement.scrollHeight,
        document.body.scrollHeight,
        window.innerHeight);
      if (height !== this.sizeTracking.lastHeight) {
        this.sizeTracking.lastHeight = height;
        this.element.style.height = height + "px";
      }
      let width = Math.max(
        document.documentElement.clientWidth,
        document.body.clientWidth,
        document.documentElement.scrollWidth,
        document.body.scrollWidth,
        window.innerWidth);
      if (width !== this.sizeTracking.lastWidth) {
        this.sizeTracking.lastWidth = width;
        this.element.style.width = width + "px";
      }
      if (force && visible) {
        this.element.style.display = "";
      }
    },

    initSizeWatch() {
      this.stopSizeWatch();
      this.sizeTracking.timer = setInterval(watchFunction(this.updateElementSize.bind(this)), 2000);
      window.addEventListener("resize", this.onResize, true);
    },

    stopSizeWatch() {
      if (this.sizeTracking.timer) {
        clearTimeout(this.sizeTracking.timer);
        this.sizeTracking.timer = null;
      }
      if (this.sizeTracking.windowDelayer) {
        clearTimeout(this.sizeTracking.windowDelayer);
        this.sizeTracking.windowDelayer = null;
      }
      this.sizeTracking.lastHeight = this.sizeTracking.lastWidth = null;
      window.removeEventListener("resize", this.onResize, true);
    },

    getElementFromPoint(x, y) {
      this.element.style.pointerEvents = "none";
      let el;
      try {
        el = document.elementFromPoint(x, y);
      } finally {
        this.element.style.pointerEvents = "";
      }
      return el;
    },

    remove() {
      this.stopSizeWatch();
      util.removeNode(this.element);
      this.element = this.document = null;
    }
  };

  iframeSelection.onResize = watchFunction(assertIsTrusted(onResize.bind(iframeSelection)), true);

  let iframePreSelection = exports.iframePreSelection = {
    element: null,
    document: null,
    sizeTracking: {
      windowDelayer: null
    },
    display(installHandlerOnDocument, standardOverlayCallbacks) {
      return new Promise((resolve, reject) => {
        if (!this.element) {
          this.element = document.createElement("iframe");
          this.element.src = browser.extension.getURL("blank.html");
          this.element.id = "firefox-screenshots-preselection-iframe";
          this.element.style.zIndex = "99999999999";
          this.element.style.border = "none";
          this.element.style.position = "fixed";
          this.element.style.top = "0";
          this.element.style.left = "0";
          this.element.style.margin = "0";
          this.element.scrolling = "no";
          this.updateElementSize();
          this.element.addEventListener("load", watchFunction(() => {
            this.document = this.element.contentDocument;
            assertIsBlankDocument(this.document)
            this.document.documentElement.innerHTML = `
               <head>
                <style>${substitutedCss}</style>
                <title></title>
               </head>
               <body>
                 <div class="preview-overlay">
                   <div class="fixed-container">
                     <div class="face-container">
                       <div class="eye left"><div class="eyeball"></div></div>
                       <div class="eye right"><div class="eyeball"></div></div>
                       <div class="face"></div>
                     </div>
                     <div class="preview-instructions"></div>
                     <div class="myshots-all-buttons-container">
                       <button class="myshots-button myshots-link" tabindex="1"></button>
                     </div>
                   </div>
                 </div>
               </body>`;
            installHandlerOnDocument(this.document);
            if (this.addClassName) {
              this.document.body.className = this.addClassName;
            }
            this.document.documentElement.dir = browser.i18n.getMessage("@@bidi_dir");
            this.document.documentElement.lang = browser.i18n.getMessage("@@ui_locale");
            const overlay = this.document.querySelector(".preview-overlay");
            overlay.querySelector(".preview-instructions").textContent = browser.i18n.getMessage("screenshotInstructions");
            overlay.querySelector(".myshots-link").textContent = browser.i18n.getMessage("myShotsLink");
            overlay.querySelector(".myshots-button").addEventListener(
              "click", watchFunction(assertIsTrusted(standardOverlayCallbacks.onOpenMyShots)));
            resolve();
          }), {once: true});
          document.body.appendChild(this.element);
          this.unhide();
        } else {
          resolve();
        }
      });
    },

    updateElementSize() {
      if (!this.element) {
        // This can happen if the selector is unloaded during the resize adjustment
        // time-delay
        return;
      }
      this.element.style.height = window.innerHeight + "px";
      this.element.style.width = window.innerWidth + "px";
    },

    hide() {
      window.removeEventListener("scroll", watchFunction(assertIsTrusted(this.onScroll)));
      window.removeEventListener("resize", this.onResize, true);
      if (this.element) {
        this.element.style.display = "none";
      }
    },

    unhide() {
      this.updateElementSize();
      window.addEventListener("scroll", watchFunction(assertIsTrusted(this.onScroll)));
      window.addEventListener("resize", this.onResize, true);
      this.element.style.display = "";
      this.element.focus();
    },

    onScroll() {
      exports.HoverBox.hide();
    },

    getElementFromPoint(x, y) {
      this.element.style.pointerEvents = "none";
      let el;
      try {
        el = document.elementFromPoint(x, y);
      } finally {
        this.element.style.pointerEvents = "";
      }
      return el;
    },

    remove() {
      this.hide();
      util.removeNode(this.element);
      this.element = null;
      this.document = null;
    }
  };

  iframePreSelection.onResize = watchFunction(onResize.bind(iframePreSelection), true);

  let iframe = exports.iframe = {
    currentIframe: iframePreSelection,
    display(installHandlerOnDocument, standardOverlayCallbacks) {
      return iframeSelection.display(installHandlerOnDocument)
        .then(() => iframePreSelection.display(installHandlerOnDocument, standardOverlayCallbacks));
    },

    hide() {
      this.currentIframe.hide();
    },

    unhide() {
      this.currentIframe.unhide();
    },

    getElementFromPoint(x, y) {
      return this.currentIframe.getElementFromPoint(x, y);
    },

    remove() {
      iframeSelection.remove();
      iframePreSelection.remove();
    },

    document() {
      return this.currentIframe.document;
    },

    useSelection() {
      if (this.currentIframe === iframePreSelection) {
        this.hide();
      }
      this.currentIframe = iframeSelection;
      this.unhide();
    },

    usePreSelection() {
      if (this.currentIframe === iframeSelection) {
        this.hide();
      }
      this.currentIframe = iframePreSelection;
      this.unhide();
    }
  };

  let movements = ["topLeft", "top", "topRight", "left", "right", "bottomLeft", "bottom", "bottomRight"];

  /** Creates the selection box */
  exports.Box = {

    display(pos, callbacks) {
      this._createEl();
      if (callbacks !== undefined && callbacks.cancel) {
        // We use onclick here because we don't want addEventListener
        // to add multiple event handlers to the same button
        this.cancel.onclick = watchFunction(assertIsTrusted(callbacks.cancel));
        this.cancel.style.display = "";
      } else {
        this.cancel.style.display = "none";
      }
      if (callbacks !== undefined && callbacks.save) {
        // We use onclick here because we don't want addEventListener
        // to add multiple event handlers to the same button
        this.save.removeAttribute("disabled");
        this.save.onclick = watchFunction(assertIsTrusted((e) => {
          this.save.setAttribute("disabled", "true");
          callbacks.save(e);
        }));
        this.save.style.display = "";
      } else {
        this.save.style.display = "none";
      }
      if (callbacks !== undefined && callbacks.download) {
        this.download.removeAttribute("disabled");
        this.download.onclick = watchFunction(assertIsTrusted((e) => {
          this.download.setAttribute("disabled", true);
          callbacks.download(e);
          e.preventDefault();
          e.stopPropagation();
          return false;
        }));
        this.download.style.display = "";
      } else {
        this.download.style.display = "none";
      }
      let bodyRect = getBodyRect();
      // Note, document.documentElement.scrollHeight is zero on some strange pages (such as the page created when you load an image):
      let docHeight = Math.max(document.documentElement.scrollHeight || 0, document.body.scrollHeight);
      let docWidth = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth);

      let winBottom = window.innerHeight;
      let pageYOffset = window.pageYOffset;

      if ((pos.right - pos.left) < 78 || (pos.bottom - pos.top) < 78) {
        this.el.classList.add("small-selection");
      } else {
        this.el.classList.remove("small-selection");
      }

      // if the selection bounding box is w/in SAVE_BUTTON_HEIGHT px of the bottom of
      // the window, flip controls into the box
      if (pos.bottom > ((winBottom + pageYOffset) - SAVE_BUTTON_HEIGHT)) {
        this.el.classList.add("bottom-selection");
      } else {
        this.el.classList.remove("bottom-selection");
      }

      if (pos.right < 200) {
        this.el.classList.add("left-selection");
      } else {
        this.el.classList.remove("left-selection");
      }
      this.el.style.top = (pos.top - bodyRect.top) + "px";
      this.el.style.left = (pos.left - bodyRect.left) + "px";
      this.el.style.height = (pos.bottom - pos.top - bodyRect.top) + "px";
      this.el.style.width = (pos.right - pos.left - bodyRect.left) + "px";
      this.bgTop.style.top = "0px";
      this.bgTop.style.height = (pos.top - bodyRect.top) + "px";
      this.bgTop.style.left = "0px";
      this.bgTop.style.width = docWidth + "px";
      this.bgBottom.style.top = (pos.bottom - bodyRect.top) + "px";
      this.bgBottom.style.height = docHeight - (pos.bottom - bodyRect.top) + "px";
      this.bgBottom.style.left = "0px";
      this.bgBottom.style.width = docWidth + "px";
      this.bgLeft.style.top = (pos.top - bodyRect.top) + "px";
      this.bgLeft.style.height = pos.bottom - pos.top + "px";
      this.bgLeft.style.left = "0px";
      this.bgLeft.style.width = (pos.left - bodyRect.left) + "px";
      this.bgRight.style.top = (pos.top - bodyRect.top) + "px";
      this.bgRight.style.height = pos.bottom - pos.top + "px";
      this.bgRight.style.left = (pos.right - bodyRect.left) + "px";
      this.bgRight.style.width = docWidth - (pos.right - bodyRect.left) + "px";

      if (!(this.isElementInViewport(this.buttons))) {
        this.cancel.style.position = this.download.style.position = this.save.style.position = "fixed";
        this.cancel.style.left = (pos.left - bodyRect.left - 50) + "px";
        this.download.style.left = ((pos.left - bodyRect.left - 100)) + "px";
        this.save.style.left = ((pos.left - bodyRect.left) - 190) + "px";
        this.cancel.style.top = this.download.style.top = this.save.style.top = (pos.top - bodyRect.top) + "px";
      } else {
        this.cancel.style.position = this.download.style.position = this.save.style.position = "initial";
        this.cancel.style.top = this.download.style.top = this.save.style.top = 0;
        this.cancel.style.left = this.download.style.left = this.save.style.left = 0;
      }
    },

    remove() {
      for (let name of ["el", "bgTop", "bgLeft", "bgRight", "bgBottom"]) {
        if (name in this) {
          util.removeNode(this[name]);
          this[name] = null;
        }
      }
    },

    _createEl() {
      let boxEl = this.el;
      if (boxEl) {
        return;
      }
      boxEl = makeEl("div", "highlight");
      let buttons = makeEl("div", "highlight-buttons");
      let cancel = makeEl("button", "highlight-button-cancel");
      cancel.title = browser.i18n.getMessage("cancelScreenshot");
      buttons.appendChild(cancel);
      let download = makeEl("button", "highlight-button-download");
      download.title = browser.i18n.getMessage("downloadScreenshot");
      buttons.appendChild(download);
      let save = makeEl("button", "highlight-button-save");
      save.textContent = browser.i18n.getMessage("saveScreenshotSelectedArea");
      save.title = browser.i18n.getMessage("saveScreenshotSelectedArea");
      buttons.appendChild(save);
      this.buttons = buttons;
      this.cancel = cancel;
      this.download = download;
      this.save = save;
      boxEl.appendChild(buttons);
      for (let name of movements) {
        let elTarget = makeEl("div", "mover-target direction-" + name);
        let elMover = makeEl("div", "mover");
        elTarget.appendChild(elMover);
        boxEl.appendChild(elTarget);
      }
      this.bgTop = makeEl("div", "bghighlight");
      iframe.document().body.appendChild(this.bgTop);
      this.bgLeft = makeEl("div", "bghighlight");
      iframe.document().body.appendChild(this.bgLeft);
      this.bgRight = makeEl("div", "bghighlight");
      iframe.document().body.appendChild(this.bgRight);
      this.bgBottom = makeEl("div", "bghighlight");
      iframe.document().body.appendChild(this.bgBottom);
      iframe.document().body.appendChild(boxEl);
      this.el = boxEl;
    },

    draggerDirection(target) {
      while (target) {
        if (target.nodeType == document.ELEMENT_NODE) {
          if (target.classList.contains("mover-target")) {
            for (let name of movements) {
              if (target.classList.contains("direction-" + name)) {
                return name;
              }
            }
            catcher.unhandled(new Error("Surprising mover element"), {element: target.outerHTML});
            log.warn("Got mover-target that wasn't a specific direction");
          }
        }
        target = target.parentNode;
      }
      return null;
    },

    isSelection(target) {
      while (target) {
        if (target.tagName === "BUTTON") {
          return false;
        }
        if (target.nodeType == document.ELEMENT_NODE && target.classList.contains("highlight")) {
          return true;
        }
        target = target.parentNode;
      }
      return false;
    },

    isControl(target) {
      while (target) {
        if (target.nodeType === document.ELEMENT_NODE && target.classList.contains("highlight-buttons")) {
          return true;
        }
        target = target.parentNode;
      }
      return false;
    },

    isElementInViewport(el) {
      let rect = el.getBoundingClientRect();
      return (rect.right <= window.innerWidth);
    },

    clearSaveDisabled() {
      this.save.removeAttribute("disabled");
    },

    el: null,
    boxTopEl: null,
    boxLeftEl: null,
    boxRightEl: null,
    boxBottomEl: null
  };

  exports.HoverBox = {

    el: null,

    display(rect) {
      if (!this.el) {
        this.el = makeEl("div", "hover-highlight");
        iframe.document().body.appendChild(this.el);
      }
      this.el.style.display = "";
      this.el.style.top = (rect.top - 1) + "px";
      this.el.style.left = (rect.left - 1) + "px";
      this.el.style.width = (rect.right - rect.left + 2) + "px";
      this.el.style.height = (rect.bottom - rect.top + 2) + "px";
    },

    hide() {
      if (this.el) {
        this.el.style.display = "none";
      }
    },

    remove() {
      util.removeNode(this.el);
      this.el = null;
    }
  };

  exports.PixelDimensions = {
    el: null,
    xEl: null,
    yEl: null,
    display(xPos, yPos, x, y) {
      if (!this.el) {
        this.el = makeEl("div", "pixel-dimensions");
        this.xEl = makeEl("div");
        this.el.appendChild(this.xEl);
        this.yEl = makeEl("div");
        this.el.appendChild(this.yEl);
        iframe.document().body.appendChild(this.el);
      }
      this.xEl.textContent = x;
      this.yEl.textContent = y;
      this.el.style.top = (yPos + 12) + "px";
      this.el.style.left = (xPos + 12) + "px";
    },
    remove() {
      util.removeNode(this.el);
      this.el = this.xEl = this.yEl = null;
    }
  };

  /** Removes every UI this module creates */
  exports.remove = function() {
    for (let name in exports) {
      if (name.startsWith("iframe")) {
        continue;
      }
      if (typeof exports[name] == "object" && exports[name].remove) {
        exports[name].remove();
      }
    }
    exports.iframe.remove();
  };

  exports.triggerDownload = function(url, filename) {
    return catcher.watchPromise(callBackground("downloadShot", {url, filename}));
  };

  exports.unload = exports.remove;

  return exports;
})();
null;
PK
!<ۯejj"webextension/selector/uicontrol.js/* globals log, catcher, util, ui, slides */
/* globals shooter, callBackground, selectorLoader, assertIsTrusted */

"use strict";

this.uicontrol = (function() {
  let exports = {};

  /** ********************************************************
   * selection
   */

  /* States:

  "crosshairs":
    Nothing has happened, and the crosshairs will follow the movement of the mouse
  "draggingReady":
    The user has pressed the mouse button, but hasn't moved enough to create a selection
  "dragging":
    The user has pressed down a mouse button, and is dragging out an area far enough to show a selection
  "selected":
    The user has selected an area
  "resizing":
    The user is resizing the selection
  "cancelled":
    Everything has been cancelled

  A mousedown goes from crosshairs to dragging.
  A mouseup goes from dragging to selected
  A click outside of the selection goes from selected to crosshairs
  A click on one of the draggers goes from selected to resizing

  State variables:

  state (string, one of the above)
  mousedownPos (object with x/y during draggingReady, shows where the selection started)
  selectedPos (object with x/y/h/w during selected or dragging, gives the entire selection)
  resizeDirection (string: top, topLeft, etc, during resizing)
  resizeStartPos (x/y position where resizing started)
  mouseupNoAutoselect (true if a mouseup in draggingReady should not trigger autoselect)

  */

  const { watchFunction, watchPromise } = catcher;

  const MAX_PAGE_HEIGHT = 5000;
  const MAX_PAGE_WIDTH = 5000;
  // An autoselection smaller than these will be ignored entirely:
  const MIN_DETECT_ABSOLUTE_HEIGHT = 10;
  const MIN_DETECT_ABSOLUTE_WIDTH = 30;
  // An autoselection smaller than these will not be preferred:
  const MIN_DETECT_HEIGHT = 30;
  const MIN_DETECT_WIDTH = 100;
  // An autoselection bigger than either of these will be ignored:
  const MAX_DETECT_HEIGHT = Math.max(window.innerHeight + 100, 700);
  const MAX_DETECT_WIDTH = Math.max(window.innerWidth + 100, 1000);
  // This is how close (in pixels) you can get to the edge of the window and then
  // it will scroll:
  const SCROLL_BY_EDGE = 20;
  // This is how wide the inboard scrollbars are, generally 0 except on Mac
  const SCROLLBAR_WIDTH = (window.navigator.platform.match(/Mac/i)) ? 17 : 0;


  const { sendEvent } = shooter;
  const log = global.log;

  function round10(n) {
    return Math.floor(n / 10) * 10;
  }

  function eventOptionsForBox(box) {
    return {
      cd1: round10(Math.abs(box.bottom - box.top)),
      cd2: round10(Math.abs(box.right - box.left))
    };
  }

  function eventOptionsForResize(boxStart, boxEnd) {
    return {
      cd1: round10(
        (boxEnd.bottom - boxEnd.top)
        - (boxStart.bottom - boxStart.top)),
      cd2: round10(
        (boxEnd.right - boxEnd.left)
        - (boxStart.right - boxStart.left))
    };
  }

  function eventOptionsForMove(posStart, posEnd) {
    return {
      cd1: round10(posEnd.y - posStart.y),
      cd2: round10(posEnd.x - posStart.x)
    };
  }

  /** *********************************************
   * State and stateHandlers infrastructure
   */

  // This enumerates all the anchors on the selection, and what part of the
  // selection they move:
  const movements = {
    topLeft: ["x1", "y1"],
    top: [null, "y1"],
    topRight: ["x2", "y1"],
    left: ["x1", null],
    right: ["x2", null],
    bottomLeft: ["x1", "y2"],
    bottom: [null, "y2"],
    bottomRight: ["x2", "y2"],
    move: ["*", "*"]
  };

  const doNotAutoselectTags = {
    H1: true,
    H2: true,
    H3: true,
    H4: true,
    H5: true,
    H6: true
  };

  let standardDisplayCallbacks = {
    cancel: () => {
      sendEvent("cancel-shot", "overlay-cancel-button");
      exports.deactivate();
    }, save: () => {
      sendEvent("save-shot", "overlay-save-button");
      shooter.takeShot("selection", selectedPos);
    }, download: () => {
      sendEvent("download-shot", "overlay-download-button");
      shooter.downloadShot(selectedPos);
    }
  };

  let standardOverlayCallbacks = {
    onOpenMyShots: () => {
      sendEvent("goto-myshots", "selection-button");
      callBackground("openMyShots")
        .then(() => exports.deactivate())
        .catch(() => {
          // Handled in communication.js
        });
    },
    onClickVisible: () => {
      sendEvent("capture-visible", "selection-button");
      selectedPos = new Selection(
        window.scrollX, window.scrollY,
        window.scrollX + window.innerWidth, window.scrollY + window.innerHeight);
      shooter.takeShot("visible", selectedPos);
    },
    onClickFullPage: () => {
      sendEvent("capture-full-page", "selection-button");
      let width = Math.max(
        document.body.clientWidth,
        document.documentElement.clientWidth,
        document.body.scrollWidth,
        document.documentElement.scrollWidth);
      width = Math.min(width, MAX_PAGE_WIDTH);
      let height = Math.max(
        document.body.clientHeight,
        document.documentElement.clientHeight,
        document.body.scrollHeight,
        document.documentElement.scrollHeight);
      height = Math.min(height, MAX_PAGE_HEIGHT);
      selectedPos = new Selection(
        0, 0,
        width, height);
      shooter.takeShot("fullPage", selectedPos);
    }
  }

  /** Holds all the objects that handle events for each state: */
  let stateHandlers = {};

  function getState() {
    return getState.state;
  }
  getState.state = "cancel";

  function setState(s) {
    if (!stateHandlers[s]) {
      throw new Error("Unknown state: " + s);
    }
    let cur = getState.state;
    let handler = stateHandlers[cur];
    if (handler.end) {
      handler.end();
    }
    getState.state = s;
    if (stateHandlers[s].start) {
      stateHandlers[s].start();
    }
  }

  /** Various values that the states use: */
  let mousedownPos;
  let selectedPos;
  let resizeDirection;
  let resizeStartPos;
  let resizeStartSelected;
  let resizeHasMoved;
  let mouseupNoAutoselect = false;
  let autoDetectRect;

  /** Represents a selection box: */
  class Selection {
    constructor(x1, y1, x2, y2) {
      this.x1 = x1;
      this.y1 = y1;
      this.x2 = x2;
      this.y2 = y2;
    }

    rect() {
      return {
        top: Math.floor(this.top),
        left: Math.floor(this.left),
        bottom: Math.floor(this.bottom),
        right: Math.floor(this.right)
      };
    }

    get top() {
      return Math.min(this.y1, this.y2);
    }
    set top(val) {
      if (this.y1 < this.y2) {
        this.y1 = val;
      } else {
        this.y2 = val;
      }
    }

    get bottom() {
      return Math.max(this.y1, this.y2);
    }
    set bottom(val) {
      if (this.y1 > this.y2) {
        this.y1 = val;
      } else {
        this.y2 = val;
      }
    }

    get left() {
      return Math.min(this.x1, this.x2);
    }
    set left(val) {
      if (this.x1 < this.x2) {
        this.x1 = val;
      } else {
        this.x2 = val;
      }
    }

    get right() {
      return Math.max(this.x1, this.x2);
    }
    set right(val) {
      if (this.x1 > this.x2) {
        this.x1 = val;
      } else {
        this.x2 = val;
      }
    }

    get width() {
      return Math.abs(this.x1 - this.x2);
    }
    get height() {
      return Math.abs(this.y1 - this.y2);
    }

    /** Sort x1/x2 and y1/y2 so x1<x2, y1<y2 */
    sortCoords() {
      if (this.x1 > this.x2) {
        let tmp = this.x2;
        this.x2 = this.x1;
        this.x1 = tmp;
      }
      if (this.y1 > this.y2) {
        let tmp = this.y2;
        this.y2 = this.y1;
        this.y1 = tmp;
      }
    }

    union(other) {
      return new Selection(
        Math.min(this.left, other.left),
        Math.min(this.top, other.top),
        Math.max(this.right, other.right),
        Math.max(this.bottom, other.bottom)
      );
    }

    clone() {
      return new Selection(this.x1, this.y1, this.x2, this.y2);
    }

    asJson() {
      return {
        left: this.left,
        right: this.right,
        top: this.top,
        bottom: this.bottom
      };
    }
  }

  Selection.getBoundingClientRect = function(el) {
    if (!el.getBoundingClientRect) {
      // Typically the <html> element or somesuch
      return null;
    }
    let rect = el.getBoundingClientRect();
    if (!rect) {
      return null;
    }
    return new Selection(rect.left, rect.top, rect.right, rect.bottom);
  };

  /** Represents a single x/y point, typically for a mouse click that doesn't have a drag: */
  class Pos {
    constructor(x, y) {
      this.x = x;
      this.y = y;
    }

    elementFromPoint() {
      return ui.iframe.getElementFromPoint(
        this.x - window.pageXOffset,
        this.y - window.pageYOffset
      );
    }

    distanceTo(x, y) {
      return Math.sqrt(Math.pow(this.x - x, 2), Math.pow(this.y - y));
    }
  }

  /** *********************************************
   * all stateHandlers
   */

  stateHandlers.onboarding = {
    start() {
      if (typeof slides == "undefined") {
        throw new Error("Attempted to set state to onboarding without loading slides");
      }
      catcher.watchPromise(slides.display({
        onEnd: this.slidesOnEnd.bind(this)
      }));
    },

    slidesOnEnd() {
      callBackground("hasSeenOnboarding");
      setState("crosshairs");
    },

    end() {
      slides.remove();
    }
  };

  stateHandlers.crosshairs = {

    cachedEl: null,

    start() {
      selectedPos = mousedownPos = null;
      this.cachedEl = null;
      watchPromise(ui.iframe.display(installHandlersOnDocument, standardOverlayCallbacks).then(() => {
        ui.iframe.usePreSelection();
        ui.Box.remove();
        const handler = watchFunction(assertIsTrusted(keyupHandler));
        document.addEventListener("keyup", handler);
        registeredDocumentHandlers.push({name: "keyup", doc: document, handler, useCapture: false});
      }));
    },

    mousemove(event) {
      ui.PixelDimensions.display(event.pageX, event.pageY, event.pageX, event.pageY);
      if (event.target.classList &&
          (!event.target.classList.contains("preview-overlay"))) {
        // User is hovering over a toolbar button or control
        autoDetectRect = null;
        ui.HoverBox.hide();
        return;
      }
      let el;
      if (event.target.classList && event.target.classList.contains("preview-overlay")) {
        // The hover is on the overlay, so we need to figure out the real element
        el = ui.iframe.getElementFromPoint(
          event.pageX + window.scrollX - window.pageXOffset,
          event.pageY + window.scrollY - window.pageYOffset
        );
        let xpos = Math.floor(10 * (event.pageX - window.innerWidth / 2) / window.innerWidth);
        let ypos = Math.floor(10 * (event.pageY - window.innerHeight / 2) / window.innerHeight)

        for (var i = 0; i < 2; i++) {
          let move = `translate(${xpos}px, ${ypos}px)`;
          event.target.getElementsByClassName('eyeball')[i].style.transform = move;
        }
      } else {
        // The hover is on the element we care about, so we use that
        el = event.target;
      }
      if (this.cachedEl && this.cachedEl === el) {
        // Still hovering over the same element
        return;
      }
      this.cachedEl = el;
      this.setAutodetectBasedOnElement(el);
    },

    setAutodetectBasedOnElement(el) {
      let lastRect;
      let lastNode;
      let rect;
      let attemptExtend = false;
      let node = el;
      while (node) {
        rect = Selection.getBoundingClientRect(node);
        if (!rect) {
          rect = lastRect;
          break;
        }
        if (rect.width > MAX_DETECT_WIDTH || rect.height > MAX_DETECT_HEIGHT) {
          // Then the last rectangle is better
          rect = lastRect;
          attemptExtend = true;
          break;
        }
        if (rect.width >= MIN_DETECT_WIDTH && rect.height >= MIN_DETECT_HEIGHT) {
          if (!doNotAutoselectTags[node.tagName]) {
            break;
          }
        }
        lastRect = rect;
        lastNode = node;
        node = node.parentNode;
      }
      if (rect && node) {
        let evenBetter = this.evenBetterElement(node, rect);
        if (evenBetter) {
          node = lastNode = evenBetter;
          rect = Selection.getBoundingClientRect(evenBetter);
          attemptExtend = false;
        }
      }
      if (rect && attemptExtend) {
        let extendNode = lastNode.nextSibling;
        while (extendNode) {
          if (extendNode.nodeType === document.ELEMENT_NODE) {
            break;
          }
          extendNode = extendNode.nextSibling;
          if (!extendNode) {
            let parent = lastNode.parentNode;
            for (let i = 0; i < parent.childNodes.length; i++) {
              if (parent.childNodes[i] === lastNode) {
                extendNode = parent.childNodes[i + 1];
              }
            }
          }
        }
        if (extendNode) {
          let extendSelection = Selection.getBoundingClientRect(extendNode);
          let extendRect = rect.union(extendSelection);
          if (extendRect.width <= MAX_DETECT_WIDTH && extendRect.height <= MAX_DETECT_HEIGHT) {
            rect = extendRect;
          }
        }
      }

      if (rect && (rect.width < MIN_DETECT_ABSOLUTE_WIDTH || rect.height < MIN_DETECT_ABSOLUTE_HEIGHT)) {
        rect = null;
      }
      if (!rect) {
        ui.HoverBox.hide();
      } else {
        ui.HoverBox.display(rect);
      }
      autoDetectRect = rect;
    },

    /** When we find an element, maybe there's one that's just a little bit better... */
    evenBetterElement(node, origRect) {
      let el = node.parentNode;
      let ELEMENT_NODE = document.ELEMENT_NODE;
      while (el && el.nodeType == ELEMENT_NODE) {
        if (!el.getAttribute) {
          return null;
        }
        let role = el.getAttribute("role");
        if (role === "article" || (el.className && typeof el.className == "string" && el.className.search("tweet ") !== -1)) {
          let rect = Selection.getBoundingClientRect(el);
          if (!rect) {
            return null;
          }
          if (rect.width <= MAX_DETECT_WIDTH && rect.height <= MAX_DETECT_HEIGHT) {
            return el;
          }
          return null;
        }
        el = el.parentNode;
      }
      return null;
    },

    mousedown(event) {
      // FIXME: this is happening but we don't know why, we'll track it now
      // but avoid popping up messages:
      if (typeof ui === "undefined") {
        let exc = new Error("Undefined ui in mousedown");
        exc.unloadTime = unloadTime;
        exc.nowTime = Date.now();
        exc.noPopup = true;
        throw exc;
      }
      if (ui.isHeader(event.target)) {
        return undefined;
      }
      // If the pageX is greater than this, then probably it's an attempt to get
      // to the scrollbar, or an actual scroll, and not an attempt to start the
      // selection:
      let maxX = window.innerWidth - SCROLLBAR_WIDTH;
      if (event.pageX >= maxX) {
        event.stopPropagation();
        event.preventDefault();
        return false;
      }

      mousedownPos = new Pos(event.pageX + window.scrollX, event.pageY + window.scrollY);
      setState("draggingReady");
      event.stopPropagation();
      event.preventDefault();
      return false;
    },

    end() {
      ui.HoverBox.remove();
      ui.PixelDimensions.remove();
    }
  };

  stateHandlers.draggingReady = {
    minMove: 40, // px
    minAutoImageWidth: 40,
    minAutoImageHeight: 40,
    maxAutoElementWidth: 800,
    maxAutoElementHeight: 600,

    start() {
      ui.iframe.usePreSelection();
      ui.Box.remove();
    },

    mousemove(event) {
      if (mousedownPos.distanceTo(event.pageX, event.pageY) > this.minMove) {
        selectedPos = new Selection(
          mousedownPos.x,
          mousedownPos.y,
          event.pageX + window.scrollX,
          event.pageY + window.scrollY);
        mousedownPos = null;
        setState("dragging");
      }
    },

    mouseup(event) {
      // If we don't get into "dragging" then we attempt an autoselect
      if (mouseupNoAutoselect) {
        sendEvent("cancel-selection", "selection-background-mousedown");
        setState("crosshairs");
        return false;
      }
      if (autoDetectRect) {
        selectedPos = autoDetectRect;
        selectedPos.x1 += window.scrollX;
        selectedPos.y1 += window.scrollY;
        selectedPos.x2 += window.scrollX;
        selectedPos.y2 += window.scrollY;
        autoDetectRect = null;
        mousedownPos = null;
        ui.iframe.useSelection();
        ui.Box.display(selectedPos, standardDisplayCallbacks);
        sendEvent("make-selection", "selection-click", eventOptionsForBox(selectedPos));
        setState("selected");
        sendEvent("autoselect");
      } else {
        sendEvent("no-selection", "no-element-found");
        setState("crosshairs");
      }
      return undefined;
    },

    click(event) {
      this.mouseup(event);
    },

    findGoodEl() {
      let el = mousedownPos.elementFromPoint();
      if (!el) {
        return null;
      }
      let isGoodEl = (el) => {
        if (el.nodeType != document.ELEMENT_NODE) {
          return false;
        }
        if (el.tagName == "IMG") {
          let rect = el.getBoundingClientRect();
          return rect.width >= this.minAutoImageWidth && rect.height >= this.minAutoImageHeight;
        }
        let display = window.getComputedStyle(el).display;
        if (['block', 'inline-block', 'table'].indexOf(display) != -1) {
          return true;
          // FIXME: not sure if this is useful:
          // let rect = el.getBoundingClientRect();
          // return rect.width <= this.maxAutoElementWidth && rect.height <= this.maxAutoElementHeight;
        }
        return false;
      };
      while (el) {
        if (isGoodEl(el)) {
          return el;
        }
        el = el.parentNode;
      }
      return null;
    },

    end() {
      mouseupNoAutoselect = false;
    }

  };

  stateHandlers.dragging = {

    start() {
      ui.iframe.useSelection();
      ui.Box.display(selectedPos);
    },

    mousemove(event) {
      selectedPos.x2 = util.truncateX(event.pageX);
      selectedPos.y2 = util.truncateY(event.pageY);
      scrollIfByEdge(event.pageX, event.pageY);
      ui.Box.display(selectedPos);
      ui.PixelDimensions.display(event.pageX, event.pageY, selectedPos.width, selectedPos.height);
    },

    mouseup(event) {
      selectedPos.x2 = util.truncateX(event.pageX);
      selectedPos.y2 = util.truncateY(event.pageY);
      ui.Box.display(selectedPos, standardDisplayCallbacks);
      sendEvent(
        "make-selection", "selection-drag",
        eventOptionsForBox({
          top: selectedPos.y1,
          bottom: selectedPos.y2,
          left: selectedPos.x1,
          right: selectedPos.x2
        }));
      setState("selected");
    },

    end() {
      ui.PixelDimensions.remove();
    }
  };

  stateHandlers.selected = {
    start() {
      ui.iframe.useSelection();
    },

    mousedown(event) {
      let target = event.target;
      if (target.tagName == "HTML") {
        // This happens when you click on the scrollbar
        return undefined;
      }
      let direction = ui.Box.draggerDirection(target);
      if (direction) {
        sendEvent("start-resize-selection", "handle");
        stateHandlers.resizing.startResize(event, direction);
      } else if (ui.Box.isSelection(target)) {
        sendEvent("start-move-selection", "selection");
        stateHandlers.resizing.startResize(event, "move");
      } else if (!ui.Box.isControl(target)) {
        mousedownPos = new Pos(event.pageX, event.pageY);
        setState("crosshairs");
      }
      event.preventDefault();
      return false;
    }
  };

  stateHandlers.resizing = {
    start() {
      ui.iframe.useSelection();
      selectedPos.sortCoords();
    },

    startResize(event, direction) {
      selectedPos.sortCoords();
      resizeDirection = direction;
      resizeStartPos = new Pos(event.pageX, event.pageY);
      resizeStartSelected = selectedPos.clone();
      resizeHasMoved = false;
      setState("resizing");
    },

    mousemove(event) {
      this._resize(event);
      return false;
    },

    mouseup(event) {
      this._resize(event);
      sendEvent("selection-resized");
      ui.Box.display(selectedPos, standardDisplayCallbacks);
      if (resizeHasMoved) {
        if (resizeDirection == "move") {
          let startPos = new Pos(resizeStartSelected.left, resizeStartSelected.top);
          let endPos = new Pos(selectedPos.left, selectedPos.top);
          sendEvent(
            "move-selection", "mouseup",
            eventOptionsForMove(startPos, endPos));
        } else {
          sendEvent(
            "resize-selection", "mouseup",
            eventOptionsForResize(resizeStartSelected, selectedPos));
        }
      } else if (resizeDirection == "move") {
        sendEvent("keep-resize-selection", "mouseup");
      } else {
        sendEvent("keep-move-selection", "mouseup");
      }
      setState("selected");
    },

    _resize(event) {
      let diffX = event.pageX - resizeStartPos.x;
      let diffY = event.pageY - resizeStartPos.y;
      let movement = movements[resizeDirection];
      if (movement[0]) {
        let moveX = movement[0];
        moveX = moveX == "*" ? ["x1", "x2"] : [moveX];
        for (let moveDir of moveX) {
          selectedPos[moveDir] =  util.truncateX(resizeStartSelected[moveDir] + diffX);
        }
      }
      if (movement[1]) {
        let moveY = movement[1];
        moveY = moveY == "*" ? ["y1", "y2"] : [moveY];
        for (let moveDir of moveY) {
          selectedPos[moveDir] = util.truncateY(resizeStartSelected[moveDir] + diffY);
        }
      }
      if (diffX || diffY) {
        resizeHasMoved = true;
      }
      scrollIfByEdge(event.pageX, event.pageY);
      ui.Box.display(selectedPos);
    },

    end() {
      resizeDirection = resizeStartPos = resizeStartSelected = null;
      selectedPos.sortCoords();
    }
  };

  stateHandlers.cancel = {
    start() {
      ui.iframe.hide();
      ui.Box.remove();
    }
  };

  let documentWidth = Math.max(
    document.body && document.body.clientWidth,
    document.documentElement.clientWidth,
    document.body && document.body.scrollWidth,
    document.documentElement.scrollWidth);
  let documentHeight = Math.max(
    document.body && document.body.clientHeight,
    document.documentElement.clientHeight,
    document.body && document.body.scrollHeight,
    document.documentElement.scrollHeight);

  function scrollIfByEdge(pageX, pageY) {
    let top = window.scrollY;
    let bottom = top + window.innerHeight;
    let left = window.scrollX;
    let right = left + window.innerWidth;
    if (pageY + SCROLL_BY_EDGE >= bottom && bottom < documentHeight) {
      window.scrollBy(0, SCROLL_BY_EDGE);
    } else if (pageY - SCROLL_BY_EDGE <= top) {
      window.scrollBy(0, -SCROLL_BY_EDGE);
    }
    if (pageX + SCROLL_BY_EDGE >= right && right < documentWidth) {
      window.scrollBy(SCROLL_BY_EDGE, 0);
    } else if (pageX - SCROLL_BY_EDGE <= left) {
      window.scrollBy(-SCROLL_BY_EDGE, 0);
    }
  }

  /** *********************************************
   * Selection communication
   */

   // If the slides module is loaded then we're supposed to onboard
  let shouldOnboard = typeof slides !== "undefined";

  exports.activate = function() {
    if (!document.body) {
      callBackground("abortNoDocumentBody", document.documentElement.tagName);
      selectorLoader.unloadModules();
      return;
    }
    if (isFrameset()) {
      callBackground("abortFrameset");
      selectorLoader.unloadModules();
      return;
    }
    addHandlers();
    if (shouldOnboard) {
      setState("onboarding");
    } else {
      setState("crosshairs");
    }
  }

  function isFrameset() {
    return document.body.tagName == "FRAMESET";
  }

  exports.deactivate = function() {
    try {
      setState("cancel");
      callBackground('closeSelector');
      selectorLoader.unloadModules();
    } catch (e) {
      log.error('Error in deactivate', e)
      // Sometimes this fires so late that the document isn't available
      // We don't care about the exception, so we swallow it here
    }
  };

  let unloadTime = 0;

  exports.unload = function() {
    // Note that ui.unload() will be called on its own
    unloadTime = Date.now();
    removeHandlers();
  };

  /** *********************************************
   * Event handlers
   */

  let primedDocumentHandlers = new Map();
  let registeredDocumentHandlers = []

  function addHandlers() {
    ["mouseup", "mousedown", "mousemove", "click"].forEach((eventName) => {
      let fn = watchFunction(assertIsTrusted((function(eventName, event) {
        if (typeof event.button == "number" && event.button !== 0) {
          // Not a left click
          return undefined;
        }
        if (event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) {
          // Modified click of key
          return undefined;
        }
        let state = getState();
        let handler = stateHandlers[state];
        if (handler[eventName]) {
          return handler[eventName](event);
        }
        return undefined;
      }).bind(null, eventName)));
      primedDocumentHandlers.set(eventName, fn);
    });
    primedDocumentHandlers.set("keyup", watchFunction(assertIsTrusted(keyupHandler)));
    window.addEventListener('beforeunload', beforeunloadHandler);
  }

  let mousedownSetOnDocument = false;

  function installHandlersOnDocument(docObj) {
    for (let [eventName, handler] of primedDocumentHandlers) {
      let watchHandler = watchFunction(handler);
      let useCapture = eventName !== "keyup";
      docObj.addEventListener(eventName, watchHandler, useCapture);
      registeredDocumentHandlers.push({name: eventName, doc: docObj, handler: watchHandler, useCapture});
    }
    if (!mousedownSetOnDocument) {
      let mousedownHandler = primedDocumentHandlers.get("mousedown");
      document.addEventListener("mousedown", mousedownHandler, true);
      registeredDocumentHandlers.push({name: "mousedown", doc: document, handler: mousedownHandler, useCapture: true});
      mousedownSetOnDocument = true;
    }
  }

  function beforeunloadHandler() {
    sendEvent("cancel-shot", "tab-load");
    exports.deactivate();
  }

  function keyupHandler(event) {
    if (event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) {
      // Modified
      return;
    }
    if ((event.key || event.code) === "Escape") {
      sendEvent("cancel-shot", "keyboard-escape");
      exports.deactivate();
    }
    if ((event.key || event.code) === "Enter") {
      if (getState.state === "selected") {
        sendEvent("save-shot", "keyboard-enter");
        shooter.takeShot("selection", selectedPos);
      }
    }
  }

  function removeHandlers() {
    window.removeEventListener("beforeunload", beforeunloadHandler);
    for (let {name, doc, handler, useCapture} of registeredDocumentHandlers) {
      doc.removeEventListener(name, handler, !!useCapture);
    }
    registeredDocumentHandlers = [];
  }

  catcher.watchFunction(exports.activate)();

  return exports;
})();

null;
PK
!<T9+webextension/selector/util.js"use strict";

this.util = (function() { // eslint-disable-line no-unused-vars
  let exports = {};

  /** Removes a node from its document, if it's a node and the node is attached to a parent */
  exports.removeNode = function(el) {
    if (el && el.parentNode) {
      el.remove();
    }
  };

  /** Truncates the X coordinate to the document size */
  exports.truncateX = function(x) {
    let max = Math.max(document.documentElement.clientWidth, document.body.clientWidth, document.documentElement.scrollWidth, document.body.scrollWidth);
    if (x < 0) {
      return 0;
    } else if (x > max) {
      return max;
    }
    return x;
  };

  /** Truncates the Y coordinate to the document size */
  exports.truncateY = function(y) {
    let max = Math.max(document.documentElement.clientHeight, document.body.clientHeight, document.documentElement.scrollHeight, document.body.scrollHeight);
    if (y < 0) {
      return 0;
    } else if (y > max) {
      return max;
    }
    return y;
  };

  // Pixels of wiggle the captured region gets in captureSelectedText:
  var CAPTURE_WIGGLE = 10;
  const ELEMENT_NODE = document.ELEMENT_NODE;

  exports.captureEnclosedText = function(box) {
    var scrollX = window.scrollX;
    var scrollY = window.scrollY;
    var text = [];
    function traverse(el) {
      var elBox = el.getBoundingClientRect();
      elBox = {
        top: elBox.top + scrollY,
        bottom: elBox.bottom + scrollY,
        left: elBox.left + scrollX,
        right: elBox.right + scrollX
      };
      if (elBox.bottom < box.top ||
          elBox.top > box.bottom ||
          elBox.right < box.left ||
          elBox.left > box.right) {
        // Totally outside of the box
        return;
      }
      if (elBox.bottom > box.bottom + CAPTURE_WIGGLE ||
          elBox.top < box.top - CAPTURE_WIGGLE ||
          elBox.right > box.right + CAPTURE_WIGGLE ||
          elBox.left < box.left - CAPTURE_WIGGLE) {
        // Partially outside the box
        for (var i = 0; i < el.childNodes.length; i++) {
          var child = el.childNodes[i];
          if (child.nodeType == ELEMENT_NODE) {
            traverse(child);
          }
        }
        return;
      }
      addText(el);
    }
    function addText(el) {
      let t;
      if (el.tagName == "IMG") {
        t = el.getAttribute("alt") || el.getAttribute("title");
      } else if (el.tagName == "A") {
        t = el.innerText;
        if (el.getAttribute("href") && !el.getAttribute("href").startsWith("#")) {
          t += " (" + el.href + ")";
        }
      } else {
        t = el.innerText;
      }
      if (t) {
        text.push(t);
      }
    }
    traverse(document.body);
    if (text.length) {
      let result = text.join("\n");
      result = result.replace(/^\s+/, "");
      result = result.replace(/\s+$/, "");
      result = result.replace(/[ \t]+\n/g, "\n");
      return result;
    }
    return null;
  };


  return exports;
})();
null;
PK
!<ϵ|webextension/sitehelper.js/* globals catcher, callBackground */
/** This is a content script added to all screenshots.firefox.com pages, and allows the site to
    communicate with the add-on */

"use strict";

this.sitehelper = (function() {

  catcher.registerHandler((errorObj) => {
    callBackground("reportError", errorObj);
  });


  function sendCustomEvent(name, detail) {
    if (typeof detail == "object") {
      // Note sending an object can lead to security problems, while a string
      // is safe to transfer:
      detail = JSON.stringify(detail);
    }
    document.dispatchEvent(new CustomEvent(name, {detail}));
  }

  document.addEventListener("delete-everything", catcher.watchFunction((event) => {
    // FIXME: reset some data in the add-on
  }, false));

  document.addEventListener("request-login", catcher.watchFunction((event) => {
    let shotId = event.detail;
    catcher.watchPromise(callBackground("getAuthInfo", shotId || null).then((info) => {
      sendCustomEvent("login-successful", {deviceId: info.deviceId, isOwner: info.isOwner});
    }));
  }));

  document.addEventListener("request-onboarding", catcher.watchFunction((event) => {
    callBackground("requestOnboarding");
  }));

  // Depending on the script loading order, the site might get the addon-present event,
  // but probably won't - instead the site will ask for that event after it has loaded
  document.addEventListener("request-addon-present", catcher.watchFunction(() => {
    sendCustomEvent("addon-present");
  }));

  sendCustomEvent("addon-present");

})();
null;
PK)

Anon7 - 2022
AnonSec Team